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