声明:此处代码分析,来源与 nuttx 12.8.0版本。
在分析之前,需要一图镇楼。

/***************************************************************************** Name: nxsched_add_readytorun** Description:* This function adds a TCB to the ready to run list. If the currently* active task has preemption disabled and the new TCB would cause this* task to be pre-empted, the new task is added to the g_pendingtasks list* instead. The pending tasks will be made ready-to-run when preemption is* unlocked.** Input Parameters:* btcb - Points to the blocked TCB that is ready-to-run** Returned Value:* true if the currently active task (the head of the ready-to-run list)* has changed.** Assumptions:* - The caller has established a critical section before calling this* function (calling sched_lock() first is NOT a good idea -- use* enter_critical_section()).* - The caller has already removed the input rtcb from whatever list it* was in.* - The caller handles the condition that occurs if the head of the* ready-to-run list is changed.*****************************************************************************/#ifndef CONFIG_SMP
bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
{FAR struct tcb_s *rtcb = this_task();bool ret;/* Check if pre-emption is disabled for the current running task and if* the new ready-to-run task would cause the current running task to be* pre-empted. NOTE that IRQs disabled implies that pre-emption is* also disabled.*/if (nxsched_islocked_tcb(rtcb) &&rtcb->sched_priority < btcb->sched_priority){/* Yes. Preemption would occur! Add the new ready-to-run task to the* g_pendingtasks task list for now.*/nxsched_add_prioritized(btcb, list_pendingtasks());btcb->task_state = TSTATE_TASK_PENDING;ret = false;}/* Otherwise, add the new task to the ready-to-run task list */else if (nxsched_add_prioritized(btcb, list_readytorun())){/* The new btcb was added at the head of the ready-to-run list. It* is now the new active task!*/DEBUGASSERT(!nxsched_islocked_tcb(rtcb) && !is_idle_task(btcb));btcb->task_state = TSTATE_TASK_RUNNING;btcb->flink->task_state = TSTATE_TASK_READYTORUN;up_update_task(btcb);ret = true;}else{/* The new btcb was added in the middle of the ready-to-run list */btcb->task_state = TSTATE_TASK_READYTORUN;ret = false;}return ret;
}
#endif /* !CONFIG_SMP */
显然,此函数的功能是,在非SMP情况下,将btcb 加入到reaytorun 队列。这个加入队列的操作,可能会导致任务切换。为什么是这样呢,根据上图,不应该是加入到running 队列中才可能会导致任务切换吗?为此,我们需要看看reaytorun 队列的定义。
/* This is the list of all tasks that are ready to run. This is a* prioritized list with head of the list holding the highest priority* (unassigned) task. In the non-SMP case, the head of this list is the* currently active task and the tail of this list, the lowest priority* task, is always the IDLE task.*/dq_queue_t g_readytorun;
对于非SMP,g_readytorun队列的头部就是正在运行的任务。对于非SMP ,不存在running 队列,因此在加入readtorun队列时,可能会导致任务切换。
那,具体怎么个加法呢? 这就涉及到函数主体中的判断条件,
nxsched_islocked_tcb(rtcb) 和rtcb->sched_priority < btcb->sched_priority。此组合有四种情况。
1.当rtcb非可抢占且rtcb->sched_priority < btcb->sched_priority时,将bctb加入到g_pendingtasks。并设置状态位为TSTATE_TASK_PENDING。
2. 当rtcb非可抢占且rtcb->sched_priority >= btcb->sched_priority时, 将bctb按照优先级加入到g_readytorun。并设置状态位为TSTATE_TASK_READYTORUN。
3. 当rtcb可抢占且rtcb->sched_priority < btcb->sched_priority时, 将会出现任务切换的情况。此时,nxsched_add_readytorun函数只负责将btcb插入到g_readytorun 队列头,标记其状态为TSTATE_TASK_RUNNING。将rtcb状态标记为TSTATE_TASK_READYTORUN,至于真正的任务上下文的切换工作,不在此函数的功能范围。
4.当rtcb可抢占且rtcb->sched_priority >= btcb->sched_priority时, 将bctb按照优先级加入到g_readytorun。并设置状态位为TSTATE_TASK_READYTORUN。