xref: /kernel/liteos_m/kernel/src/los_queue.c (revision 3d8536b4)
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
46LITE_OS_SEC_BSS LosQueueCB *g_allQueue = NULL ;
47LITE_OS_SEC_BSS LOS_DL_LIST g_freeQueueList;
48
49#if (LOSCFG_BASE_IPC_QUEUE_STATIC == 1)
50LITE_OS_SEC_BSS LosQueueCB *g_staticQueue = NULL ;
51LITE_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**************************************************************************/
61LITE_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
110static 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)
218LITE_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 *****************************************************************************/
244LITE_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
258static 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
280static 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
303static 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
363static 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
380UINT32 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
434QUEUE_END:
435    LOS_IntRestore(intSave);
436    return ret;
437}
438
439LITE_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
460LITE_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
477LITE_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
498LITE_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
515LITE_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
534LITE_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 *****************************************************************************/
558LITE_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
609END:
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 *****************************************************************************/
623LITE_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 *****************************************************************************/
672LITE_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
731QUEUE_END:
732    LOS_IntRestore(intSave);
733    return ret;
734}
735
736LITE_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
783QUEUE_END:
784    LOS_IntRestore(intSave);
785    return ret;
786}
787
788LosQueueCB *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