1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_queue.h"
33 #include "securec.h"
34 #include "los_config.h"
35 #include "los_debug.h"
36 #include "los_hook.h"
37 #include "los_interrupt.h"
38 #include "los_membox.h"
39 #include "los_memory.h"
40 #include "los_sched.h"
41 #include <stdint.h>
42 
43 
44 #if (LOSCFG_BASE_IPC_QUEUE == 1)
45 
46 LITE_OS_SEC_BSS LosQueueCB *g_allQueue = NULL ;
47 LITE_OS_SEC_BSS LOS_DL_LIST g_freeQueueList;
48 
49 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
50 LITE_OS_SEC_BSS LosQueueCB *g_staticQueue = NULL ;
51 LITE_OS_SEC_BSS LOS_DL_LIST g_freeStaticQueueList;
52 #endif
53 
54 /**************************************************************************
55  Function    : OsQueueInit
56  Description : queue initial
57  Input       : None
58  Output      : None
59  Return      : LOS_OK on success or error code on failure
60 **************************************************************************/
OsQueueInitnull61 LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID)
62 {
63     LosQueueCB *queueNode = NULL;
64     UINT16 index;
65 
66 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
67     LosQueueCB *queueNodeStatic = NULL;
68 #endif
69 
70     if (OS_ALL_IPC_QUEUE_LIMIT == 0) {
71         return LOS_ERRNO_QUEUE_MAXNUM_ZERO;
72     }
73 
74     g_allQueue = (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB));
75     if (g_allQueue == NULL) {
76         return LOS_ERRNO_QUEUE_NO_MEMORY;
77     }
78 
79     (VOID)memset_s(g_allQueue, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB),
80                    0, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB));
81 
82     LOS_ListInit(&g_freeQueueList);
83     for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
84         queueNode = ((LosQueueCB *)g_allQueue) + index;
85         queueNode->queueID = index;
86         LOS_ListTailInsert(&g_freeQueueList, &queueNode->readWriteList[OS_QUEUE_WRITE]);
87     }
88 
89 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
90     g_staticQueue = (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0, LOSCFG_BASE_IPC_STATIC_QUEUE_LIMIT * sizeof(LosQueueCB));
91     if (g_staticQueue == NULL) {
92         return LOS_ERRNO_QUEUE_NO_MEMORY;
93     }
94 
95     (VOID)memset_s(g_staticQueue, LOSCFG_BASE_IPC_STATIC_QUEUE_LIMIT * sizeof(LosQueueCB),
96                    0, LOSCFG_BASE_IPC_STATIC_QUEUE_LIMIT * sizeof(LosQueueCB));
97 
98     LOS_ListInit(&g_freeStaticQueueList);
99     for (index = 0; index < LOSCFG_BASE_IPC_STATIC_QUEUE_LIMIT; index++) {
100         queueNodeStatic = ((LosQueueCB *)g_staticQueue) + index;
101         queueNodeStatic->queueID = index + LOSCFG_BASE_IPC_QUEUE_LIMIT;
102         LOS_ListTailInsert(&g_freeStaticQueueList, &queueNodeStatic->readWriteList[OS_QUEUE_WRITE]);
103     }
104 #endif
105 
106     return LOS_OK;
107 }
108 
109 
OsQueueCreate(const CHAR *queueName, UINT16 len, UINT32 *queueID, UINT8 *staticMem, UINT32 flags, UINT16 maxMsgSize)110 static UINT32 OsQueueCreate(const CHAR *queueName,
111                             UINT16 len,
112                             UINT32 *queueID,
113                             UINT8 *staticMem,
114                             UINT32 flags,
115                             UINT16 maxMsgSize)
116 {
117     LosQueueCB *queueCB = NULL;
118     UINT32 intSave;
119     LOS_DL_LIST *unusedQueue = NULL;
120     UINT8 *queue = NULL;
121     UINT16 msgSize;
122 
123     (VOID)flags;
124 
125     if (queueID == NULL) {
126         return LOS_ERRNO_QUEUE_CREAT_PTR_NULL;
127     }
128 
129     if (maxMsgSize > (OS_NULL_SHORT - sizeof(UINT32))) {
130         return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;
131     }
132 
133     if ((len == 0) || (maxMsgSize == 0)) {
134         return LOS_ERRNO_QUEUE_PARA_ISZERO;
135     }
136     msgSize = maxMsgSize + sizeof(UINT32);
137 
138     /* Memory allocation is time-consuming, to shorten the time of disable interrupt,
139        move the memory allocation to here. */
140     if ((UINT32_MAX / msgSize) < len) {
141         return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;
142     }
143 
144 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
145     if (staticMem != NULL) {
146         queue = staticMem;
147         intSave = LOS_IntLock();
148 
149         if (LOS_ListEmpty(&g_freeStaticQueueList)) {
150             LOS_IntRestore(intSave);
151             return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
152         }
153         unusedQueue = LOS_DL_LIST_FIRST(&(g_freeStaticQueueList));
154     } else {
155         queue = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, (UINT32)len * msgSize);
156         if (queue == NULL) {
157             return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
158         }
159 
160         intSave = LOS_IntLock();
161         if (LOS_ListEmpty(&g_freeQueueList)) {
162             LOS_IntRestore(intSave);
163             (VOID)LOS_MemFree(m_aucSysMem0, queue);
164             return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
165         }
166         unusedQueue = LOS_DL_LIST_FIRST(&(g_freeQueueList));
167     }
168 #else
169     queue = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, (UINT32)len * msgSize);
170     if (queue == NULL) {
171         return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
172     }
173 
174     intSave = LOS_IntLock();
175     if (LOS_ListEmpty(&g_freeQueueList)) {
176         LOS_IntRestore(intSave);
177         (VOID)LOS_MemFree(m_aucSysMem0, queue);
178         return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
179     }
180     unusedQueue = LOS_DL_LIST_FIRST(&(g_freeQueueList));
181 #endif
182 
183     LOS_ListDelete(unusedQueue);
184     queueCB = (GET_QUEUE_LIST(unusedQueue));
185     queueCB->queueName = (UINT8 *)queueName; // The name can be null
186     queueCB->queueLen = len;
187     queueCB->queueSize = msgSize;
188     queueCB->queue = queue;
189     queueCB->queueState = OS_QUEUE_INUSED;
190     queueCB->readWriteableCnt[OS_QUEUE_READ] = 0;
191     queueCB->readWriteableCnt[OS_QUEUE_WRITE] = len;
192     queueCB->queueHead = 0;
193     queueCB->queueTail = 0;
194     LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_READ]);
195     LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_WRITE]);
196     LOS_ListInit(&queueCB->memList);
197     LOS_IntRestore(intSave);
198 
199     *queueID = queueCB->queueID;
200 
201     OsHookCall(LOS_HOOK_TYPE_QUEUE_CREATE, queueCB);
202 
203     return LOS_OK;
204 }
205 
206 /*****************************************************************************
207  Function    : LOS_QueueCreateStatic
208  Description : Create a queue use static menory
209  Input       : queueName  --- Queue name, less than 4 characters
210              : len        --- Queue length
211              : queueMem   --- Queue static memory for data storage
212              : flags      --- Queue type, FIFO or PRIO
213              : maxMsgSize --- Maximum message size in byte
214  Output      : queueID    --- Queue ID
215  Return      : LOS_OK on success or error code on failure
216  *****************************************************************************/
217 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
LOS_QueueCreateStatic(const CHAR *queueName, UINT16 len, UINT32 *queueID, UINT8 *staticMem, UINT32 flags, UINT16 maxMsgSize)218 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreateStatic(const CHAR *queueName,
219                                                    UINT16 len,
220                                                    UINT32 *queueID,
221                                                    UINT8 *staticMem,
222                                                    UINT32 flags,
223                                                    UINT16 maxMsgSize)
224 {
225     UINT32 ret;
226 
227     (VOID)flags;
228 
229     ret = OsQueueCreate(queueName, len, queueID, staticMem, 0, maxMsgSize);
230     return ret;
231 }
232 #endif
233 
234 /*****************************************************************************
235  Function    : LOS_QueueCreate
236  Description : Create a queue
237  Input       : queueName  --- Queue name, less than 4 characters
238              : len        --- Queue length
239              : flags      --- Queue type, FIFO or PRIO
240              : maxMsgSize --- Maximum message size in byte
241  Output      : queueID    --- Queue ID
242  Return      : LOS_OK on success or error code on failure
243  *****************************************************************************/
LOS_QueueCreate(const CHAR *queueName, UINT16 len, UINT32 *queueID, UINT32 flags, UINT16 maxMsgSize)244 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(const CHAR *queueName,
245                                              UINT16 len,
246                                              UINT32 *queueID,
247                                              UINT32 flags,
248                                              UINT16 maxMsgSize)
249 {
250     UINT32 ret;
251 
252     (VOID)flags;
253 
254     ret = OsQueueCreate(queueName, len, queueID, NULL, 0, maxMsgSize);
255     return ret;
256 }
257 
OsQueueReadParameterCheck(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)258 static INLINE LITE_OS_SEC_TEXT UINT32 OsQueueReadParameterCheck(UINT32 queueID, VOID *bufferAddr,
259                                                                 UINT32 *bufferSize, UINT32 timeOut)
260 {
261     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
262         return LOS_ERRNO_QUEUE_INVALID;
263     }
264     if ((bufferAddr == NULL) || (bufferSize == NULL)) {
265         return LOS_ERRNO_QUEUE_READ_PTR_NULL;
266     }
267 
268     if (*bufferSize == 0) {
269         return LOS_ERRNO_QUEUE_READSIZE_ISZERO;
270     }
271 
272     if (timeOut != LOS_NO_WAIT) {
273         if (OS_INT_ACTIVE) {
274             return LOS_ERRNO_QUEUE_READ_IN_INTERRUPT;
275         }
276     }
277     return LOS_OK;
278 }
279 
OsQueueWriteParameterCheck(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)280 static INLINE LITE_OS_SEC_TEXT UINT32 OsQueueWriteParameterCheck(UINT32 queueID, VOID *bufferAddr,
281                                                                  UINT32 *bufferSize, UINT32 timeOut)
282 {
283     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
284         return LOS_ERRNO_QUEUE_INVALID;
285     }
286 
287     if (bufferAddr == NULL) {
288         return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
289     }
290 
291     if (*bufferSize == 0) {
292         return LOS_ERRNO_QUEUE_WRITESIZE_ISZERO;
293     }
294 
295     if (timeOut != LOS_NO_WAIT) {
296         if (OS_INT_ACTIVE) {
297             return LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT;
298         }
299     }
300     return LOS_OK;
301 }
302 
OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize)303 static INLINE VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType,
304                                                                 VOID *bufferAddr, UINT32 *bufferSize)
305 {
306     UINT8 *queueNode = NULL;
307     UINT32 msgDataSize;
308     UINT16 queuePosition;
309     errno_t rc;
310 
311     /* get the queue position */
312     switch (OS_QUEUE_OPERATE_GET(operateType)) {
313         case OS_QUEUE_READ_HEAD:
314             queuePosition = queueCB->queueHead;
315             ((queueCB->queueHead + 1) == queueCB->queueLen) ? (queueCB->queueHead = 0) : (queueCB->queueHead++);
316             break;
317 
318         case OS_QUEUE_WRITE_HEAD:
319             (queueCB->queueHead == 0) ? (queueCB->queueHead = (queueCB->queueLen - 1)) : (--queueCB->queueHead);
320             queuePosition = queueCB->queueHead;
321             break;
322 
323         case OS_QUEUE_WRITE_TAIL:
324             queuePosition = queueCB->queueTail;
325             ((queueCB->queueTail + 1) == queueCB->queueLen) ? (queueCB->queueTail = 0) : (queueCB->queueTail++);
326             break;
327 
328         default:
329             PRINT_ERR("invalid queue operate type!\n");
330             return;
331     }
332 
333     queueNode = &(queueCB->queue[(queuePosition * (queueCB->queueSize))]);
334 
335     if (OS_QUEUE_IS_POINT(operateType)) {
336         if (OS_QUEUE_IS_READ(operateType)) {
337             *(UINTPTR *)bufferAddr = *(UINTPTR *)(VOID *)queueNode;
338         } else {
339             *(UINTPTR *)(VOID *)queueNode = *(UINTPTR *)bufferAddr;
340         }
341     } else {
342         if (OS_QUEUE_IS_READ(operateType)) {
343             msgDataSize = *((UINT32 *)(UINTPTR)((queueNode + queueCB->queueSize) - sizeof(UINT32)));
344             msgDataSize = (*bufferSize < msgDataSize) ? *bufferSize : msgDataSize;
345             rc = memcpy_s((VOID *)bufferAddr, *bufferSize, (VOID *)queueNode, msgDataSize);
346             if (rc != EOK) {
347                 PRINT_ERR("%s[%d] memcpy failed, error type = %u\n", __FUNCTION__, __LINE__, rc);
348                 return;
349             }
350 
351             *bufferSize = msgDataSize;
352         } else {
353             *((UINT32 *)(UINTPTR)((queueNode + queueCB->queueSize) - sizeof(UINT32))) = *bufferSize;
354             rc = memcpy_s((VOID *)queueNode, queueCB->queueSize, (VOID *)bufferAddr, *bufferSize);
355             if (rc != EOK) {
356                 PRINT_ERR("%s[%d] memcpy failed, error type = %u\n", __FUNCTION__, __LINE__, rc);
357                 return;
358             }
359         }
360     }
361 }
362 
OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 operateType, const UINT32 *bufferSize)363 static INLINE UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 operateType, const UINT32 *bufferSize)
364 {
365     if (queueCB->queueState == OS_QUEUE_UNUSED) {
366         return LOS_ERRNO_QUEUE_NOT_CREATE;
367     }
368 
369     if (OS_QUEUE_IS_WRITE(operateType) && (*bufferSize > (queueCB->queueSize - sizeof(UINT32)))) {
370         return LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG;
371     }
372 
373     if (*bufferSize >= SECUREC_MEM_MAX_LEN) {
374         return LOS_ERRNO_QUEUE_BUFFER_SIZE_TOO_BIG;
375     }
376 
377     return LOS_OK;
378 }
379 
OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)380 UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)
381 {
382     LosQueueCB *queueCB = NULL;
383     LosTaskCB *resumedTask = NULL;
384     UINT32 ret;
385     UINT32 readWrite = OS_QUEUE_READ_WRITE_GET(operateType);
386     UINT32 readWriteTmp = !readWrite;
387 
388     UINT32 intSave = LOS_IntLock();
389 
390     queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
391     ret = OsQueueOperateParamCheck(queueCB, operateType, bufferSize);
392     if (ret != LOS_OK) {
393         goto QUEUE_END;
394     }
395 
396     if (queueCB->readWriteableCnt[readWrite] == 0) {
397         if (timeOut == LOS_NO_WAIT) {
398             ret = OS_QUEUE_IS_READ(operateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;
399             goto QUEUE_END;
400         }
401 
402         if (g_losTaskLock) {
403             ret = LOS_ERRNO_QUEUE_PEND_IN_LOCK;
404             goto QUEUE_END;
405         }
406 
407         LosTaskCB *runTsk = (LosTaskCB *)g_losTask.runTask;
408         OsSchedTaskWait(&queueCB->readWriteList[readWrite], timeOut);
409         LOS_IntRestore(intSave);
410         LOS_Schedule();
411 
412         intSave = LOS_IntLock();
413         if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
414             runTsk->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
415             ret = LOS_ERRNO_QUEUE_TIMEOUT;
416             goto QUEUE_END;
417         }
418     } else {
419         queueCB->readWriteableCnt[readWrite]--;
420     }
421 
422     OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);
423 
424     if (!LOS_ListEmpty(&queueCB->readWriteList[readWriteTmp])) {
425         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[readWriteTmp]));
426         OsSchedTaskWake(resumedTask);
427         LOS_IntRestore(intSave);
428         LOS_Schedule();
429         return LOS_OK;
430     } else {
431         queueCB->readWriteableCnt[readWriteTmp]++;
432     }
433 
434 QUEUE_END:
435     LOS_IntRestore(intSave);
436     return ret;
437 }
438 
LOS_QueueReadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)439 LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID,
440                                           VOID *bufferAddr,
441                                           UINT32 *bufferSize,
442                                           UINT32 timeOut)
443 {
444     UINT32 ret;
445     UINT32 operateType;
446 
447     ret = OsQueueReadParameterCheck(queueID, bufferAddr, bufferSize, timeOut);
448     if (ret != LOS_OK) {
449         return ret;
450     }
451 
452     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD, OS_QUEUE_NOT_POINT);
453 
454     OsHookCall(LOS_HOOK_TYPE_QUEUE_READ_COPY, (LosQueueCB *)GET_QUEUE_HANDLE(queueID),
455                operateType, *bufferSize, timeOut);
456 
457     return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeOut);
458 }
459 
LOS_QueueWriteHeadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)460 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueID,
461                                                VOID *bufferAddr,
462                                                UINT32 bufferSize,
463                                                UINT32 timeOut)
464 {
465     UINT32 ret;
466     UINT32 operateType;
467 
468     ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeOut);
469     if (ret != LOS_OK) {
470         return ret;
471     }
472 
473     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_HEAD, OS_QUEUE_NOT_POINT);
474     return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
475 }
476 
LOS_QueueWriteCopy(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)477 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueID,
478                                            VOID *bufferAddr,
479                                            UINT32 bufferSize,
480                                            UINT32 timeOut)
481 {
482     UINT32 ret;
483     UINT32 operateType;
484 
485     ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeOut);
486     if (ret != LOS_OK) {
487         return ret;
488     }
489 
490     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL, OS_QUEUE_NOT_POINT);
491 
492     OsHookCall(LOS_HOOK_TYPE_QUEUE_WRITE_COPY, (LosQueueCB *)GET_QUEUE_HANDLE(queueID),
493                operateType, bufferSize, timeOut);
494 
495     return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
496 }
497 
LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)498 LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)
499 {
500     UINT32 ret;
501     UINT32 operateType;
502 
503     ret = OsQueueReadParameterCheck(queueID, bufferAddr, &bufferSize, timeOut);
504     if (ret != LOS_OK) {
505         return ret;
506     }
507 
508     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD, OS_QUEUE_POINT);
509 
510     OsHookCall(LOS_HOOK_TYPE_QUEUE_READ, (LosQueueCB *)GET_QUEUE_HANDLE(queueID), operateType, bufferSize, timeOut);
511 
512     return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
513 }
514 
LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)515 LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)
516 {
517     UINT32 ret;
518     UINT32 operateType;
519     UINT32 size = sizeof(UINT32 *);
520     (VOID)bufferSize;
521 
522     ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &size, timeOut);
523     if (ret != LOS_OK) {
524         return ret;
525     }
526 
527     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL, OS_QUEUE_POINT);
528 
529     OsHookCall(LOS_HOOK_TYPE_QUEUE_WRITE, (LosQueueCB *)GET_QUEUE_HANDLE(queueID), operateType, size, timeOut);
530 
531     return OsQueueOperate(queueID, operateType, &bufferAddr, &size, timeOut);
532 }
533 
LOS_QueueWriteHead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)534 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueID,
535                                            VOID *bufferAddr,
536                                            UINT32 bufferSize,
537                                            UINT32 timeOut)
538 {
539     UINT32 size = sizeof(UINT32 *);
540     (VOID)bufferSize;
541 
542     if (bufferAddr == NULL) {
543         return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
544     }
545 
546     return LOS_QueueWriteHeadCopy(queueID, &bufferAddr, size, timeOut);
547 }
548 
549 /*****************************************************************************
550  Function    : OsQueueMailAlloc
551  Description : Mail allocate memory
552  Input       : queueID   --- QueueID
553              : mailPool  --- MailPool
554              : timeOut   --- TimeOut
555  Output      : None
556  Return      : mem:pointer if success otherwise NULL
557  *****************************************************************************/
OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeOut)558 LITE_OS_SEC_TEXT VOID *OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeOut)
559 {
560     VOID *mem = (VOID *)NULL;
561     UINT32 intSave;
562     LosQueueCB *queueCB = (LosQueueCB *)NULL;
563     LosTaskCB *runTsk = (LosTaskCB *)NULL;
564 
565     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
566         return NULL;
567     }
568 
569     if (mailPool == NULL) {
570         return NULL;
571     }
572 
573     if (timeOut != LOS_NO_WAIT) {
574         if (OS_INT_ACTIVE) {
575             return NULL;
576         }
577     }
578 
579     intSave = LOS_IntLock();
580     queueCB = GET_QUEUE_HANDLE(queueID);
581     if (queueCB->queueState == OS_QUEUE_UNUSED) {
582         goto END;
583     }
584 
585     mem = LOS_MemboxAlloc(mailPool);
586     if (mem == NULL) {
587         if (timeOut == LOS_NO_WAIT) {
588             goto END;
589         }
590 
591         runTsk = (LosTaskCB *)g_losTask.runTask;
592         OsSchedTaskWait(&queueCB->memList, timeOut);
593         LOS_IntRestore(intSave);
594         LOS_Schedule();
595 
596         intSave = LOS_IntLock();
597         if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
598             runTsk->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
599             goto END;
600         } else {
601             /* When enters the current branch, means the current task already got an available membox,
602              * so the runTsk->msg can not be NULL.
603              */
604             mem = runTsk->msg;
605             runTsk->msg = NULL;
606         }
607     }
608 
609 END:
610     LOS_IntRestore(intSave);
611     return mem;
612 }
613 
614 /*****************************************************************************
615  Function    : OsQueueMailFree
616  Description : Mail free memory
617  Input       : queueID   --- QueueID
618              : mailPool  --- MailPool
619              : mailMem   --- MailMem
620  Output      : None
621  Return      : LOS_OK on success or error code on failure
622  *****************************************************************************/
OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem)623 LITE_OS_SEC_TEXT UINT32 OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem)
624 {
625     UINT32 intSave;
626     LosQueueCB *queueCB = (LosQueueCB *)NULL;
627     LosTaskCB *resumedTask = (LosTaskCB *)NULL;
628 
629     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
630         return LOS_ERRNO_QUEUE_MAIL_HANDLE_INVALID;
631     }
632 
633     if (mailPool == NULL) {
634         return LOS_ERRNO_QUEUE_MAIL_PTR_INVALID;
635     }
636 
637     intSave = LOS_IntLock();
638     queueCB = GET_QUEUE_HANDLE(queueID);
639     if (queueCB->queueState == OS_QUEUE_UNUSED) {
640         LOS_IntRestore(intSave);
641         return LOS_ERRNO_QUEUE_NOT_CREATE;
642     }
643 
644     if (!LOS_ListEmpty(&queueCB->memList)) {
645         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->memList));
646         /* When enter this branch, it means the resumed task can
647          * get an available mailMem.
648          */
649         resumedTask->msg = mailMem;
650         OsSchedTaskWake(resumedTask);
651         LOS_IntRestore(intSave);
652         LOS_Schedule();
653     } else {
654         /* No task waiting for the mailMem, so free it. */
655         if (LOS_MemboxFree(mailPool, mailMem)) {
656             LOS_IntRestore(intSave);
657             return LOS_ERRNO_QUEUE_MAIL_FREE_ERROR;
658         }
659         LOS_IntRestore(intSave);
660     }
661 
662     return LOS_OK;
663 }
664 
665 /*****************************************************************************
666  Function    : LOS_QueueDelete
667  Description : Delete a queue
668  Input       : queueID   --- QueueID
669  Output      : None
670  Return      : LOS_OK on success or error code on failure
671  *****************************************************************************/
LOS_QueueDelete(UINT32 queueID)672 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID)
673 {
674     LosQueueCB *queueCB = NULL;
675     UINT8 *queue = NULL;
676     UINT32 intSave;
677     UINT32 ret;
678 
679     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
680         return LOS_ERRNO_QUEUE_NOT_FOUND;
681     }
682 
683     intSave = LOS_IntLock();
684     queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
685     if (queueCB->queueState == OS_QUEUE_UNUSED) {
686         ret = LOS_ERRNO_QUEUE_NOT_CREATE;
687         goto QUEUE_END;
688     }
689 
690     if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_READ])) {
691         ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
692         goto QUEUE_END;
693     }
694 
695     if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_WRITE])) {
696         ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
697         goto QUEUE_END;
698     }
699 
700     if (!LOS_ListEmpty(&queueCB->memList)) {
701         ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
702         goto QUEUE_END;
703     }
704 
705     if ((queueCB->readWriteableCnt[OS_QUEUE_WRITE] + queueCB->readWriteableCnt[OS_QUEUE_READ]) !=
706         queueCB->queueLen) {
707         ret = LOS_ERRNO_QUEUE_IN_TSKWRITE;
708         goto QUEUE_END;
709     }
710 
711     queue = queueCB->queue;
712     queueCB->queue = (UINT8 *)NULL;
713     queueCB->queueName = (UINT8 *)NULL;
714     queueCB->queueState = OS_QUEUE_UNUSED;
715 
716 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
717     if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT && queueID < OS_ALL_IPC_QUEUE_LIMIT) {
718         LOS_ListAdd(&g_freeStaticQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
719         LOS_IntRestore(intSave);
720         return LOS_OK;
721     }
722 #endif
723     LOS_ListAdd(&g_freeQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
724     LOS_IntRestore(intSave);
725 
726     OsHookCall(LOS_HOOK_TYPE_QUEUE_DELETE, queueCB);
727 
728     ret = LOS_MemFree(m_aucSysMem0, (VOID *)queue);
729     return ret;
730 
731 QUEUE_END:
732     LOS_IntRestore(intSave);
733     return ret;
734 }
735 
LOS_QueueInfoGet(UINT32 queueID, QUEUE_INFO_S *queueInfo)736 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_QueueInfoGet(UINT32 queueID, QUEUE_INFO_S *queueInfo)
737 {
738     UINT32 intSave;
739     UINT32 ret = LOS_OK;
740     LosQueueCB *queueCB = NULL;
741     LosTaskCB *tskCB = NULL;
742 
743     if (queueInfo == NULL) {
744         return LOS_ERRNO_QUEUE_PTR_NULL;
745     }
746 
747     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
748         return LOS_ERRNO_QUEUE_INVALID;
749     }
750 
751     (VOID)memset_s((VOID *)queueInfo, sizeof(QUEUE_INFO_S), 0, sizeof(QUEUE_INFO_S));
752     intSave = LOS_IntLock();
753 
754     queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
755     if (queueCB->queueState == OS_QUEUE_UNUSED) {
756         ret = LOS_ERRNO_QUEUE_NOT_CREATE;
757         goto QUEUE_END;
758     }
759 
760     queueInfo->queueID = queueID;
761     queueInfo->queueLen = queueCB->queueLen;
762     queueInfo->queueSize = queueCB->queueSize;
763     queueInfo->queueHead = queueCB->queueHead;
764     queueInfo->queueTail = queueCB->queueTail;
765     queueInfo->readableCnt = queueCB->readWriteableCnt[OS_QUEUE_READ];
766     queueInfo->writableCnt = queueCB->readWriteableCnt[OS_QUEUE_WRITE];
767 
768     LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_READ], LosTaskCB, pendList) {
769         queueInfo->waitReadTask[OS_WAIT_TASK_ID_TO_ARRAY_IDX(tskCB->taskID)] |=
770             (1 << (tskCB->taskID & OS_WAIT_TASK_ARRAY_ELEMENT_MASK));
771     }
772 
773     LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_WRITE], LosTaskCB, pendList) {
774         queueInfo->waitWriteTask[OS_WAIT_TASK_ID_TO_ARRAY_IDX(tskCB->taskID)] |=
775             (1 << (tskCB->taskID & OS_WAIT_TASK_ARRAY_ELEMENT_MASK));
776     }
777 
778     LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->memList, LosTaskCB, pendList) {
779         queueInfo->waitMemTask[OS_WAIT_TASK_ID_TO_ARRAY_IDX(tskCB->taskID)] |=
780             (1 << (tskCB->taskID & OS_WAIT_TASK_ARRAY_ELEMENT_MASK));
781     }
782 
783 QUEUE_END:
784     LOS_IntRestore(intSave);
785     return ret;
786 }
787 
OsGetQueueHandle(UINT32 queueID)788 LosQueueCB *OsGetQueueHandle(UINT32 queueID)
789 {
790 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
791     if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT && queueID < OS_ALL_IPC_QUEUE_LIMIT) {
792         return (((LosQueueCB *)g_staticQueue) + (queueID - LOSCFG_BASE_IPC_QUEUE_LIMIT));
793     }
794 #endif
795 
796     return (((LosQueueCB *)g_allQueue) + (queueID));
797 }
798 
799 #endif /* (LOSCFG_BASE_IPC_QUEUE == 1) */
800 
801