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 **************************************************************************/
OsQueueInitnull61 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 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)
LOS_QueueCreateStatic(const CHAR *queueName, UINT16 len, UINT32 *queueID, UINT8 *staticMem, UINT32 flags, UINT16 maxMsgSize)218 LITE_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 *****************************************************************************/
LOS_QueueCreate(const CHAR *queueName, UINT16 len, UINT32 *queueID, UINT32 flags, UINT16 maxMsgSize)244 LITE_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
OsQueueReadParameterCheck(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)258 static 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
OsQueueWriteParameterCheck(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)280 static 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
OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize)303 static 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
OsQueueOperateParamCheck(const LosQueueCB *queueCB, UINT32 operateType, const UINT32 *bufferSize)363 static 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
OsQueueOperate(UINT32 queueID, UINT32 operateType, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)380 UINT32 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
434 QUEUE_END:
435 LOS_IntRestore(intSave);
436 return ret;
437 }
438
LOS_QueueReadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeOut)439 LITE_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
LOS_QueueWriteHeadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)460 LITE_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
LOS_QueueWriteCopy(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)477 LITE_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
LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)498 LITE_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
LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)515 LITE_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
LOS_QueueWriteHead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)534 LITE_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 *****************************************************************************/
OsQueueMailAlloc(UINT32 queueID, VOID *mailPool, UINT32 timeOut)558 LITE_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
609 END:
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 *****************************************************************************/
OsQueueMailFree(UINT32 queueID, VOID *mailPool, VOID *mailMem)623 LITE_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 *****************************************************************************/
LOS_QueueDelete(UINT32 queueID)672 LITE_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
731 QUEUE_END:
732 LOS_IntRestore(intSave);
733 return ret;
734 }
735
LOS_QueueInfoGet(UINT32 queueID, QUEUE_INFO_S *queueInfo)736 LITE_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
783 QUEUE_END:
784 LOS_IntRestore(intSave);
785 return ret;
786 }
787
OsGetQueueHandle(UINT32 queueID)788 LosQueueCB *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