Abstract: This article leads everyone to analyze the source code of the QueueMail two interfaces of the queue module of the Hongmeng light kernel.
This article is shared from Huawei Cloud Community " Light Kernel M Core Source Code Analysis Series 13 (Continued) Message Queue QueueMail Interface ", author: zhushy.
I have analyzed the source code of the queue before, and learned about the operations of queue initialization, queue creation, deletion, queue read and write, etc. The queue also provides two interfaces OsQueueMailAlloc and OsQueueMailFree. The queue can be associated with a static memory pool. When a task applies for a memory block from the static memory pool, if the application fails, the task will be inserted into the memory blocking list of the queue. When other tasks release the memory, the task will The memory block is allocated.
Next, look at the source code of these two interfaces in detail.
1. Queue structure definition
1.1 Queue structure definition
We recall the definition of the queue structure. The queue control block structure is defined as LosQueueCB in the file kernel\include\los_queue.h. The source code of the structure is as follows. You need to look at the member variable memList. When a task cannot apply for a free memory block from the static memory pool associated with the queue, the task will be inserted into the memList memory blocking list, then scheduled, and task switching is performed. When another task releases the free memory block to this static memory pool, the task applies for the free memory block, removes the task from the memList memory blocking list, inserts it into the task ready queue, and triggers task scheduling.
typedef struct {
UINT8 *queue; /**< 队列内存空间的指针 */
UINT16 queueState; /**< 队列的使用状态 */
UINT16 queueLen; /**< 队列长度,即消息数量 */
UINT16 queueSize; /**< 消息节点大小 */
UINT16 queueID; /**< 队列编号 */
UINT16 queueHead; /**< 消息头节点位置 */
UINT16 queueTail; /**< 消息尾节点位置 */
UINT16 readWriteableCnt[OS_READWRITE_LEN]; /**< 2维数组,可读、可写的消息数量, 0:可读, 1:可写 */
LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /**< 2维双向链表数组,阻塞读、写任务的双向链表, 0:读链表, 1:写链表 */
LOS_DL_LIST memList; /**< 内存节点双向链表 */
} LosQueueCB;
2. QueueMail interface source code analysis
2.1 OsQueueMailAlloc interface
We can use the function VOID OsQueueMailAlloc (UINT32 queueID, VOID mailPool, UINT32 timeOut) to apply for free memory from the static memory pool associated with the queue. Let's look at how to apply for memory by analyzing the source code. This function requires 3 parameters, queueID is the number of a queue in use, *mailPool is the address of the static memory pool associated with the queue, and timeOut is the timeout period, the value is [0,LOS_WAIT_FOREVER]. This interface function returns the requested memory address or NULL.
⑴ Start to verify the parameters, ⑵ get the queue control structure queueCB according to the queue number, and then verify whether the queue is in use. (3) Call the static memory allocation function LOS_MemboxAlloc to obtain a free memory block, and then the obtained memory address is not NULL, and the memory block address is returned, otherwise the subsequent code is executed. (4) Get the currently running task control structure, (5) add the current task to the memory blocking list queueCB->memList of the queue, and then trigger task scheduling.
After other tasks call OsQueueMailFree to release the memory, the above-mentioned blocked task obtains a memory block, or exits the blocking list due to timeout and is scheduled to run, then the statement ⑹ will be executed. ⑺ means that because of the timeout return, the task did not get the memory block, jump to the END tag, and return the NULL memory address. ⑻ indicates that the memory block is obtained, the msg of the task is empty, and the address of the obtained memory block is returned.
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();
⑵ 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;
}
⑷ runTsk = (LosTaskCB *)g_losTask.runTask;
⑸ OsSchedTaskWait(&queueCB->memList, timeOut);
LOS_IntRestore(intSave);
LOS_Schedule();
⑹ 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,
* so the runTsk->msg can not be NULL.
*/
⑻ mem = runTsk->msg;
runTsk->msg = NULL;
}
}
END:
LOS_IntRestore(intSave);
return mem;
}
2.2 OsQueueMailFree
We can use the function UINT32 OsQueueMailFree(UINT32 queueID, VOID mailPool, VOID mailMem) to release free memory to the static memory pool associated with the queue. Let’s analyze the source code to see how to release the memory. This function takes three parameters, queueID queue is used in a number of states, mailPool and static memory pool address is associated with the queue, mailMem indicates that the memory block address to be released. The return value type of this interface is an unsigned integer, which indicates success or error code.
⑴ Start to verify the parameters. (2) Call the static memory release function LOS_MemboxFree to release the free memory block. If the release fails, an error code is returned. (3) Obtain the queue control structure queueCB according to the queue number, and then check whether the queue is in use. After the memory is successfully released, if the memory blocking list of the queue is not empty and there are blocking tasks, then execute (4). (5) Obtain the first task control structure from the blocked list, and then call the interface OsSchedTaskWake to remove the task from the blocked list and add it to the task ready queue. ⑹ Apply for a memory block from the static memory pool, if the application fails, return an error code, otherwise execute ⑺, assign the requested memory to the msg member variable of the task control structure, and then trigger the 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;
}
⑷ if (!LOS_ListEmpty(&queueCB->memList)) {
⑸ resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->memList));
OsSchedTaskWake(resumedTask);
⑹ 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;
}
summary
This article led everyone to analyze the source code of the QueueMail two interfaces of the Queue Module of the Hongmeng Light Kernel. Thanks for reading. If you have any questions or suggestions, you can leave a message to me, thank you.
Click to follow and learn about Huawei Cloud's fresh technology for the first time~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。