第二十讲 任务的挂起和恢复
1、任务处于一系列的列表中,比如某个优先级的就绪列表等。任务挂起的时候,就是把任务的node从这些列表中删除。
2、任务可能会被多次挂起,所以需要定义一个挂起计数器。
3、处于delay状态中的函数不要挂起。
主要实现两个函数,挂起和唤醒。
void tTaskSchedUnRdy (tTask * task) { tListRemove(&taskTable[task->prio], &(task->linkNode)); // 队列中可能存在多个任务。只有当没有任务时,才清除位图标记 if (tListCount(&taskTable[task->prio]) == 0) { tBitmapClear(&taskPrioBitmap, task->prio); } } void tTaskSchedRdy (tTask * task) { tListAddLast(&taskTable[task->prio], &(task->linkNode)); tBitmapSet(&taskPrioBitmap, task->prio); } void tTaskSuspend (tTask * task) { // 进入临界区 uint32_t status = tTaskEnterCritical(); // 不允许对已经进入延时状态的任务挂起 if (!(task->state & TINYOS_TASK_STATE_DELAYED)) { // 增加挂起计数,仅当该任务被执行第一次挂起操作时,才考虑是否 // 要执行任务切换操作 if (++task->suspendCount <= 1) { // 设置挂起标志 task->state |= TINYOS_TASK_STATE_SUSPEND; // 挂起方式很简单,就是将其从就绪队列中移除,这样调度器就不会发现他 // 也就没法切换到该任务运行 tTaskSchedUnRdy(task); // 当然,这个任务可能是自己,那么就切换到其它任务 if (task == currentTask) { tTaskSched(); } } } // 退出临界区 tTaskExitCritical(status); } /********************************************************************************************************** ** Function name : tTaskWakeUp ** Descriptions : 唤醒被挂起的任务 ** parameters : task 待唤醒的任务 ** Returned value : 无 ***********************************************************************************************************/ void tTaskWakeUp (tTask * task) { // 进入临界区 uint32_t status = tTaskEnterCritical(); // 检查任务是否处于挂起状态 if (task->state & TINYOS_TASK_STATE_SUSPEND) { // 递减挂起计数,如果为0了,则清除挂起标志,同时设置进入就绪状态 if (--task->suspendCount == 0) { // 清除挂起标志 task->state &= ~TINYOS_TASK_STATE_SUSPEND; // 同时将任务放回就绪队列中 tTaskSchedRdy(task); // 唤醒过程中,可能有更高优先级的任务就绪,执行一次任务调度 tTaskSched(); } } // 退出临界区 tTaskExitCritical(status); }