Abstract: This article will introduce the important data structures in the source code of the Hongmeng light kernel M core to the reader, and the task is based on the priority-based ready queue Priority Queue.
This article is shared from Huawei Cloud Community " Light Kernel M Core Source Code Analysis Series Three Data Structures - Task Ready Queue ", the original author: zhushy.
This article will introduce the important data structures in the source code of the Hongmeng light kernel M core to the reader, and the task is based on the priority-based ready queue Priority Queue.
During the explanation, it will combine the related drawings of data structures to cultivate the readers' plane imagination ability of data structures, and help to better learn and understand the usage of these data structures. The source code involved in this article, taking the OpenHarmony LiteOS-M kernel as an example, can be obtained from the open source site https://gitee.com/openharmony/kernel_liteos_m .
1 task ready queue
In the task scheduling module, the ready queue is an important data structure. After the task is created, it enters the ready state and is placed in the ready queue. In Hongmeng Light Kernel, the ready queue is a doubly circular linked list array, each array element is a linked list, and tasks of the same priority are placed in the same linked list.
The task-ready queue Priority Queue is mainly for internal use and is not involved in business development by users, so no external interface is provided. Doubly circular linked list arrays can more easily support task scheduling based on priority. The core code of the task ready queue is in the kernel\src\los_task.c file.
1.1 Definition of Task Ready Queue
The main variables related to the task ready queue are defined in the kernel\src\los_task.c file.
The source code is as follows:
⑴ LITE_OS_SEC_BSS LOS_DL_LIST *g_losPriorityQueueList = NULL;
⑵ static LITE_OS_SEC_BSS UINT32 g_priqueueBitmap = 0;
⑶ #define PRIQUEUE_PRIOR0_BIT (UINT32)0x80000000
⑷ #define OS_PRIORITY_QUEUE_PRIORITYNUM 32
Among them, (1) represents the task ready queue, which is an array of doubly linked lists. When the array is initialized later, the length of the array will be set to OS_PRIORITY_QUEUE_PRIORITYNUM defined at (4); (2) it represents the priority bitmap, which identifies the ready tasks that have been mounted in the task ready queue. The priority; ⑶ indicates the bit with priority 0; ⑷ indicates the number of priorities supported by the task ready queue is 32, so the value range of the Hongmeng light kernel priority is 0-31, the smaller the value, the higher the priority .
The relationship between the bits of the priority bitmap g_priqueueBitmap and the priority is bit=31-priority, the priority array g_losPriorityQueueList[priority] contains OS_PRIORITY_QUEUE_PRIORITYNUM array elements, each array element is a doubly linked list, the same priority is ready All tasks in the state are mounted in a doubly linked list of corresponding priorities.
The schematic diagram is as follows:
2 Task ready queue operations
2.1 Initialize the task ready queue
The task ready queue initialization function is OsPriQueueInit(), which is called in the system initialization phase. The calling path is: main.c:main() --> kernel\src\los_init.c:LOS_KernelInit() --> kernel\src\los_task. c:OsTaskInit() --> OsPriqueueInit().
The source code is as follows:
STATIC UINT32 OsPriqueueInit(VOID)
{
UINT32 priority;
⑴ UINT32 size = OS_PRIORITY_QUEUE_PRIORITYNUM * sizeof(LOS_DL_LIST);
g_losPriorityQueueList = (LOS_DL_LIST *)LOS_MemAlloc(m_aucSysMem0, size);
if (g_losPriorityQueueList == NULL) {
return LOS_NOK;
}
for (priority = 0; priority < OS_PRIORITY_QUEUE_PRIORITYNUM; ++priority) {
⑵ LOS_ListInit(&g_losPriorityQueueList[priority]);
}
retu
rn LOS_OK;
}
(1) Calculate the memory size required by the ready queue array, and then apply for memory for the task ready queue. The memory occupied is the memory size required by the OS_PRIORITY_QUEUE_PRIORITYNUM doubly linked list. The memory will not be released during operation and is the system resident memory. The code at 2 initializes each array element as a doubly circular linked list.
2.2 Task ready queue insertion
The task ready queue insertion function is OsPriqueueEnqueue(), which inserts the task in the ready state into the tail of the task ready queue. In the task ready queue, the task at the head of the queue is called first, and the task at the end of the queue is called last.
The source code is as follows:
STATIC VOID OsPriqueueEnqueue(LOS_DL_LIST *priqueueItem, UINT32 priority)
{
⑴ if (LOS_ListEmpty(&g_losPriorityQueueList[priority])) {
⑵ g_priqueueBitmap |= (PRIQUEUE_PRIOR0_BIT >> priority);
}
⑶ LOS_ListTailInsert(&g_losPriorityQueueList[priority], priqueueItem);
}
At 1, first judge whether the task ready queue of the specified priority priority is empty. If it is empty, update the priority bitmap at 2, and set the 31st-priority bit to 1. (3) The task in the ready state is inserted into the tail of the task ready queue for queuing.
2.3 Delete from task ready queue
The function to remove from the task ready queue is OsPriqueueDequeue(). In scenarios such as task deletion, suspend blocking state, priority adjustment, etc., this function needs to be called to delete the task from the task ready queue.
The source code is as follows:
STATIC VOID OsPriqueueDequeue(LOS_DL_LIST *priqueueItem)
{
LosTaskCB *runningTask = NULL;
⑴ LOS_ListDelete(priqueueItem);
⑵ runningTask = LOS_DL_LIST_ENTRY(priqueueItem, LosTaskCB, pendList);
⑶ if (LOS_ListEmpty(&g_losPriorityQueueList[runningTask->priority])) {
⑷ g_priqueueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> runningTask->priority);
}
}
(1) Delete the task from the task ready queue. (2) Obtain the task control block information of the deleted task to obtain the priority of the task. After the task is deleted, the queue may become an empty queue, so the code at (3) determines whether the task ready queue is empty. If it is empty, the code at (4) needs to be executed to update the priority bitmap and set the 31st-prioritybit bit to 0.
2.4 Get the highest priority node in the queue
The function to get the highest priority linked list node in the task ready queue is OsPriQueueTop().
The source code is as follows:
STATIC LOS_DL_LIST *OsPriqueueTop(VOID)
{
UINT32 priority;
⑴ if (g_priqueueBitmap != 0) {
⑵ priority = CLZ(g_priqueueBitmap);
⑶ return LOS_DL_LIST_FIRST(&g_losPriorityQueueList[priority]);
}
return (LOS_DL_LIST *)NULL;
}
(1) Judging whether the priority bitmap g_priqueueBitmap is 0, if it is 0, it returns NULL directly, indicating that there is no task in the ready state in the task ready queue. (2) Calculate the number of bits whose high-order bit is 0 when g_priqueueBitmap is expressed in binary, and its value is the priority of the task. The priority obtained by this method is the highest of all priorities in the task-ready queue. Then (3) obtains the first linked list node from the priority queue &g_losPriorityQueueList[priority], and obtains the task with the highest priority in the task ready queue.
2.5 Get the number of ready tasks with the specified priority
The function to get the number of tasks with the specified priority in the task ready queue is OsPriqueueSize().
The source code is as follows:
STATIC UINT32 OsPriqueueSize(UINT32 priority)
{
UINT32 itemCnt = 0;
LOS_DL_LIST *curPQNode = (LOS_DL_LIST *)NULL;
⑴ LOS_DL_LIST_FOR_EACH(curPQNode, &g_losPriorityQueueList[priority]) {
⑵ ++itemCnt;
}
return itemCnt;
}
(1) The code at 1 uses the for loop defined by the macro LOS_DL_LIST_FOR_EACH to traverse the doubly linked list of the specified priority priority. If a new node is obtained, it means that there is a ready task under this priority, and then execute the code at 2. Add 1 to the count, and return The result is how many tasks are ready under the given priority.
summary
Mastering the important data structure of the Priority Queue of the Harmony Light Kernel will lay the foundation for further study and analysis of the source code of the Harmony Light Kernel, and make subsequent learning easier. More sharing articles will be released in the future, please look forward to it. You are also welcome to share your experience in learning and using the Light Kernel. If you have any questions or suggestions, you can leave a message to us: 161f12046dce3e https://gitee.com/openharmony /kernel_liteos_m/issues . light kernel code warehouse more easily, it is recommended to visit 161f12046dce41 https://gitee.com/openharmony/kernel_liteos_m , follow Watch, like Star, and Fork to your account, thank you.
Click to follow and learn about Huawei Cloud's new technologies for the first time~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。