任務掛起函數OSTaskSuspend()
無條件掛起一個任務,它必須和任務恢複函數OSTaskResume()
成對出現。任務一旦被掛起,被掛起的任務就只能通過其它任務調用OSTaskResume()
函數來恢復。
任務掛起函數
OSTaskSuspend()
源碼如下,主要流程:- 判斷要掛起的任務是否爲當前運行的任務。
- 取消要掛起任務的就緒狀態並在任務控制塊中記錄,
ptcb->OSTCBStat |=OS_STAT_SUSPEND;
。 - 如果要掛起的任務是當前運行的任務則執行一次任務調度。
INT8U OSTaskSuspend (INT8U prio)
{
BOOLEAN self;
OS_TCB *ptcb;
INT8U y;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to suspend idle task */
return (OS_ERR_TASK_SUSPEND_IDLE);
}
if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if suspend SELF */
prio = OSTCBCur->OSTCBPrio;
self = OS_TRUE;
} else if (prio == OSTCBCur->OSTCBPrio) { /* See if suspending self */
self = OS_TRUE;
} else {
self = OS_FALSE; /* No suspending another task */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_SUSPEND_PRIO);
}
if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
y = ptcb->OSTCBY;
OSRdyTbl[y] &= ~ptcb->OSTCBBitX; /* Make task not ready */
if (OSRdyTbl[y] == 0) {
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is 'SUSPENDED' */
OS_EXIT_CRITICAL();
if (self == OS_TRUE) { /* Context switch only if SELF */
OS_Sched(); /* Find new highest priority task */
}
return (OS_ERR_NONE);
}
- 任務恢複函數
OSTaskResume()
源碼如下,主要流程:
- 判斷待恢復的任務是否是一個已掛起的任務,是則繼續,否則返回。
- 在任務控制塊中清除掛起標誌
ptcb->OSTCBStat &= ~(INT8U)OS_STAT_SUSPEND;
。 - 判斷任務是否處於就緒狀態
if (ptcb->OSTCBStat == OS_STAT_RDY)
&& 等待時間爲0ptcb->OSTCBDly == 0
,如果是則在任務就緒表中標記該任務並且執行一次任務調度。
INT8U OSTaskResume (INT8U prio)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO) { /* Make sure task priority is valid */
return (OS_ERR_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_RESUME_PRIO);
}
if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended */
ptcb->OSTCBStat &= ~(INT8U)OS_STAT_SUSPEND; /* Remove suspension */
if (ptcb->OSTCBStat == OS_STAT_RDY) { /* See if task is now ready */
if (ptcb->OSTCBDly == 0) {
OSRdyGrp |= ptcb->OSTCBBitY; /* Yes, Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
if (OSRunning == OS_TRUE) {
OS_Sched(); /* Find new highest priority task */
}
} else {
OS_EXIT_CRITICAL();
}
} else { /* Must be pending on event */
OS_EXIT_CRITICAL();
}
return (OS_ERR_NONE);
}
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_SUSPENDED);
}