Nuttx之nxsched_add_readytorun(non-SMP)

发布于:2025-06-26 ⋅ 阅读:(18) ⋅ 点赞:(0)

声明:此处代码分析,来源与 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。


网站公告

今日签到

点亮在社区的每一天
去签到