• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 **************************************************************************/
OsQueueInit(VOID)61 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     (void)staticMem;
170 
171     queue = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, (UINT32)len * msgSize);
172     if (queue == NULL) {
173         return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
174     }
175 
176     intSave = LOS_IntLock();
177     if (LOS_ListEmpty(&g_freeQueueList)) {
178         LOS_IntRestore(intSave);
179         (VOID)LOS_MemFree(m_aucSysMem0, queue);
180         return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
181     }
182     unusedQueue = LOS_DL_LIST_FIRST(&(g_freeQueueList));
183 #endif
184 
185     LOS_ListDelete(unusedQueue);
186     queueCB = (GET_QUEUE_LIST(unusedQueue));
187     queueCB->queueName = (UINT8 *)queueName; // The name can be null
188     queueCB->queueLen = len;
189     queueCB->queueSize = msgSize;
190     queueCB->queue = queue;
191     queueCB->queueState = OS_QUEUE_INUSED;
192     queueCB->readWriteableCnt[OS_QUEUE_READ] = 0;
193     queueCB->readWriteableCnt[OS_QUEUE_WRITE] = len;
194     queueCB->queueHead = 0;
195     queueCB->queueTail = 0;
196     LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_READ]);
197     LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_WRITE]);
198     LOS_ListInit(&queueCB->memList);
199     LOS_IntRestore(intSave);
200 
201     *queueID = queueCB->queueID;
202 
203     OsHookCall(LOS_HOOK_TYPE_QUEUE_CREATE, queueCB);
204 
205     return LOS_OK;
206 }
207 
208 /*****************************************************************************
209  Function    : LOS_QueueCreateStatic
210  Description : Create a queue use static menory
211  Input       : queueName  --- Queue name, less than 4 characters
212              : len        --- Queue length
213              : queueMem   --- Queue static memory for data storage
214              : flags      --- Queue type, FIFO or PRIO
215              : maxMsgSize --- Maximum message size in byte
216  Output      : queueID    --- Queue ID
217  Return      : LOS_OK on success or error code on failure
218  *****************************************************************************/
219 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
LOS_QueueCreateStatic(const CHAR * queueName,UINT16 len,UINT32 * queueID,UINT8 * staticMem,UINT32 flags,UINT16 maxMsgSize)220 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreateStatic(const CHAR *queueName,
221                                                    UINT16 len,
222                                                    UINT32 *queueID,
223                                                    UINT8 *staticMem,
224                                                    UINT32 flags,
225                                                    UINT16 maxMsgSize)
226 {
227     UINT32 ret;
228 
229     (VOID)flags;
230 
231     ret = OsQueueCreate(queueName, len, queueID, staticMem, 0, maxMsgSize);
232     return ret;
233 }
234 #endif
235 
236 /*****************************************************************************
237  Function    : LOS_QueueCreate
238  Description : Create a queue
239  Input       : queueName  --- Queue name, less than 4 characters
240              : len        --- Queue length
241              : flags      --- Queue type, FIFO or PRIO
242              : maxMsgSize --- Maximum message size in byte
243  Output      : queueID    --- Queue ID
244  Return      : LOS_OK on success or error code on failure
245  *****************************************************************************/
LOS_QueueCreate(const CHAR * queueName,UINT16 len,UINT32 * queueID,UINT32 flags,UINT16 maxMsgSize)246 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(const CHAR *queueName,
247                                              UINT16 len,
248                                              UINT32 *queueID,
249                                              UINT32 flags,
250                                              UINT16 maxMsgSize)
251 {
252     UINT32 ret;
253 
254     (VOID)flags;
255 
256     ret = OsQueueCreate(queueName, len, queueID, NULL, 0, maxMsgSize);
257     return ret;
258 }
259 
OsQueueReadParameterCheck(UINT32 queueID,VOID * bufferAddr,UINT32 * bufferSize,UINT32 timeOut)260 static INLINE LITE_OS_SEC_TEXT UINT32 OsQueueReadParameterCheck(UINT32 queueID, VOID *bufferAddr,
261                                                                 UINT32 *bufferSize, UINT32 timeOut)
262 {
263     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
264         return LOS_ERRNO_QUEUE_INVALID;
265     }
266     if ((bufferAddr == NULL) || (bufferSize == NULL)) {
267         return LOS_ERRNO_QUEUE_READ_PTR_NULL;
268     }
269 
270     if (*bufferSize == 0) {
271         return LOS_ERRNO_QUEUE_READSIZE_ISZERO;
272     }
273 
274     if (timeOut != LOS_NO_WAIT) {
275         if (OS_INT_ACTIVE) {
276             return LOS_ERRNO_QUEUE_READ_IN_INTERRUPT;
277         }
278     }
279     return LOS_OK;
280 }
281 
OsQueueWriteParameterCheck(UINT32 queueID,VOID * bufferAddr,UINT32 * bufferSize,UINT32 timeOut)282 static INLINE LITE_OS_SEC_TEXT UINT32 OsQueueWriteParameterCheck(UINT32 queueID, VOID *bufferAddr,
283                                                                  UINT32 *bufferSize, UINT32 timeOut)
284 {
285     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
286         return LOS_ERRNO_QUEUE_INVALID;
287     }
288 
289     if (bufferAddr == NULL) {
290         return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
291     }
292 
293     if (*bufferSize == 0) {
294         return LOS_ERRNO_QUEUE_WRITESIZE_ISZERO;
295     }
296 
297     if (timeOut != LOS_NO_WAIT) {
298         if (OS_INT_ACTIVE) {
299             return LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT;
300         }
301     }
302     return LOS_OK;
303 }
304 
OsQueueBufferOperate(LosQueueCB * queueCB,UINT32 operateType,VOID * bufferAddr,UINT32 * bufferSize)305 static INLINE VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType,
306                                                                 VOID *bufferAddr, UINT32 *bufferSize)
307 {
308     UINT8 *queueNode = NULL;
309     UINT32 msgDataSize;
310     UINT16 queuePosition;
311     errno_t rc;
312 
313     /* get the queue position */
314     switch (OS_QUEUE_OPERATE_GET(operateType)) {
315         case OS_QUEUE_READ_HEAD:
316             queuePosition = queueCB->queueHead;
317             ((queueCB->queueHead + 1) == queueCB->queueLen) ? (queueCB->queueHead = 0) : (queueCB->queueHead++);
318             break;
319 
320         case OS_QUEUE_WRITE_HEAD:
321             (queueCB->queueHead == 0) ? (queueCB->queueHead = (queueCB->queueLen - 1)) : (--queueCB->queueHead);
322             queuePosition = queueCB->queueHead;
323             break;
324 
325         case OS_QUEUE_WRITE_TAIL:
326             queuePosition = queueCB->queueTail;
327             ((queueCB->queueTail + 1) == queueCB->queueLen) ? (queueCB->queueTail = 0) : (queueCB->queueTail++);
328             break;
329 
330         default:
331             PRINT_ERR("invalid queue operate type!\n");
332             return;
333     }
334 
335     queueNode = &(queueCB->queue[(queuePosition * (queueCB->queueSize))]);
336 
337     if (OS_QUEUE_IS_POINT(operateType)) {
338         if (OS_QUEUE_IS_READ(operateType)) {
339             *(UINTPTR *)bufferAddr = *(UINTPTR *)(VOID *)queueNode;
340         } else {
341             *(UINTPTR *)(VOID *)queueNode = *(UINTPTR *)bufferAddr;
342         }
343     } else {
344         if (OS_QUEUE_IS_READ(operateType)) {
345             msgDataSize = *((UINT32 *)(UINTPTR)((queueNode + queueCB->queueSize) - sizeof(UINT32)));
346             msgDataSize = (*bufferSize < msgDataSize) ? *bufferSize : msgDataSize;
347             rc = memcpy_s((VOID *)bufferAddr, *bufferSize, (VOID *)queueNode, msgDataSize);
348             if (rc != EOK) {
349                 PRINT_ERR("%s[%d] memcpy failed, error type = %u\n", __FUNCTION__, __LINE__, rc);
350                 return;
351             }
352 
353             *bufferSize = msgDataSize;
354         } else {
355             *((UINT32 *)(UINTPTR)((queueNode + queueCB->queueSize) - sizeof(UINT32))) = *bufferSize;
356             rc = memcpy_s((VOID *)queueNode, queueCB->queueSize, (VOID *)bufferAddr, *bufferSize);
357             if (rc != EOK) {
358                 PRINT_ERR("%s[%d] memcpy failed, error type = %u\n", __FUNCTION__, __LINE__, rc);
359                 return;
360             }
361         }
362     }
363 }
364 
OsQueueOperateParamCheck(const LosQueueCB * queueCB,UINT32 operateType,const UINT32 * bufferSize)365 static INLINE UINT32 OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 operateType, const UINT32 *bufferSize)
366 {
367     if (queueCB->queueState == OS_QUEUE_UNUSED) {
368         return LOS_ERRNO_QUEUE_NOT_CREATE;
369     }
370 
371     if (OS_QUEUE_IS_WRITE(operateType) && (*bufferSize > (queueCB->queueSize - sizeof(UINT32)))) {
372         return LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG;
373     }
374 
375     if (*bufferSize >= SECUREC_MEM_MAX_LEN) {
376         return LOS_ERRNO_QUEUE_BUFFER_SIZE_TOO_BIG;
377     }
378 
379     return LOS_OK;
380 }
381 
OsQueueOperate(UINT32 queueID,UINT32 operateType,VOID * bufferAddr,UINT32 * bufferSize,UINT32 timeOut)382 UINT32 OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)
383 {
384     LosQueueCB *queueCB = NULL;
385     LosTaskCB *resumedTask = NULL;
386     UINT32 ret;
387     UINT32 readWrite = OS_QUEUE_READ_WRITE_GET(operateType);
388     UINT32 readWriteTmp = !readWrite;
389 
390     UINT32 intSave = LOS_IntLock();
391 
392     queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
393     ret = OsQueueOperateParamCheck(queueCB, operateType, bufferSize);
394     if (ret != LOS_OK) {
395         goto QUEUE_END;
396     }
397 
398     if (queueCB->readWriteableCnt[readWrite] == 0) {
399         if (timeOut == LOS_NO_WAIT) {
400             ret = OS_QUEUE_IS_READ(operateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;
401             goto QUEUE_END;
402         }
403 
404         if (g_losTaskLock) {
405             ret = LOS_ERRNO_QUEUE_PEND_IN_LOCK;
406             goto QUEUE_END;
407         }
408 
409         LosTaskCB *runTsk = (LosTaskCB *)g_losTask.runTask;
410         OsSchedTaskWait(&queueCB->readWriteList[readWrite], timeOut);
411         LOS_IntRestore(intSave);
412         LOS_Schedule();
413 
414         intSave = LOS_IntLock();
415         if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
416             runTsk->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
417             ret = LOS_ERRNO_QUEUE_TIMEOUT;
418             goto QUEUE_END;
419         }
420     } else {
421         queueCB->readWriteableCnt[readWrite]--;
422     }
423 
424     OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);
425 
426     if (!LOS_ListEmpty(&queueCB->readWriteList[readWriteTmp])) {
427         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->readWriteList[readWriteTmp]));
428         OsSchedTaskWake(resumedTask);
429         LOS_IntRestore(intSave);
430         LOS_Schedule();
431         return LOS_OK;
432     } else {
433         queueCB->readWriteableCnt[readWriteTmp]++;
434     }
435 
436 QUEUE_END:
437     LOS_IntRestore(intSave);
438     return ret;
439 }
440 
LOS_QueueReadCopy(UINT32 queueID,VOID * bufferAddr,UINT32 * bufferSize,UINT32 timeOut)441 LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID,
442                                           VOID *bufferAddr,
443                                           UINT32 *bufferSize,
444                                           UINT32 timeOut)
445 {
446     UINT32 ret;
447     UINT32 operateType;
448 
449     ret = OsQueueReadParameterCheck(queueID, bufferAddr, bufferSize, timeOut);
450     if (ret != LOS_OK) {
451         return ret;
452     }
453 
454     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD, OS_QUEUE_NOT_POINT);
455 
456     OsHookCall(LOS_HOOK_TYPE_QUEUE_READ_COPY, (LosQueueCB *)GET_QUEUE_HANDLE(queueID),
457                operateType, *bufferSize, timeOut);
458 
459     return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeOut);
460 }
461 
LOS_QueueWriteHeadCopy(UINT32 queueID,VOID * bufferAddr,UINT32 bufferSize,UINT32 timeOut)462 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueID,
463                                                VOID *bufferAddr,
464                                                UINT32 bufferSize,
465                                                UINT32 timeOut)
466 {
467     UINT32 ret;
468     UINT32 operateType;
469 
470     ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeOut);
471     if (ret != LOS_OK) {
472         return ret;
473     }
474 
475     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_HEAD, OS_QUEUE_NOT_POINT);
476     return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
477 }
478 
LOS_QueueWriteCopy(UINT32 queueID,VOID * bufferAddr,UINT32 bufferSize,UINT32 timeOut)479 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueID,
480                                            VOID *bufferAddr,
481                                            UINT32 bufferSize,
482                                            UINT32 timeOut)
483 {
484     UINT32 ret;
485     UINT32 operateType;
486 
487     ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &bufferSize, timeOut);
488     if (ret != LOS_OK) {
489         return ret;
490     }
491 
492     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL, OS_QUEUE_NOT_POINT);
493 
494     OsHookCall(LOS_HOOK_TYPE_QUEUE_WRITE_COPY, (LosQueueCB *)GET_QUEUE_HANDLE(queueID),
495                operateType, bufferSize, timeOut);
496 
497     return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
498 }
499 
LOS_QueueRead(UINT32 queueID,VOID * bufferAddr,UINT32 bufferSize,UINT32 timeOut)500 LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)
501 {
502     UINT32 ret;
503     UINT32 operateType;
504 
505     ret = OsQueueReadParameterCheck(queueID, bufferAddr, &bufferSize, timeOut);
506     if (ret != LOS_OK) {
507         return ret;
508     }
509 
510     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD, OS_QUEUE_POINT);
511 
512     OsHookCall(LOS_HOOK_TYPE_QUEUE_READ, (LosQueueCB *)GET_QUEUE_HANDLE(queueID), operateType, bufferSize, timeOut);
513 
514     return OsQueueOperate(queueID, operateType, bufferAddr, &bufferSize, timeOut);
515 }
516 
LOS_QueueWrite(UINT32 queueID,VOID * bufferAddr,UINT32 bufferSize,UINT32 timeOut)517 LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)
518 {
519     UINT32 ret;
520     UINT32 operateType;
521     UINT32 size = sizeof(UINT32 *);
522     (VOID)bufferSize;
523 
524     ret = OsQueueWriteParameterCheck(queueID, bufferAddr, &size, timeOut);
525     if (ret != LOS_OK) {
526         return ret;
527     }
528 
529     operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL, OS_QUEUE_POINT);
530 
531     OsHookCall(LOS_HOOK_TYPE_QUEUE_WRITE, (LosQueueCB *)GET_QUEUE_HANDLE(queueID), operateType, size, timeOut);
532 
533     return OsQueueOperate(queueID, operateType, &bufferAddr, &size, timeOut);
534 }
535 
LOS_QueueWriteHead(UINT32 queueID,VOID * bufferAddr,UINT32 bufferSize,UINT32 timeOut)536 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHead(UINT32 queueID,
537                                            VOID *bufferAddr,
538                                            UINT32 bufferSize,
539                                            UINT32 timeOut)
540 {
541     UINT32 size = sizeof(UINT32 *);
542     (VOID)bufferSize;
543 
544     if (bufferAddr == NULL) {
545         return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
546     }
547 
548     return LOS_QueueWriteHeadCopy(queueID, &bufferAddr, size, timeOut);
549 }
550 
551 /*****************************************************************************
552  Function    : OsQueueMailAlloc
553  Description : Mail allocate memory
554  Input       : queueID   --- QueueID
555              : mailPool  --- MailPool
556              : timeOut   --- TimeOut
557  Output      : None
558  Return      : mem:pointer if success otherwise NULL
559  *****************************************************************************/
OsQueueMailAlloc(UINT32 queueID,VOID * mailPool,UINT32 timeOut)560 LITE_OS_SEC_TEXT VOID *OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeOut)
561 {
562     VOID *mem = (VOID *)NULL;
563     UINT32 intSave;
564     LosQueueCB *queueCB = (LosQueueCB *)NULL;
565     LosTaskCB *runTsk = (LosTaskCB *)NULL;
566 
567     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
568         return NULL;
569     }
570 
571     if (mailPool == NULL) {
572         return NULL;
573     }
574 
575     if (timeOut != LOS_NO_WAIT) {
576         if (OS_INT_ACTIVE) {
577             return NULL;
578         }
579     }
580 
581     intSave = LOS_IntLock();
582     queueCB = GET_QUEUE_HANDLE(queueID);
583     if (queueCB->queueState == OS_QUEUE_UNUSED) {
584         goto END;
585     }
586 
587     mem = LOS_MemboxAlloc(mailPool);
588     if (mem == NULL) {
589         if (timeOut == LOS_NO_WAIT) {
590             goto END;
591         }
592 
593         runTsk = (LosTaskCB *)g_losTask.runTask;
594         OsSchedTaskWait(&queueCB->memList, timeOut);
595         LOS_IntRestore(intSave);
596         LOS_Schedule();
597 
598         intSave = LOS_IntLock();
599         if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {
600             runTsk->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
601             goto END;
602         } else {
603             /* When enters the current branch, means the current task already got an available membox,
604              * so the runTsk->msg can not be NULL.
605              */
606             mem = runTsk->msg;
607             runTsk->msg = NULL;
608         }
609     }
610 
611 END:
612     LOS_IntRestore(intSave);
613     return mem;
614 }
615 
616 /*****************************************************************************
617  Function    : OsQueueMailFree
618  Description : Mail free memory
619  Input       : queueID   --- QueueID
620              : mailPool  --- MailPool
621              : mailMem   --- MailMem
622  Output      : None
623  Return      : LOS_OK on success or error code on failure
624  *****************************************************************************/
OsQueueMailFree(UINT32 queueID,VOID * mailPool,VOID * mailMem)625 LITE_OS_SEC_TEXT UINT32 OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem)
626 {
627     UINT32 intSave;
628     LosQueueCB *queueCB = (LosQueueCB *)NULL;
629     LosTaskCB *resumedTask = (LosTaskCB *)NULL;
630 
631     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
632         return LOS_ERRNO_QUEUE_MAIL_HANDLE_INVALID;
633     }
634 
635     if (mailPool == NULL) {
636         return LOS_ERRNO_QUEUE_MAIL_PTR_INVALID;
637     }
638 
639     intSave = LOS_IntLock();
640     queueCB = GET_QUEUE_HANDLE(queueID);
641     if (queueCB->queueState == OS_QUEUE_UNUSED) {
642         LOS_IntRestore(intSave);
643         return LOS_ERRNO_QUEUE_NOT_CREATE;
644     }
645 
646     if (!LOS_ListEmpty(&queueCB->memList)) {
647         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&queueCB->memList));
648         /* When enter this branch, it means the resumed task can
649          * get an available mailMem.
650          */
651         resumedTask->msg = mailMem;
652         OsSchedTaskWake(resumedTask);
653         LOS_IntRestore(intSave);
654         LOS_Schedule();
655     } else {
656         /* No task waiting for the mailMem, so free it. */
657         if (LOS_MemboxFree(mailPool, mailMem)) {
658             LOS_IntRestore(intSave);
659             return LOS_ERRNO_QUEUE_MAIL_FREE_ERROR;
660         }
661         LOS_IntRestore(intSave);
662     }
663 
664     return LOS_OK;
665 }
666 
667 /*****************************************************************************
668  Function    : LOS_QueueDelete
669  Description : Delete a queue
670  Input       : queueID   --- QueueID
671  Output      : None
672  Return      : LOS_OK on success or error code on failure
673  *****************************************************************************/
LOS_QueueDelete(UINT32 queueID)674 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID)
675 {
676     LosQueueCB *queueCB = NULL;
677     UINT8 *queue = NULL;
678     UINT32 intSave;
679     UINT32 ret;
680 
681     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
682         return LOS_ERRNO_QUEUE_NOT_FOUND;
683     }
684 
685     intSave = LOS_IntLock();
686     queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
687     if (queueCB->queueState == OS_QUEUE_UNUSED) {
688         ret = LOS_ERRNO_QUEUE_NOT_CREATE;
689         goto QUEUE_END;
690     }
691 
692     if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_READ])) {
693         ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
694         goto QUEUE_END;
695     }
696 
697     if (!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_WRITE])) {
698         ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
699         goto QUEUE_END;
700     }
701 
702     if (!LOS_ListEmpty(&queueCB->memList)) {
703         ret = LOS_ERRNO_QUEUE_IN_TSKUSE;
704         goto QUEUE_END;
705     }
706 
707     if ((queueCB->readWriteableCnt[OS_QUEUE_WRITE] + queueCB->readWriteableCnt[OS_QUEUE_READ]) !=
708         queueCB->queueLen) {
709         ret = LOS_ERRNO_QUEUE_IN_TSKWRITE;
710         goto QUEUE_END;
711     }
712 
713     queue = queueCB->queue;
714     queueCB->queue = (UINT8 *)NULL;
715     queueCB->queueName = (UINT8 *)NULL;
716     queueCB->queueState = OS_QUEUE_UNUSED;
717 
718 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
719     if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT && queueID < OS_ALL_IPC_QUEUE_LIMIT) {
720         LOS_ListAdd(&g_freeStaticQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
721         LOS_IntRestore(intSave);
722         return LOS_OK;
723     }
724 #endif
725     LOS_ListAdd(&g_freeQueueList, &queueCB->readWriteList[OS_QUEUE_WRITE]);
726     LOS_IntRestore(intSave);
727 
728     OsHookCall(LOS_HOOK_TYPE_QUEUE_DELETE, queueCB);
729 
730     ret = LOS_MemFree(m_aucSysMem0, (VOID *)queue);
731     return ret;
732 
733 QUEUE_END:
734     LOS_IntRestore(intSave);
735     return ret;
736 }
737 
LOS_QueueInfoGet(UINT32 queueID,QUEUE_INFO_S * queueInfo)738 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_QueueInfoGet(UINT32 queueID, QUEUE_INFO_S *queueInfo)
739 {
740     UINT32 intSave;
741     UINT32 ret = LOS_OK;
742     LosQueueCB *queueCB = NULL;
743     LosTaskCB *tskCB = NULL;
744 
745     if (queueInfo == NULL) {
746         return LOS_ERRNO_QUEUE_PTR_NULL;
747     }
748 
749     if (queueID >= OS_ALL_IPC_QUEUE_LIMIT) {
750         return LOS_ERRNO_QUEUE_INVALID;
751     }
752 
753     (VOID)memset_s((VOID *)queueInfo, sizeof(QUEUE_INFO_S), 0, sizeof(QUEUE_INFO_S));
754     intSave = LOS_IntLock();
755 
756     queueCB = (LosQueueCB *)GET_QUEUE_HANDLE(queueID);
757     if (queueCB->queueState == OS_QUEUE_UNUSED) {
758         ret = LOS_ERRNO_QUEUE_NOT_CREATE;
759         goto QUEUE_END;
760     }
761 
762     queueInfo->queueID = queueID;
763     queueInfo->queueLen = queueCB->queueLen;
764     queueInfo->queueSize = queueCB->queueSize;
765     queueInfo->queueHead = queueCB->queueHead;
766     queueInfo->queueTail = queueCB->queueTail;
767     queueInfo->readableCnt = queueCB->readWriteableCnt[OS_QUEUE_READ];
768     queueInfo->writableCnt = queueCB->readWriteableCnt[OS_QUEUE_WRITE];
769 
770     LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_READ], LosTaskCB, pendList) {
771         queueInfo->waitReadTask[OS_WAIT_TASK_ID_TO_ARRAY_IDX(tskCB->taskID)] |=
772             (1 << (tskCB->taskID & OS_WAIT_TASK_ARRAY_ELEMENT_MASK));
773     }
774 
775     LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->readWriteList[OS_QUEUE_WRITE], LosTaskCB, pendList) {
776         queueInfo->waitWriteTask[OS_WAIT_TASK_ID_TO_ARRAY_IDX(tskCB->taskID)] |=
777             (1 << (tskCB->taskID & OS_WAIT_TASK_ARRAY_ELEMENT_MASK));
778     }
779 
780     LOS_DL_LIST_FOR_EACH_ENTRY(tskCB, &queueCB->memList, LosTaskCB, pendList) {
781         queueInfo->waitMemTask[OS_WAIT_TASK_ID_TO_ARRAY_IDX(tskCB->taskID)] |=
782             (1 << (tskCB->taskID & OS_WAIT_TASK_ARRAY_ELEMENT_MASK));
783     }
784 
785 QUEUE_END:
786     LOS_IntRestore(intSave);
787     return ret;
788 }
789 
OsGetQueueHandle(UINT32 queueID)790 LosQueueCB *OsGetQueueHandle(UINT32 queueID)
791 {
792 #if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
793     if (queueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT && queueID < OS_ALL_IPC_QUEUE_LIMIT) {
794         return (((LosQueueCB *)g_staticQueue) + (queueID - LOSCFG_BASE_IPC_QUEUE_LIMIT));
795     }
796 #endif
797 
798     return (((LosQueueCB *)g_allQueue) + (queueID));
799 }
800 
801 #endif /* (LOSCFG_BASE_IPC_QUEUE == 1) */
802 
803