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