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