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.