diff --git a/Documentation/reference/os/arch.rst b/Documentation/reference/os/arch.rst index 42df537b98..12c9dbbb86 100644 --- a/Documentation/reference/os/arch.rst +++ b/Documentation/reference/os/arch.rst @@ -174,19 +174,17 @@ APIs Exported by Architecture-Specific Logic to NuttX and threads must have come from memory that is accessible to user -.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb) +.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb) - A task is currently in an inactive task list but - has been prepped to execute. Move the TCB to the ready-to-run - list, restore its context, and start execution. + A task is currently in the ready-to-run list but has been preppe + to execute. Restore its context, and start execution. This function is called only from the NuttX scheduling logic. Interrupts will always be disabled when this function is called. - :param tcb: Refers to the tcb to be unblocked. This tcb is in one - of the waiting tasks lists. It must be moved to the - ready-to-run list and, if it is the highest priority ready to - run tasks, executed. + :param tcb: Refers to the head task of the ready-to-run list + which will be executed. + :param rtcb: Refers to the running task which will be blocked. .. c:function:: void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) diff --git a/arch/arm/src/common/arm_unblocktask.c b/arch/arm/src/common/arm_unblocktask.c index 5b347c0dfc..af53886a1a 100644 --- a/arch/arm/src/common/arm_unblocktask.c +++ b/arch/arm/src/common/arm_unblocktask.c @@ -43,93 +43,61 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + arm_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + arm_restorestate(tcb->xcp.regs); + } - arm_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - nxsched_resume_scheduler(rtcb); + arm_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - arm_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Switch context to the context of the task at the head of the - * ready to run list. - */ - - arm_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - - /* arm_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* arm_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/arm64/src/common/arm64_unblocktask.c b/arch/arm64/src/common/arm64_unblocktask.c index 68fc5d88cb..c91eddfed3 100644 --- a/arch/arm64/src/common/arm64_unblocktask.c +++ b/arch/arm64/src/common/arm64_unblocktask.c @@ -43,93 +43,61 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + arm64_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + arm64_restorestate(tcb->xcp.regs); + } - arm64_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - nxsched_resume_scheduler(rtcb); + arm64_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - arm64_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Switch context to the context of the task at the head of the - * ready to run list. - */ - - arm64_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - - /* arm_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* arm_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/avr/src/avr/up_unblocktask.c b/arch/avr/src/avr/up_unblocktask.c index 8e54f5008c..1d906bb4b8 100644 --- a/arch/avr/src/avr/up_unblocktask.c +++ b/arch/avr/src/avr/up_unblocktask.c @@ -42,91 +42,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts */ - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + up_restorestate(tcb->xcp.regs); + } - up_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - nxsched_resume_scheduler(rtcb); + up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts */ - - up_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Switch context to the context of the task at the head of the - * ready to run list. - */ - - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - - /* up_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/avr/src/avr32/up_unblocktask.c b/arch/avr/src/avr32/up_unblocktask.c index 486bca0d7b..8dfcc80eaa 100644 --- a/arch/avr/src/avr32/up_unblocktask.c +++ b/arch/avr/src/avr32/up_unblocktask.c @@ -43,106 +43,69 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any new address environment needed by + * the new thread will be instantiated before the return from + * interrupt. + */ - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + up_restorestate(tcb->xcp.regs); + } - up_savestate(rtcb->xcp.regs); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then switch contexts. Any new address environment needed by - * the new thread will be instantiated before the return from - * interrupt. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - struct tcb_s *nexttcb = this_task(); + /* No, then we will need to perform the user context switch */ + else + { #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(nexttcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(nexttcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs); - /* up_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/ceva/src/common/up_unblocktask.c b/arch/ceva/src/common/up_unblocktask.c index 84e7b24502..395c9db46b 100644 --- a/arch/ceva/src/common/up_unblocktask.c +++ b/arch/ceva/src/common/up_unblocktask.c @@ -38,91 +38,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * - * Inputs: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run taks, executed. + * Input Parameters: + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + sched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - sched_removeblocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (sched_addreadytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + rtcb->xcp.regs = CURRENT_REGS; + /* Update scheduler parameters */ - sched_suspend_scheduler(rtcb); + sched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + CURRENT_REGS = tcb->xcp.regs; + } - rtcb->xcp.regs = CURRENT_REGS; + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + sched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - sched_resume_scheduler(rtcb); + up_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts */ - - CURRENT_REGS = rtcb->xcp.regs; - } - - /* No, then we will need to perform the user context switch */ - - else - { - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - sched_resume_scheduler(nexttcb); - - /* Switch context to the context of the task at the head of the - * ready to run list. - */ - - up_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - - /* up_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/hc/src/common/up_unblocktask.c b/arch/hc/src/common/up_unblocktask.c index 94609a1744..75991546be 100644 --- a/arch/hc/src/common/up_unblocktask.c +++ b/arch/hc/src/common/up_unblocktask.c @@ -43,103 +43,66 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ - - up_savestate(rtcb->xcp.regs); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * up_saveusercontext returns a non-zero value, then this is really the - * previously running task restarting! + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + up_restorestate(tcb->xcp.regs); + } - rtcb = this_task(); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + else if (!up_saveusercontext(rtcb->xcp.regs)) + { #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(rtcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(tcb->xcp.regs); } } diff --git a/arch/mips/src/mips32/mips_unblocktask.c b/arch/mips/src/mips32/mips_unblocktask.c index 586fb4b226..4cdb70e682 100644 --- a/arch/mips/src/mips32/mips_unblocktask.c +++ b/arch/mips/src/mips32/mips_unblocktask.c @@ -45,96 +45,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + up_restorestate(tcb->xcp.regs); + } - up_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Then switch contexts */ - nxsched_resume_scheduler(rtcb); + up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Then switch contexts */ - - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - - /* up_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/misoc/src/lm32/lm32_unblocktask.c b/arch/misoc/src/lm32/lm32_unblocktask.c index 4a6e69decb..51e7c01b99 100644 --- a/arch/misoc/src/lm32/lm32_unblocktask.c +++ b/arch/misoc/src/lm32/lm32_unblocktask.c @@ -45,96 +45,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + up_restorestate(tcb->xcp.regs); + } - up_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Then switch contexts */ - nxsched_resume_scheduler(rtcb); + up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Then switch contexts */ - - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - - /* up_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/misoc/src/minerva/minerva_unblocktask.c b/arch/misoc/src/minerva/minerva_unblocktask.c index 69c4e0a340..a8b74afc0e 100644 --- a/arch/misoc/src/minerva/minerva_unblocktask.c +++ b/arch/misoc/src/minerva/minerva_unblocktask.c @@ -45,96 +45,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized ready-to-run - * task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do a context - * switch to the new task. + /* Yes, then we have to do things differently. Just copy the + * g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment changes + * will be made when the interrupt returns. + */ - if (g_current_regs) - { - /* Yes, then we have to do things differently. Just copy the - * g_current_regs into the OLD rtcb. - */ + up_restorestate(tcb->xcp.regs); + } - up_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head of - * the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Then switch contexts */ - nxsched_resume_scheduler(rtcb); + up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Then switch contexts */ - - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - - /* up_switchcontext forces a context switch to the task at the head - * of the ready-to-run list. It does not 'return' in the normal - * sense. When it does return, it is because the blocked task is - * again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the head + * of the ready-to-run list. It does not 'return' in the normal + * sense. When it does return, it is because the blocked task is + * again ready to run and has execution priority. + */ } } diff --git a/arch/or1k/src/common/up_unblocktask.c b/arch/or1k/src/common/up_unblocktask.c index be26e53062..01e80d3c48 100644 --- a/arch/or1k/src/common/up_unblocktask.c +++ b/arch/or1k/src/common/up_unblocktask.c @@ -43,107 +43,70 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) +#if 0 /* REVISIT */ + if (CURRENT_REGS) +#else + if (0) +#endif { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - -#if 0 /* REVISIT */ - if (CURRENT_REGS) -#else - if (0) -#endif - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ - - up_savestate(rtcb->xcp.regs); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * up_saveusercontext returns a non-zero value, then this is really the - * previously running task restarting! + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + up_restorestate(tcb->xcp.regs); + } - rtcb = this_task(); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + else if (!up_saveusercontext(rtcb->xcp.regs)) + { #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(rtcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(tcb->xcp.regs); } } diff --git a/arch/renesas/src/common/up_unblocktask.c b/arch/renesas/src/common/up_unblocktask.c index a7df03de61..de0987019c 100644 --- a/arch/renesas/src/common/up_unblocktask.c +++ b/arch/renesas/src/common/up_unblocktask.c @@ -43,103 +43,66 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ - - up_savestate(rtcb->xcp.regs); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - g_current_regs = rtcb->xcp.regs; - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * up_saveusercontext returns a non-zero value, then this is really the - * previously running task restarting! + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + g_current_regs = tcb->xcp.regs; + } - rtcb = this_task(); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + else if (!up_saveusercontext(rtcb->xcp.regs)) + { #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(rtcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(tcb->xcp.regs); } } diff --git a/arch/risc-v/src/common/riscv_unblocktask.c b/arch/risc-v/src/common/riscv_unblocktask.c index c72360dadc..e77b237585 100644 --- a/arch/risc-v/src/common/riscv_unblocktask.c +++ b/arch/risc-v/src/common/riscv_unblocktask.c @@ -45,96 +45,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + riscv_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + riscv_restorestate(tcb->xcp.regs); + } - riscv_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Then switch contexts */ - nxsched_resume_scheduler(rtcb); + riscv_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - riscv_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Then switch contexts */ - - riscv_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - - /* riscv_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* riscv_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/sim/src/sim/up_unblocktask.c b/arch/sim/src/sim/up_unblocktask.c index 3f1bd1929e..08ed9d0e07 100644 --- a/arch/sim/src/sim/up_unblocktask.c +++ b/arch/sim/src/sim/up_unblocktask.c @@ -42,109 +42,75 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - - /* Verify that the context switch can be performed */ - - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); - sinfo("Unblocking TCB=%p\n", tcb); - /* Remove the task from the blocked task list */ + /* Update scheduler parameters */ - nxsched_remove_blocked(tcb); + nxsched_suspend_scheduler(rtcb); - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ + /* Are we in an interrupt handler? */ - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! */ + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Restore the cpu lock */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + restore_critical_section(); - up_savestate(rtcb->xcp.regs); + /* Then switch contexts */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + up_restorestate(tcb->xcp.regs); + } - rtcb = this_task(); + /* Copy the exception context into the TCB of the task that was + * previously active. if setjmp returns a non-zero value, then + * this is really the previously running task restarting! + */ - /* Update scheduler parameters */ + else if (!setjmp(rtcb->xcp.regs)) + { + sinfo("New Active Task TCB=%p\n", tcb); - nxsched_resume_scheduler(rtcb); + /* Update scheduler parameters */ - /* Restore the cpu lock */ + nxsched_resume_scheduler(tcb); - restore_critical_section(); + /* Restore the cpu lock */ - /* Then switch contexts */ + restore_critical_section(); - up_restorestate(rtcb->xcp.regs); - } + /* Then switch contexts */ - /* Copy the exception context into the TCB of the task that was - * previously active. if setjmp returns a non-zero value, then - * this is really the previously running task restarting! + longjmp(tcb->xcp.regs, 1); + } + else + { + /* The way that we handle signals in the simulation is kind of + * a kludge. This would be unsafe in a truly multi-threaded, + * interrupt driven environment. */ - else if (!setjmp(rtcb->xcp.regs)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - rtcb = this_task(); - sinfo("New Active Task TCB=%p\n", rtcb); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Restore the cpu lock */ - - restore_critical_section(); - - /* Then switch contexts */ - - longjmp(rtcb->xcp.regs, 1); - } - else - { - /* The way that we handle signals in the simulation is kind of - * a kludge. This would be unsafe in a truly multi-threaded, - * interrupt driven environment. - */ - - sim_sigdeliver(); - } + sim_sigdeliver(); } } diff --git a/arch/sparc/src/sparc_v8/up_unblocktask.c b/arch/sparc/src/sparc_v8/up_unblocktask.c index 986b4af358..b20b52a50a 100644 --- a/arch/sparc/src/sparc_v8/up_unblocktask.c +++ b/arch/sparc/src/sparc_v8/up_unblocktask.c @@ -45,96 +45,59 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + up_restorestate(tcb->xcp.regs); + } - up_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Then switch contexts */ - nxsched_resume_scheduler(rtcb); + up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Then switch contexts */ - - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - - /* up_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/x86/src/common/up_unblocktask.c b/arch/x86/src/common/up_unblocktask.c index 4eaf4e529d..5003675cad 100644 --- a/arch/x86/src/common/up_unblocktask.c +++ b/arch/x86/src/common/up_unblocktask.c @@ -43,102 +43,66 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list but has been prepped to - * execute. Move the TCB to the ready-to-run list, restore its context, - * and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is in one of the - * waiting tasks lists. It must be moved to the ready-to-run list and, - * if it is the highest priority ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ - - up_savestate(rtcb->xcp.regs); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * up_saveusercontext returns a non-zero value, then this is really the - * previously running task restarting! + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + up_restorestate(tcb->xcp.regs); + } - rtcb = this_task(); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + else if (!up_saveusercontext(rtcb->xcp.regs)) + { #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(rtcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(tcb->xcp.regs); } } diff --git a/arch/x86_64/src/common/up_unblocktask.c b/arch/x86_64/src/common/up_unblocktask.c index cd3fff6db1..5420cadc63 100644 --- a/arch/x86_64/src/common/up_unblocktask.c +++ b/arch/x86_64/src/common/up_unblocktask.c @@ -45,104 +45,70 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list but has been prepped to - * execute. Move the TCB to the ready-to-run list, restore its context, - * and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is in one of the - * waiting tasks lists. It must be moved to the ready-to-run list and, - * if it is the highest priority ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (g_current_regs) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ + up_savestate(rtcb->xcp.regs); + + up_restore_auxstate(tcb); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ - - up_savestate(rtcb->xcp.regs); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - up_restore_auxstate(rtcb); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - up_restorestate(rtcb->xcp.regs); - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * up_saveusercontext returns a non-zero value, then this is really the - * previously running task restarting! + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + up_restorestate(tcb->xcp.regs); + } - rtcb = this_task(); - up_restore_auxstate(rtcb); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + up_restore_auxstate(tcb); #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(rtcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(tcb->xcp.regs); } } diff --git a/arch/xtensa/src/common/xtensa_unblocktask.c b/arch/xtensa/src/common/xtensa_unblocktask.c index c1bcf7afb5..5f453cedb4 100644 --- a/arch/xtensa/src/common/xtensa_unblocktask.c +++ b/arch/xtensa/src/common/xtensa_unblocktask.c @@ -45,93 +45,61 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(struct tcb_s *tcb) +void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (CURRENT_REGS) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ + xtensa_savestate(rtcb->xcp.regs); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + xtensa_restorestate(tcb->xcp.regs); + } - xtensa_savestate(rtcb->xcp.regs); + /* No, then we will need to perform the user context switch */ - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + else + { + /* Reset scheduler parameters */ - rtcb = this_task(); + nxsched_resume_scheduler(tcb); - /* Update scheduler parameters */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - nxsched_resume_scheduler(rtcb); + xtensa_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs); - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - xtensa_restorestate(rtcb->xcp.regs); - } - - /* No, then we will need to perform the user context switch */ - - else - { - struct tcb_s *nexttcb = this_task(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(nexttcb); - - /* Switch context to the context of the task at the head of the - * ready to run list. - */ - - xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - - /* xtensa_switchcontext forces a context switch to the task at the - * head of the ready-to-run list. It does not 'return' in the - * normal sense. When it does return, it is because the blocked - * task is again ready to run and has execution priority. - */ - } + /* xtensa_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ } } diff --git a/arch/z16/src/common/z16_unblocktask.c b/arch/z16/src/common/z16_unblocktask.c index 74d2d6664e..b24d8c414c 100644 --- a/arch/z16/src/common/z16_unblocktask.c +++ b/arch/z16/src/common/z16_unblocktask.c @@ -44,96 +44,57 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(FAR struct tcb_s *tcb) +void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb) { - FAR struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* sinfo("Unblocking TCB=%p\n", tcb); */ - - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (IN_INTERRUPT) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the current context into the OLD rtcb. */ + SAVE_IRQCONTEXT(rtcb); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - - if (IN_INTERRUPT) - { - /* Yes, then we have to do things differently. - * Just copy the current context into the OLD rtcb. - */ - - SAVE_IRQCONTEXT(rtcb); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then setup so that the context will be performed on exit - * from the interrupt. - */ - - SET_IRQCONTEXT(rtcb); - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * SAVE_USERCONTEXT returns a non-zero value, then this is really the - * previously running task restarting! + /* Then setup so that the context will be performed on exit + * from the interrupt. */ - else if (!SAVE_USERCONTEXT(rtcb)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + SET_IRQCONTEXT(tcb); + } - rtcb = this_task(); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * SAVE_USERCONTEXT returns a non-zero value, then this is really the + * previously running task restarting! + */ - /* Update scheduler parameters */ + else if (!SAVE_USERCONTEXT(rtcb)) + { + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - RESTORE_USERCONTEXT(rtcb); - } + RESTORE_USERCONTEXT(tcb); } } diff --git a/arch/z80/src/common/z80_unblocktask.c b/arch/z80/src/common/z80_unblocktask.c index bad43f0be3..55fc1b2d34 100644 --- a/arch/z80/src/common/z80_unblocktask.c +++ b/arch/z80/src/common/z80_unblocktask.c @@ -46,106 +46,67 @@ * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(FAR struct tcb_s *tcb) +void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb) { - FAR struct tcb_s *rtcb = this_task(); + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && - (tcb->task_state <= LAST_BLOCKED_STATE)); + /* Are we in an interrupt handler? */ - /* _info("Unblocking TCB=%p\n", tcb); */ - - /* Remove the task from the blocked task list */ - - nxsched_remove_blocked(tcb); - - /* Add the task in the correct location in the prioritized - * ready-to-run task list - */ - - if (nxsched_add_readytorun(tcb)) + if (IN_INTERRUPT()) { - /* The currently active task has changed! We need to do - * a context switch to the new task. + /* Yes, then we have to do things differently. + * Just copy the current context into the OLD rtcb. */ + SAVE_IRQCONTEXT(rtcb); + /* Update scheduler parameters */ - nxsched_suspend_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Are we in an interrupt handler? */ - - if (IN_INTERRUPT()) - { - /* Yes, then we have to do things differently. - * Just copy the current context into the OLD rtcb. - */ - - SAVE_IRQCONTEXT(rtcb); - - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Update scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then setup so that the context will be performed on exit - * from the interrupt. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - SET_IRQCONTEXT(rtcb); - } - - /* We are not in an interrupt handler. Copy the user C context - * into the TCB of the task that was previously active. if - * SAVE_USERCONTEXT returns a non-zero value, then this is really the - * previously running task restarting! + /* Then setup so that the context will be performed on exit + * from the interrupt. Any necessary address environment + * changes will be made when the interrupt returns. */ - else if (!SAVE_USERCONTEXT(rtcb)) - { - /* Restore the exception context of the new task that is ready to - * run (probably tcb). This is the new rtcb at the head of the - * ready-to-run task list. - */ + SET_IRQCONTEXT(tcb); + } - rtcb = this_task(); + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * SAVE_USERCONTEXT returns a non-zero value, then this is really the + * previously running task restarting! + */ + else if (!SAVE_USERCONTEXT(rtcb)) + { #ifdef CONFIG_ARCH_ADDRENV - /* Make sure that the address environment for the previously - * running task is closed down gracefully (data caches dump, - * MMU flushed) and set up the address environment for the new - * thread at the head of the ready-to-run list. - */ + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ - group_addrenv(rtcb); + group_addrenv(tcb); #endif - /* Update scheduler parameters */ + /* Update scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(tcb); - /* Then switch contexts */ + /* Then switch contexts */ - RESTORE_USERCONTEXT(rtcb); - } + RESTORE_USERCONTEXT(tcb); } } diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index e41adb394f..6eee128995 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -387,23 +387,21 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype); * Name: up_unblock_task * * Description: - * A task is currently in an inactive task list - * but has been prepped to execute. Move the TCB to the - * ready-to-run list, restore its context, and start execution. + * A task is currently in the ready-to-run list but has been prepped + * to execute. Restore its context, and start execution. * * This function is called only from the NuttX scheduling * logic. Interrupts will always be disabled when this * function is called. * * Input Parameters: - * tcb: Refers to the tcb to be unblocked. This tcb is - * in one of the waiting tasks lists. It must be moved to - * the ready-to-run list and, if it is the highest priority - * ready to run task, executed. + * tcb: Refers to the head task of the ready-to-run list + * which will be executed. + * rtcb: Refers to the running task which will be blocked. * ****************************************************************************/ -void up_unblock_task(FAR struct tcb_s *tcb); +void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb); /**************************************************************************** * Name: up_block_task diff --git a/sched/group/group_continue.c b/sched/group/group_continue.c index 9a03b0d623..b775ebbdbf 100644 --- a/sched/group/group_continue.c +++ b/sched/group/group_continue.c @@ -57,6 +57,7 @@ static int group_continue_handler(pid_t pid, FAR void *arg) { + FAR struct tcb_s *tcb = this_task(); FAR struct tcb_s *rtcb; /* Resume all threads */ @@ -64,7 +65,18 @@ static int group_continue_handler(pid_t pid, FAR void *arg) rtcb = nxsched_get_tcb(pid); if (rtcb != NULL) { - up_unblock_task(rtcb); + /* Remove the task from waitting list */ + + nxsched_remove_blocked(rtcb); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(rtcb)) + { + up_unblock_task(rtcb, tcb); + } } /* Always return zero. We need to visit each member of the group */ diff --git a/sched/mqueue/mq_rcvinternal.c b/sched/mqueue/mq_rcvinternal.c index 48348cc01d..c22604658f 100644 --- a/sched/mqueue/mq_rcvinternal.c +++ b/sched/mqueue/mq_rcvinternal.c @@ -279,13 +279,15 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq, if (msgq->cmn.nwaitnotfull > 0) { + FAR struct tcb_s *rtcb = this_task(); + /* Find the highest priority task that is waiting for * this queue to be not-full in waitfornotfull list. * This must be performed in a critical section because * messages can be sent from interrupt handlers. */ - btcb = (FAR struct tcb_s *)dq_peek(MQ_WNFLIST(msgq->cmn)); + btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn)); /* If one was found, unblock it. NOTE: There is a race * condition here: the queue might be full again by the @@ -300,7 +302,19 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq, } msgq->cmn.nwaitnotfull--; - up_unblock_task(btcb); + + /* Indicate that the wait is over. */ + + btcb->waitobj = NULL; + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(btcb)) + { + up_unblock_task(btcb, rtcb); + } } /* Return the length of the message transferred to the user buffer */ diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c index 578d8b7523..d74f9301c3 100644 --- a/sched/mqueue/mq_sndinternal.c +++ b/sched/mqueue/mq_sndinternal.c @@ -388,6 +388,8 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq, if (msgq->cmn.nwaitnotempty > 0) { + FAR struct tcb_s *rtcb = this_task(); + /* Find the highest priority task that is waiting for * this queue to be non-empty in waitfornotempty * list. leave_critical_section() should give us sufficient @@ -395,7 +397,7 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq, * in this list */ - btcb = (FAR struct tcb_s *)dq_peek(MQ_WNELIST(msgq->cmn)); + btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn)); /* If one was found, unblock it */ @@ -407,7 +409,19 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq, } msgq->cmn.nwaitnotempty--; - up_unblock_task(btcb); + + /* Indicate that the wait is over. */ + + btcb->waitobj = NULL; + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(btcb)) + { + up_unblock_task(btcb, rtcb); + } } return OK; diff --git a/sched/mqueue/mq_waitirq.c b/sched/mqueue/mq_waitirq.c index aa2e800c5f..58d78b2291 100644 --- a/sched/mqueue/mq_waitirq.c +++ b/sched/mqueue/mq_waitirq.c @@ -33,6 +33,7 @@ #include #include "mqueue/mqueue.h" +#include "sched/sched.h" /**************************************************************************** * Public Functions @@ -61,6 +62,7 @@ void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode) { + FAR struct tcb_s *rtcb = this_task(); FAR struct mqueue_inode_s *msgq; /* It is possible that an interrupt/context switch beat us to the punch and @@ -80,18 +82,29 @@ void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode) { DEBUGASSERT(msgq->cmn.nwaitnotempty > 0); msgq->cmn.nwaitnotempty--; + dq_rem((FAR dq_entry_t *)wtcb, MQ_WNELIST(msgq->cmn)); } else { DEBUGASSERT(msgq->cmn.nwaitnotfull > 0); msgq->cmn.nwaitnotfull--; + dq_rem((FAR dq_entry_t *)wtcb, MQ_WNFLIST(msgq->cmn)); } + /* Indicate that the wait is over. */ + + wtcb->waitobj = NULL; + /* Mark the error value for the thread. */ wtcb->errcode = errcode; - /* Restart the task. */ + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ - up_unblock_task(wtcb); + if (nxsched_add_readytorun(wtcb)) + { + up_unblock_task(wtcb, rtcb); + } } diff --git a/sched/mqueue/msgrcv.c b/sched/mqueue/msgrcv.c index 1402b022d4..23a33a6abf 100644 --- a/sched/mqueue/msgrcv.c +++ b/sched/mqueue/msgrcv.c @@ -221,13 +221,15 @@ ssize_t msgrcv(int msqid, FAR void *msgp, size_t msgsz, long msgtyp, if (msgq->cmn.nwaitnotfull > 0) { + FAR struct tcb_s *rtcb = this_task(); + /* Find the highest priority task that is waiting for * this queue to be not-full in g_waitingformqnotfull list. * This must be performed in a critical section because * messages can be sent from interrupt handlers. */ - btcb = (FAR struct tcb_s *)dq_peek(MQ_WNFLIST(msgq->cmn)); + btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn)); /* If one was found, unblock it. NOTE: There is a race * condition here: the queue might be full again by the @@ -242,7 +244,19 @@ ssize_t msgrcv(int msqid, FAR void *msgp, size_t msgsz, long msgtyp, } msgq->cmn.nwaitnotfull--; - up_unblock_task(btcb); + + /* Indicate that the wait is over. */ + + btcb->waitobj = NULL; + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(btcb)) + { + up_unblock_task(btcb, rtcb); + } } errout_with_critical: diff --git a/sched/mqueue/msgsnd.c b/sched/mqueue/msgsnd.c index aac4983d52..f10407b132 100644 --- a/sched/mqueue/msgsnd.c +++ b/sched/mqueue/msgsnd.c @@ -216,6 +216,8 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg) if (msgq->cmn.nwaitnotempty > 0) { + FAR struct tcb_s *rtcb = this_task(); + /* Find the highest priority task that is waiting for * this queue to be non-empty in g_waitingformqnotempty * list. enter_critical_section() should give us sufficient @@ -223,7 +225,7 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg) * in this list */ - btcb = (FAR struct tcb_s *)dq_peek(MQ_WNELIST(msgq->cmn)); + btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn)); /* If one was found, unblock it */ @@ -235,7 +237,19 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg) } msgq->cmn.nwaitnotempty--; - up_unblock_task(btcb); + + /* Indicate that the wait is over. */ + + btcb->waitobj = NULL; + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(btcb)) + { + up_unblock_task(btcb, rtcb); + } } } diff --git a/sched/paging/pg_worker.c b/sched/paging/pg_worker.c index 2a08b8c1ca..82dbc6ed47 100644 --- a/sched/paging/pg_worker.c +++ b/sched/paging/pg_worker.c @@ -215,6 +215,8 @@ static void pg_callback(FAR struct tcb_s *tcb, int result) static inline bool pg_dequeue(void) { + FAR struct tcb_s *wtcb = this_task(); + /* Loop until either (1) the TCB of a task that requires a fill is found, * OR (2) the g_watingforfill list becomes empty. */ @@ -253,7 +255,6 @@ static inline bool pg_dequeue(void) * if a new higher priority fill is required). */ - FAR struct tcb_s *wtcb = this_task(); if (wtcb->sched_priority > CONFIG_PAGING_DEFPRIO && wtcb->sched_priority > g_pftcb->sched_priority) { @@ -287,7 +288,15 @@ static inline bool pg_dequeue(void) */ pginfo("Restarting TCB: %p\n", g_pftcb); - up_unblock_task(g_pftcb); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(g_pftcb)) + { + up_unblock_task(g_pftcb, wtcb); + } } } while (g_pftcb != NULL); @@ -469,12 +478,22 @@ static inline void pg_alldone(void) static inline void pg_fillcomplete(void) { + FAR struct tcb_s *wtcb = this_task(); + /* Call up_unblocktask(g_pftcb) to make the task that just * received the fill ready-to-run. */ pginfo("Restarting TCB: %p\n", g_pftcb); - up_unblock_task(g_pftcb); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(g_pftcb)) + { + up_unblock_task(g_pftcb, wtcb); + } } /**************************************************************************** @@ -506,6 +525,8 @@ static inline void pg_fillcomplete(void) int pg_worker(int argc, char *argv[]) { + FAR struct tcb_s *wtcb = this_task(); + /* Loop forever -- Notice that interrupts will be disabled at all times * that this thread runs. That is so that we can't lose signals or have * asynchronous page faults. @@ -567,7 +588,15 @@ int pg_worker(int argc, char *argv[]) */ pginfo("Restarting TCB: %p\n", g_pftcb); - up_unblock_task(g_pftcb); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(g_pftcb)) + { + up_unblock_task(g_pftcb, wtcb); + } /* Yes .. Start the next asynchronous fill. Check the return * value to see a fill was actually started (false means that @@ -644,7 +673,15 @@ int pg_worker(int argc, char *argv[]) */ pginfo("Restarting TCB: %p\n", g_pftcb); - up_unblock_task(g_pftcb); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(g_pftcb)) + { + up_unblock_task(g_pftcb, wtcb); + } } /* All queued fills have been processed */ diff --git a/sched/sched/sched.h b/sched/sched/sched.h index 9dbc3ab2cb..b32a0ddda4 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -186,6 +186,14 @@ extern dq_queue_t g_waitingforsignal; extern dq_queue_t g_waitingforfill; #endif +/* This is the list of all tasks that have been stopped + * via SIGSTOP or SIGTSTP + */ + +#ifdef CONFIG_SIG_SIGSTOP_ACTION +extern dq_queue_t g_stoppedtasks; +#endif + /* This the list of all tasks that have been initialized, but not yet * activated. NOTE: This is the only list that is not prioritized. */ diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index 475bc9d121..07dc2722ed 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -132,10 +132,12 @@ int nxsem_post(FAR sem_t *sem) * that we want. */ - stcb = (FAR struct tcb_s *)dq_peek(SEM_WAITLIST(sem)); + stcb = (FAR struct tcb_s *)dq_remfirst(SEM_WAITLIST(sem)); if (stcb != NULL) { + FAR struct tcb_s *rtcb = this_task(); + /* The task will be the new holder of the semaphore when * it is awakened. */ @@ -149,9 +151,18 @@ int nxsem_post(FAR sem_t *sem) wd_cancel(&stcb->waitdog); } - /* Restart the waiting task. */ + /* Indicate that the wait is over. */ - up_unblock_task(stcb); + stcb->waitobj = NULL; + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(stcb)) + { + up_unblock_task(stcb, rtcb); + } } #if 0 /* REVISIT: This can fire on IOB throttle semaphore */ else diff --git a/sched/semaphore/sem_waitirq.c b/sched/semaphore/sem_waitirq.c index cec1dc9804..5f732fa072 100644 --- a/sched/semaphore/sem_waitirq.c +++ b/sched/semaphore/sem_waitirq.c @@ -31,6 +31,7 @@ #include #include +#include "sched/sched.h" #include "semaphore/semaphore.h" /**************************************************************************** @@ -67,6 +68,7 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode) { + FAR struct tcb_s *rtcb = this_task(); FAR sem_t *sem = wtcb->waitobj; /* It is possible that an interrupt/context switch beat us to the punch @@ -89,11 +91,24 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode) sem->semcount++; + /* Remove task from waiting list */ + + dq_rem((FAR dq_entry_t *)wtcb, SEM_WAITLIST(sem)); + + /* Indicate that the wait is over. */ + + wtcb->waitobj = NULL; + /* Mark the errno value for the thread. */ wtcb->errcode = errcode; - /* Restart the task. */ + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ - up_unblock_task(wtcb); + if (nxsched_add_readytorun(wtcb)) + { + up_unblock_task(wtcb, rtcb); + } } diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index b10337e4af..26eb31dcc2 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "sched/sched.h" #include "group/group.h" @@ -296,6 +297,7 @@ static void nxsig_add_pendingsignal(FAR struct tcb_s *stcb, int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) { + FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; int masked; int ret = OK; @@ -369,7 +371,19 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) wd_cancel(&stcb->waitdog); } - up_unblock_task(stcb); + /* Remove the task from waitting list */ + + dq_rem((FAR dq_entry_t *)stcb, &g_waitingforsignal); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(stcb)) + { + up_unblock_task(stcb, rtcb); + } + leave_critical_section(flags); } @@ -411,7 +425,18 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) wd_cancel(&stcb->waitdog); } - up_unblock_task(stcb); + /* Remove the task from waitting list */ + + dq_rem((FAR dq_entry_t *)stcb, &g_waitingforsignal); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(stcb)) + { + up_unblock_task(stcb, rtcb); + } } leave_critical_section(flags); @@ -464,7 +489,18 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) #ifdef HAVE_GROUP_MEMBERS group_continue(stcb); #else - up_unblock_task(stcb); + /* Remove the task from waitting list */ + + dq_rem((FAR dq_entry_t *)stcb, &g_stoppedtasks); + + /* Add the task to ready-to-run task list and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(stcb)) + { + up_unblock_task(stcb, rtcb); + } #endif } #endif diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index d8c7ffe276..b0a877c228 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "sched/sched.h" #include "signal/signal.h" @@ -96,6 +97,8 @@ static void nxsig_timeout(wdparm_t arg) if (wtcb->task_state == TSTATE_WAIT_SIG) { + FAR struct tcb_s *rtcb = this_task(); + wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT; wtcb->sigunbinfo.si_code = SI_TIMER; wtcb->sigunbinfo.si_errno = ETIMEDOUT; @@ -104,7 +107,19 @@ static void nxsig_timeout(wdparm_t arg) wtcb->sigunbinfo.si_pid = 0; /* Not applicable */ wtcb->sigunbinfo.si_status = OK; #endif - up_unblock_task(wtcb); + + /* Remove the task from waitting list */ + + dq_rem((FAR dq_entry_t *)wtcb, &g_waitingforsignal); + + /* Add the task to ready-to-run task list, and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(wtcb)) + { + up_unblock_task(wtcb, rtcb); + } } #ifdef CONFIG_SMP @@ -149,6 +164,8 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode) if (wtcb->task_state == TSTATE_WAIT_SIG) { + FAR struct tcb_s *rtcb = this_task(); + wtcb->sigunbinfo.si_signo = SIG_CANCEL_TIMEOUT; wtcb->sigunbinfo.si_code = SI_USER; wtcb->sigunbinfo.si_errno = errcode; @@ -157,7 +174,19 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode) wtcb->sigunbinfo.si_pid = 0; /* Not applicable */ wtcb->sigunbinfo.si_status = OK; #endif - up_unblock_task(wtcb); + + /* Remove the task from waitting list */ + + dq_rem((FAR dq_entry_t *)wtcb, &g_waitingforsignal); + + /* Add the task to ready-to-run task list, and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(wtcb)) + { + up_unblock_task(wtcb, rtcb); + } } #ifdef CONFIG_SMP diff --git a/sched/task/task_activate.c b/sched/task/task_activate.c index 27f53137c6..97e6caba25 100644 --- a/sched/task/task_activate.c +++ b/sched/task/task_activate.c @@ -32,6 +32,8 @@ #include #include +#include "sched/sched.h" + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -56,6 +58,7 @@ void nxtask_activate(FAR struct tcb_s *tcb) { irqstate_t flags = enter_critical_section(); + FAR struct tcb_s *rtcb = this_task(); #ifdef CONFIG_SCHED_INSTRUMENTATION @@ -77,6 +80,18 @@ void nxtask_activate(FAR struct tcb_s *tcb) sched_note_start(tcb); #endif - up_unblock_task(tcb); + /* Remove the task from waitting list */ + + nxsched_remove_blocked(tcb); + + /* Add the task to ready-to-run task list, and + * perform the context switch if one is needed + */ + + if (nxsched_add_readytorun(tcb)) + { + up_unblock_task(tcb, rtcb); + } + leave_critical_section(flags); }