OpenHarmony开发者论坛

标题: 如何在信息量中实现令牌获取的插队? [打印本页]

作者: desert    时间: 2024-4-4 21:32
标题: 如何在信息量中实现令牌获取的插队?
比如说在某些特殊情况下,需要让几个特定的线程优先获取令牌(tokens),应该如何实现?
作者: dragon    时间: 2024-4-5 13:27
标题: 如何在信息量中实现令牌获取的插队?
对于OH轻量系统来说,CMSIS-RTOS2的osSemaphoreAcquire()函数是这样实现的:

  1. osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
  2. {
  3.     UINT32 uwRet;

  4.     if (semaphore_id == NULL) {
  5.         return osErrorParameter;
  6.     }

  7.     if (OS_INT_ACTIVE && (timeout != LOS_NO_WAIT)) {
  8.         return osErrorISR;
  9.     }

  10.     uwRet = LOS_SemPend(((LosSemCB *)semaphore_id)->semID, timeout);
  11.     if (uwRet == LOS_OK) {
  12.         return osOK;
  13.     } else if (uwRet == LOS_ERRNO_SEM_TIMEOUT) {
  14.         return osErrorTimeout;
  15.     } else if (uwRet == LOS_ERRNO_SEM_INVALID) {
  16.         return osErrorParameter;
  17.     } else if (uwRet == LOS_ERRNO_SEM_PEND_INTERR) {
  18.         return osErrorISR;
  19.     } else {
  20.         return osErrorResource;
  21.     }
  22. }
复制代码

其中的关键函数LOS_SemPend()定义如下:
  1. /*****************************************************************************
  2. Function     : LOS_SemPend
  3. Description  : Specified semaphore P operation
  4. Input        : semHandle --------- semaphore operation handle
  5.               : timeout   --------- waitting time
  6. Output       : None
  7. Return       : LOS_OK on success or error code on failure
  8. *****************************************************************************/
  9. LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
  10. {
  11.     UINT32 intSave;
  12.     LosSemCB *semPended = NULL;
  13.     UINT32 retErr;
  14.     LosTaskCB *runningTask = NULL;

  15.     if (semHandle >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
  16.         OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
  17.     }

  18.     semPended = GET_SEM(semHandle);
  19.     intSave = LOS_IntLock();

  20.     retErr = OsSemValidCheck(semPended);
  21.     if (retErr) {
  22.         goto ERROR_SEM_PEND;
  23.     }

  24.     if (semPended->semCount > 0) {
  25.         semPended->semCount--;
  26.         LOS_IntRestore(intSave);
  27.         return LOS_OK;
  28.     }

  29.     if (!timeout) {
  30.         retErr = LOS_ERRNO_SEM_UNAVAILABLE;
  31.         goto ERROR_SEM_PEND;
  32.     }

  33.     runningTask = (LosTaskCB *)g_losTask.runTask;
  34.     runningTask->taskSem = (VOID *)semPended;
  35.     OsTaskWait(&semPended->semList, OS_TASK_STATUS_PEND, timeout);
  36.     LOS_IntRestore(intSave);
  37.     LOS_Schedule();

  38.     if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
  39.         intSave = LOS_IntLock();
  40.         runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
  41.         retErr = LOS_ERRNO_SEM_TIMEOUT;
  42.         goto ERROR_SEM_PEND;
  43.     }

  44.     return LOS_OK;

  45. ERROR_SEM_PEND:
  46.     LOS_IntRestore(intSave);
  47.     OS_RETURN_ERROR(retErr);
  48. }
复制代码

其中调用了OsTaskWait:
  1. /**************************************************************************
  2. Function    : OsTaskWait
  3. Description : pend the running task in a list
  4. Input       : pendingList   -- The pending list
  5.                taskStatus    -- The status need to be converted to
  6.                timeout       -- Expiry time
  7. Output      : None
  8. Return      : None
  9. **************************************************************************/
  10. VOID OsTaskWait(LOS_DL_LIST *pendingList, UINT32 taskStatus, UINT32 timeout)
  11. {
  12.     LosTaskCB *runTask = NULL;
  13.     LOS_DL_LIST *pendObj = NULL;

  14.     runTask = g_losTask.runTask;
  15.     OsPriqueueDequeue(&runTask->pendList);
  16.     runTask->taskStatus &= (~OS_TASK_STATUS_READY);
  17.     pendObj = &runTask->pendList;
  18.     runTask->taskStatus |= taskStatus;
  19.     LOS_ListTailInsert(pendingList, pendObj);
  20.     if (timeout != LOS_WAIT_FOREVER) {
  21.         runTask->taskStatus |= OS_TASK_STATUS_TIMEOUT;
  22.         OsTaskAdd2TimerList((LosTaskCB *)runTask, timeout);
  23.     }
  24. }
复制代码

可以看到是排到队尾的。线程调度的时候看线程优先级。





欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5