Yan Gang Nutx Kernel Task Link List

Keywords: Linux

Articles Catalogue

Resources

Yan Gang Nutx Kernel Task Link List

Analysis of task switching process in nuttx waiting for semaphore resources

Current tasks need to wait for semaphore resources before they can continue to execute, so you need to remove the current tasks from the ready list and add them to the waiting resource list.

int nxsem_wait(FAR sem_t *sem)
  ->  up_block_task(rtcb, TSTATE_WAIT_SEM);
     ->  switch_needed = sched_removereadytorun(tcb); // The current task removes the ready list and the next task acts as a running state
     -> sched_addblocked(tcb, TSTATE_WAIT_SEM); //The current task is set to wait for semaphores 
        if (TLIST_ISPRIORITIZED(task_state))
            -> sched_addprioritized(btcb, tasklist); //Priority queue
        else
             -> dq_addlast((FAR dq_entry_t *)btcb, tasklist); //queue
        -> btcb->task_state = TSTATE_WAIT_SEM; //Setting queue status
     -> struct tcb_s *nexttcb = this_task(); 
        -> ((FAR struct tcb_s *)g_readytorun.head) //Get the head of the waiting queue> up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); //Task switching

Nutx task scheduling after releasing semaphore resources

Nutx wakes up the thread waiting for the semaphore after releasing the semaphore

int nxsem_post(FAR sem_t *sem)
    -> up_unblock_task(stcb);
      -> sched_removeblocked(tcb); //Move out
        bool sched_removereadytorun(FAR struct tcb_s *rtcb)
        //Find the next one and set it to run state.
        ->FAR struct tcb_s *nxttcb = (FAR struct tcb_s *)rtcb->flink;
        -> nxttcb->task_state = TSTATE_TASK_RUNNING;
            doswitch = true;

        // Delete the current task block and set the status to invalid
        -> dq_rem((FAR dq_entry_t *)rtcb, (FAR dq_queue_t *)&g_readytorun);=
        -> rtcb->task_state = TSTATE_TASK_INVALID;
      ->if (sched_addreadytorun(tcb)) //Add to the run queue
        -> up_unblock_task(stcb);
            ->if (sched_addreadytorun(tcb))
                //Queuing according to priority
                -> else if (sched_addprioritized(btcb, (FAR dq_queue_t *)&g_readytorun))
                    for (next = (FAR struct tcb_s *)list->head;
                    (next && sched_priority <= next->sched_priority);
                    next = next->flink);
                    tcb->flink = next;
                    tcb->blink = prev;
                    prev->flink = tcb;
                    next->blink = tcb;
                //The current task becomes operational
                -> btcb->task_state = TSTATE_TASK_RUNNING;
                btcb->flink->task_state = TSTATE_TASK_READYTORUN;
       //Get the latest task status to proceed
       -> struct tcb_s *nexttcb = this_task();     
       -> up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);    

The state of the task

Task states are the following. Priority task states and queues correspond to each other. All tasks add up to a list of all tasks.

enum tstate_e
{
  TSTATE_TASK_INVALID    = 0, /* INVALID      - The TCB is uninitialized */
  TSTATE_TASK_PENDING,        /* READY_TO_RUN - Pending preemption unlock */
  TSTATE_TASK_READYTORUN,     /* READY-TO-RUN - But not running */
  TSTATE_TASK_RUNNING,        /* READY_TO_RUN - And running */

  TSTATE_TASK_INACTIVE,       /* BLOCKED      - Initialized but not yet activated */
  TSTATE_WAIT_SEM,            /* BLOCKED      - Waiting for a semaphore */
#ifndef CONFIG_DISABLE_SIGNALS
  TSTATE_WAIT_SIG,            /* BLOCKED      - Waiting for a signal */
#endif
#ifndef CONFIG_DISABLE_MQUEUE
  TSTATE_WAIT_MQNOTEMPTY,     /* BLOCKED      - Waiting for a MQ to become not empty. */
  TSTATE_WAIT_MQNOTFULL,      /* BLOCKED      - Waiting for a MQ to become not full. */
#endif
#ifdef CONFIG_PAGING
  TSTATE_WAIT_PAGEFILL,       /* BLOCKED      - Waiting for page fill */
#endif
#ifdef CONFIG_SIG_SIGSTOP_ACTION
  TSTATE_TASK_STOPPED,        /* BLOCKED      - Waiting for SIGCONT */
#endif

  NUM_TASK_STATES             /* Must be last */
};

const struct tasklist_s g_tasklisttable[NUM_TASK_STATES] =
{
  {                                              /* TSTATE_TASK_INVALID */
    NULL,
    0
  },
  {                                              /* TSTATE_TASK_PENDING */
    &g_pendingtasks,
    TLIST_ATTR_PRIORITIZED
  },

  {                                              /* TSTATE_TASK_READYTORUN */
    &g_readytorun,
    TLIST_ATTR_PRIORITIZED | TLIST_ATTR_RUNNABLE
  },
  {                                              /* TSTATE_TASK_RUNNING */
    &g_readytorun,
    TLIST_ATTR_PRIORITIZED | TLIST_ATTR_RUNNABLE
  },
  {                                              /* TSTATE_TASK_INACTIVE */
    &g_inactivetasks,
    0
  },
  {                                              /* TSTATE_WAIT_SEM */
    &g_waitingforsemaphore,
    TLIST_ATTR_PRIORITIZED
  }
  ,
  {                                              /* TSTATE_WAIT_SIG */
    &g_waitingforsignal,
    0
  }
};

summary

In nuttx task scheduling, the priority queue is the algorithm to find the highest priority task. Its time complexity is O(n). When the number of tasks is small, it is no problem to find the most priority task, but
When there are many tasks, it is obvious that this scheduling algorithm is unreasonable. linux is the same scheduling algorithm before 2.4 kernel. It can learn ygOS. Using bitmap, the time complexity of finding the highest priority is O1.

Posted by hatrickpatrick on Wed, 21 Aug 2019 22:49:57 -0700