Abstract: This paper leads us to analyze the source code of QueueMail two interfaces of the queue module of hongmeng light kernel.
This article is shared by Huawei cloud community “Hongmeng light kernel M source code analysis series 13 (continued) Message queue QueueMail interface”, author: zhushy.
I have analyzed the source code of Queue and understood the operations of Queue initialization, Queue creation, deletion, Queue reading and writing. Queues also provide two interfaces, OsQueueMailAlloc and OsQueueMailFree. A queue can be associated with a static memory pool. If a task fails to obtain a block from the static memory pool, the task will be inserted into the queue’s blocked list. When other tasks free the memory, the task will be allocated the block.
Next, take a closer look at the source code for these two interfaces.
1. Queue structure definition
The queue control block is defined as LosQueueCB in kernel\include\los_queue.h. The source code of the queue control block is shown below. We need to take a look at the member variable memList. When a task fails to apply for a free memory block from the static memory pool associated with the queue, the task will be inserted into the memList memory block linked list, and then scheduled for task switching. When other tasks free free memory blocks to the static memory pool, the task applies for free memory blocks, removes the task from the memList memory blocking linked list, inserts it into the task ready queue, and triggers task scheduling.
typedef struct { UINT8 *queue; /**< UINT16 queueState; /**< UINT16 queueLen; /**< UINT16 queueSize; /**< message node size */ UINT16 queueID; /**< UINT16 queueHead; */ UINT16 queueTail; */ UINT16 readWriteableCnt[OS_READWRITE_LEN]; */ LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; */ LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /**< 2 dimensional bidirectional list array, block read and write tasks bidirectional list, 0: read list, 1: write list */ LOS_DL_LIST memList; /**< memory node bidirectional list */} LosQueueCB;Copy the code
2. Source code analysis of QueueMail interface
2.1 OsQueueMailAlloc interface
VOID*OsQueueMailAlloc(UINT32 queueID, VOID* mailPool, UINT32 timeOut) is used to apply for free memory from the static memory pool associated with the queue. QueueID is the number of a queue in use, *mailPool is the static memory pool address associated with the queue, and timeOut is the timeOut time. The value is [0,LOS_WAIT_FOREVER]. This interface function returns the requested memory address or NULL.
(2) Obtain queue control structure queueCB according to queue number, and then verify whether the queue is in use. (3) Call static memory allocation function LOS_MemboxAlloc to obtain free memory block, and then obtain the memory address is not NULL, return the memory block address, otherwise execute the subsequent code. (⑸) add the current task to queueCB->memList, and then trigger the task scheduling.
After other tasks call OsQueueMailFree to free the memory, the blocked task obtains the memory block, or exits the blocking list due to timeout, and the execution of the ⑹ statement begins. Where ⑺ indicates that the task does not obtain a memory block due to a timeout. The task switches to the END tag and returns the NULL memory address. ⑻ indicates that the client has obtained the memory block, empty the MSG of the task, and return the address of the obtained memory block.
LITE_OS_SEC_TEXT VOID *OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeOut) { VOID *mem = (VOID *)NULL; UINT32 intSave; LosQueueCB *queueCB = (LosQueueCB *)NULL; LosTaskCB *runTsk = (LosTaskCB *)NULL; ⑴ if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {return NULL; } if (mailPool == NULL) { return NULL; } if (timeOut ! = LOS_NO_WAIT) { if (OS_INT_ACTIVE) { return NULL; } } intSave = LOS_IntLock(); 2 queueCB = GET_QUEUE_HANDLE (queueID); if (queueCB->queueState == OS_QUEUE_UNUSED) { goto END; } ⑶ mem = LOS_MemboxAlloc(mailPool); if (mem == NULL) { if (timeOut == LOS_NO_WAIT) { goto END; * * * * * * * * * * * * * * * * * * * * * 5] OsSchedTaskWait (& queueCB - > memList, timeOut); LOS_IntRestore(intSave); LOS_Schedule(); [6] intSave = LOS_IntLock (); If (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {runTsk->taskStatus &= (~OS_TASK_STATUS_TIMEOUT); goto END; } else { /* When enters the current branch, means the current task already got a available membox, */ ⑻ mem = runTsk-> MSG; */ ⑻ mem = runTsk-> MSG; runTsk->msg = NULL; } } END: LOS_IntRestore(intSave); return mem; }Copy the code
2.2 OsQueueMailFree
UINT32OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem) QueueID is the number of a queue in use, *mailPool is the static memory pool address associated with the queue, and *mailMem is the address of the memory block to be freed. The return value type of this interface is an unsigned integer, indicating success or error code.
(1) Start to verify the parameters. (2) call the static memory free function LOS_MemboxFree to free the free memory block. If the free block fails, return an error code. (3) Obtain the queue control structure queueCB according to the queue number, and then check whether the queue is in use. Execute ⑷ if the queue’s memory blocking list is not empty and there are blocking tasks after successfully freeing memory. The first task control structure is retrieved from the blocking list at ⑸ and the interface OsSchedTaskWake is called to remove the task from the blocking list and add it to the task ready queue. If the request fails, an error code is returned. Otherwise, execute ⑺ to assign the obtained memory to the MSG member variable of the task control structure, and then trigger scheduling.
LITE_OS_SEC_TEXT UINT32 OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem) { VOID *mem = (VOID *)NULL; UINT32 intSave; LosQueueCB *queueCB = (LosQueueCB *)NULL; LosTaskCB *resumedTask = (LosTaskCB *)NULL; ⑴ if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT) {return LOS_ERRNO_QUEUE_MAIL_HANDLE_INVALID; } if (mailPool == NULL) { return LOS_ERRNO_QUEUE_MAIL_PTR_INVALID; } intSave = LOS_IntLock(); ⑵ if (LOS_MemboxFree(mailPool, mailMem)) {LOS_IntRestore(intSave); return LOS_ERRNO_QUEUE_MAIL_FREE_ERROR; } ⑶ queueCB = GET_QUEUE_HANDLE(queueID); if (queueCB->queueState == OS_QUEUE_UNUSED) { LOS_IntRestore(intSave); return LOS_ERRNO_QUEUE_NOT_CREATE; } (4) if (! LOS_ListEmpty(&queuECB ->memList)) {⑸ resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queuECB ->memList)); OsSchedTaskWake(resumedTask); [6] mem = LOS_MemboxAlloc (mailPool); if (mem == NULL) { LOS_IntRestore(intSave); return LOS_ERRNO_QUEUE_NO_MEMORY; } ⑺ resumedTask-> MSG = mem; LOS_IntRestore(intSave); LOS_Schedule(); } else { LOS_IntRestore(intSave); } return LOS_OK; }Copy the code
summary
This article leads us to analyze the source code of QueueMail two interfaces of the queue module of hongmeng light kernel. Thank you for reading, if you have any questions, suggestions, please leave a message to me, thank you.
Click to follow, the first time to learn about Huawei cloud fresh technology ~