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