diff --git a/Documentation/reference/os/arch.rst b/Documentation/reference/os/arch.rst index 12c9dbbb860..627f6a1af71 100644 --- a/Documentation/reference/os/arch.rst +++ b/Documentation/reference/os/arch.rst @@ -186,21 +186,17 @@ APIs Exported by Architecture-Specific Logic to NuttX 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) +.. c:function:: void up_block_task(FAR struct tcb_s *rtcb) - The currently executing task at the head of the - ready to run list must be stopped. Save its context and move it to - the inactive list specified by task_state. This function is called - only from the NuttX scheduling logic. Interrupts will always be - disabled when this function is called. + The currently executing task has already removed from ready-to-run list. + Save its context and switch to the next running task at the head of the + ready-to-run list. - :param tcb: Refers to a task in the ready-to-run list (normally - the task at the head of the list). It must be stopped, its - context saved and moved into one of the waiting task lists. If - it was the task at the head of the ready-to-run list, then a - context switch to the new ready to run task must be performed. - :param task_state: Specifies which waiting task list should be - hold the blocked task TCB. + This function is called only from the NuttX scheduling logic. + Interrupts will always be disabled when this function is called. + + :param rtcb: Reference to the running task which is different to the + task (next running task) at the head of the list. .. c:function:: void up_release_pending(void) diff --git a/arch/arm/src/common/arm_blocktask.c b/arch/arm/src/common/arm_blocktask.c index dd8cb365a10..1db14cb6d85 100644 --- a/arch/arm/src/common/arm_blocktask.c +++ b/arch/arm/src/common/arm_blocktask.c @@ -44,108 +44,69 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. + */ + + arm_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(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + arm_restorestate(rtcb->xcp.regs); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + struct tcb_s *nexttcb = this_task(); - nxsched_suspend_scheduler(rtcb); + /* Reset scheduler parameters */ - /* Are we in an interrupt handler? */ + nxsched_resume_scheduler(nexttcb); - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - arm_savestate(rtcb->xcp.regs); + arm_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* 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(); - - /* Reset 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/arm/src/common/arm_reprioritizertr.c b/arch/arm/src/common/arm_reprioritizertr.c index d019d9dee76..6a44fb5147f 100644 --- a/arch/arm/src/common/arm_reprioritizertr.c +++ b/arch/arm/src/common/arm_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/arm64/src/common/arm64_blocktask.c b/arch/arm64/src/common/arm64_blocktask.c index f8b79a77c2d..85f9490760c 100644 --- a/arch/arm64/src/common/arm64_blocktask.c +++ b/arch/arm64/src/common/arm64_blocktask.c @@ -44,110 +44,69 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb; - bool switch_needed; + /* Update scheduler parameters */ - rtcb = this_task(); + nxsched_suspend_scheduler(rtcb); - /* Verify that the context switch can be performed */ + /* Are we in an interrupt handler? */ - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); - - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. + */ + + arm64_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(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + arm64_restorestate(rtcb->xcp.regs); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + struct tcb_s *nexttcb = this_task(); - nxsched_suspend_scheduler(rtcb); + /* Reset scheduler parameters */ - /* Are we in an interrupt handler? */ + nxsched_resume_scheduler(nexttcb); - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - arm64_savestate(rtcb->xcp.regs); + arm64_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* 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(); - - /* Reset 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/arm64/src/common/arm64_reprioritizertr.c b/arch/arm64/src/common/arm64_reprioritizertr.c index 8cefcf86e52..437902b31db 100644 --- a/arch/arm64/src/common/arm64_reprioritizertr.c +++ b/arch/arm64/src/common/arm64_reprioritizertr.c @@ -85,7 +85,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/avr/src/avr/up_blocktask.c b/arch/avr/src/avr/up_blocktask.c index 1be4c6751f5..02d3a5b8778 100644 --- a/arch/avr/src/avr/up_blocktask.c +++ b/arch/avr/src/avr/up_blocktask.c @@ -43,106 +43,67 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); + /* 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(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + struct tcb_s *nexttcb = this_task(); - nxsched_suspend_scheduler(rtcb); + /* Reset scheduler parameters */ - /* Are we in an interrupt handler? */ + nxsched_resume_scheduler(nexttcb); - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - up_savestate(rtcb->xcp.regs); + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* 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(); - - /* Reset 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/avr/up_reprioritizertr.c b/arch/avr/src/avr/up_reprioritizertr.c index 7bf1565e963..51c504afd68 100644 --- a/arch/avr/src/avr/up_reprioritizertr.c +++ b/arch/avr/src/avr/up_reprioritizertr.c @@ -86,7 +86,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/avr/src/avr32/up_blocktask.c b/arch/avr/src/avr32/up_blocktask.c index f789aa022b4..5da62c9562f 100644 --- a/arch/avr/src/avr32/up_blocktask.c +++ b/arch/avr/src/avr32/up_blocktask.c @@ -44,120 +44,81 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); + /* 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(); + + /* Reset 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); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + /* Get the context of the task at the head of the ready to + * run list. + */ - nxsched_suspend_scheduler(rtcb); - - /* 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(); - - /* Reset 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 - { - /* Get the context of the task at the head of the ready to - * run list. - */ - - struct tcb_s *nexttcb = this_task(); + struct tcb_s *nexttcb = this_task(); #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(nexttcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(nexttcb); + nxsched_resume_scheduler(nexttcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + 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_reprioritizertr.c b/arch/avr/src/avr32/up_reprioritizertr.c index ccc3bf431cc..7a841387c09 100644 --- a/arch/avr/src/avr32/up_reprioritizertr.c +++ b/arch/avr/src/avr32/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/ceva/src/common/up_blocktask.c b/arch/ceva/src/common/up_blocktask.c index 9ceeb233adc..2fdcbdb70ba 100644 --- a/arch/ceva/src/common/up_blocktask.c +++ b/arch/ceva/src/common/up_blocktask.c @@ -36,108 +36,67 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of - * the ready to run list must be stopped. Save its context - * and move it to the inactive list specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Inputs: - * tcb: Refers to a task in the ready-to-run list (normally - * the task at the head of the list). It most be - * stopped, its context saved and moved into one of the - * waiting task lists. It it was the task at the head - * of the ready-to-run list, then a context to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should be - * hold the blocked task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + sched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we - * are blocking the task at the head of the task list (the - * most likely case), then a context switch to the next - * ready-to-run task is needed. In this case, it should - * also be true that rtcb == tcb. - */ - - switch_needed = sched_removereadytorun(tcb); - - /* Add the task to the specified blocked task list */ - - sched_addblocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= sched_mergepending(); + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. + */ + + rtcb->xcp.regs = CURRENT_REGS; + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + CURRENT_REGS = rtcb->xcp.regs; } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + struct tcb_s *nexttcb = this_task(); - sched_suspend_scheduler(rtcb); + /* Reset scheduler parameters */ - /* Are we in an interrupt handler? */ + sched_resume_scheduler(nexttcb); - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - rtcb->xcp.regs = CURRENT_REGS; + up_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Reset scheduler parameters */ - - sched_resume_scheduler(rtcb); - - /* 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(); - - /* Reset 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_blocktask.c b/arch/hc/src/common/up_blocktask.c index 768d5429fdd..dfc9a86c140 100644 --- a/arch/hc/src/common/up_blocktask.c +++ b/arch/hc/src/common/up_blocktask.c @@ -44,116 +44,77 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* 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(); - - /* Reset 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); - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if up_saveusercontext returns a non-zero - * value, then this is really the previously running task restarting! + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + up_savestate(rtcb->xcp.regs); - rtcb = this_task(); + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset 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); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); #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(rtcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(rtcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(rtcb->xcp.regs); } } diff --git a/arch/hc/src/common/up_reprioritizertr.c b/arch/hc/src/common/up_reprioritizertr.c index 04f074fa84a..4d7c8309982 100644 --- a/arch/hc/src/common/up_reprioritizertr.c +++ b/arch/hc/src/common/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/mips/src/mips32/mips_blocktask.c b/arch/mips/src/mips32/mips_blocktask.c index 5971f02137d..35df1053619 100644 --- a/arch/mips/src/mips32/mips_blocktask.c +++ b/arch/mips/src/mips32/mips_blocktask.c @@ -45,110 +45,71 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + /* 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(); + + /* Reset 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); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + /* Get the context of the task at the head of the ready to + * run list. + */ - nxsched_suspend_scheduler(rtcb); + struct tcb_s *nexttcb = this_task(); - /* Are we in an interrupt handler? */ + /* Reset scheduler parameters */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + nxsched_resume_scheduler(nexttcb); - 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_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - rtcb = this_task(); - - /* Reset 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); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Get the context of the task at the head of the ready to - * run list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Reset 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/mips/src/mips32/mips_reprioritizertr.c b/arch/mips/src/mips32/mips_reprioritizertr.c index 7a99968d9c2..c424592e554 100644 --- a/arch/mips/src/mips32/mips_reprioritizertr.c +++ b/arch/mips/src/mips32/mips_reprioritizertr.c @@ -89,7 +89,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/misoc/src/lm32/lm32_blocktask.c b/arch/misoc/src/lm32/lm32_blocktask.c index 9bed1c02012..78f915d5563 100644 --- a/arch/misoc/src/lm32/lm32_blocktask.c +++ b/arch/misoc/src/lm32/lm32_blocktask.c @@ -45,110 +45,71 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); + /* 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(); + + /* Reset 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); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + /* Get the context of the task at the head of the ready to + * run list. + */ - nxsched_suspend_scheduler(rtcb); + struct tcb_s *nexttcb = this_task(); - /* Are we in an interrupt handler? */ + /* Reset scheduler parameters */ - if (g_current_regs) - { - /* Yes, then we have to do things differently. - * Just copy the g_current_regs into the OLD rtcb. - */ + nxsched_resume_scheduler(nexttcb); - 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_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - rtcb = this_task(); - - /* Reset 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); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Get the context of the task at the head of the ready to - * run list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Reset 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_reprioritizertr.c b/arch/misoc/src/lm32/lm32_reprioritizertr.c index 97a2568b8af..dd4e766a98a 100644 --- a/arch/misoc/src/lm32/lm32_reprioritizertr.c +++ b/arch/misoc/src/lm32/lm32_reprioritizertr.c @@ -89,7 +89,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/misoc/src/minerva/minerva_blocktask.c b/arch/misoc/src/minerva/minerva_blocktask.c index 6c6349af405..07888c91ab9 100644 --- a/arch/misoc/src/minerva/minerva_blocktask.c +++ b/arch/misoc/src/minerva/minerva_blocktask.c @@ -45,110 +45,71 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t) task_state); - - /* If there are any pending tasks, then add them to the ready-to-run task - * list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); + /* 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(); + + /* Reset 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); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + /* Get the context of the task at the head of the ready to run + * list. + */ - nxsched_suspend_scheduler(rtcb); + struct tcb_s *nexttcb = this_task(); - /* Are we in an interrupt handler? */ + /* Reset scheduler parameters */ - if (g_current_regs) - { - /* Yes, then we have to do things differently. Just copy the - * g_current_regs into the OLD rtcb. - */ + nxsched_resume_scheduler(nexttcb); - 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_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - rtcb = this_task(); - - /* Reset 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); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Get the context of the task at the head of the ready to run - * list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Reset 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_reprioritizertr.c b/arch/misoc/src/minerva/minerva_reprioritizertr.c index 00edf654194..387fd0c30ed 100644 --- a/arch/misoc/src/minerva/minerva_reprioritizertr.c +++ b/arch/misoc/src/minerva/minerva_reprioritizertr.c @@ -89,7 +89,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/or1k/src/common/up_blocktask.c b/arch/or1k/src/common/up_blocktask.c index e710fc96424..f3b513409aa 100644 --- a/arch/or1k/src/common/up_blocktask.c +++ b/arch/or1k/src/common/up_blocktask.c @@ -44,116 +44,77 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* Are we in an interrupt handler? */ - - if (CURRENT_REGS) - { - /* 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(); - - /* Reset 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); - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if up_saveusercontext returns a non-zero - * value, then this is really the previously running task restarting! + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + up_savestate(rtcb->xcp.regs); - rtcb = this_task(); + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset 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); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); #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(rtcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(rtcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(rtcb->xcp.regs); } } diff --git a/arch/or1k/src/common/up_reprioritizertr.c b/arch/or1k/src/common/up_reprioritizertr.c index 2a7c315b4af..363e11a900a 100644 --- a/arch/or1k/src/common/up_reprioritizertr.c +++ b/arch/or1k/src/common/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/renesas/src/common/up_blocktask.c b/arch/renesas/src/common/up_blocktask.c index 7b8ac5276ac..83221fcb889 100644 --- a/arch/renesas/src/common/up_blocktask.c +++ b/arch/renesas/src/common/up_blocktask.c @@ -43,117 +43,78 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* 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(); - - /* Reset 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; - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if up_saveusercontext returns a non-zero - * value, then this is really the previously running task - * restarting! + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + up_savestate(rtcb->xcp.regs); - rtcb = this_task(); + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset 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; + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task + * restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); #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(rtcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(rtcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(rtcb->xcp.regs); } } diff --git a/arch/renesas/src/common/up_reprioritizertr.c b/arch/renesas/src/common/up_reprioritizertr.c index c0f03925fa3..cc41f8ace69 100644 --- a/arch/renesas/src/common/up_reprioritizertr.c +++ b/arch/renesas/src/common/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/risc-v/src/common/riscv_blocktask.c b/arch/risc-v/src/common/riscv_blocktask.c index b3833c225a4..94d3207a679 100644 --- a/arch/risc-v/src/common/riscv_blocktask.c +++ b/arch/risc-v/src/common/riscv_blocktask.c @@ -45,110 +45,71 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. + */ + + riscv_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(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + riscv_restorestate(rtcb->xcp.regs); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + /* Get the context of the task at the head of the ready to + * run list. + */ - nxsched_suspend_scheduler(rtcb); + struct tcb_s *nexttcb = this_task(); - /* Are we in an interrupt handler? */ + /* Reset scheduler parameters */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + nxsched_resume_scheduler(nexttcb); - riscv_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. - */ + riscv_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - rtcb = this_task(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* 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 - { - /* Get the context of the task at the head of the ready to - * run list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Reset 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/risc-v/src/common/riscv_reprioritizertr.c b/arch/risc-v/src/common/riscv_reprioritizertr.c index 02c6e9f2e02..53fd2abb343 100644 --- a/arch/risc-v/src/common/riscv_reprioritizertr.c +++ b/arch/risc-v/src/common/riscv_reprioritizertr.c @@ -89,7 +89,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/sim/src/sim/up_blocktask.c b/arch/sim/src/sim/up_blocktask.c index 779d283cce5..acd1d87e641 100644 --- a/arch/sim/src/sim/up_blocktask.c +++ b/arch/sim/src/sim/up_blocktask.c @@ -43,103 +43,62 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* TODO */ - /* sinfo("Blocking TCB=%p\n", tcb); */ - - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + ASSERT(false); } - /* Now, perform the context switch if one is needed */ + /* Copy the exception context into the TCB at the (old) head of the + * ready-to-run Task list. if setjmp returns a non-zero + * value, then this is really the previously running task restarting! + */ - if (switch_needed) + else if (!setjmp(rtcb->xcp.regs)) { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* TODO */ - - if (CURRENT_REGS) - { - ASSERT(false); - } - - /* Copy the exception context into the TCB at the (old) head of the - * ready-to-run Task list. if setjmp returns a non-zero - * value, then this is really the previously running task restarting! + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. */ - else if (!setjmp(rtcb->xcp.regs)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + rtcb = this_task(); + sinfo("New Active Task TCB=%p\n", rtcb); - rtcb = this_task(); - sinfo("New Active Task TCB=%p\n", rtcb); + /* Reset scheduler parameters */ - /* Reset scheduler parameters */ + nxsched_resume_scheduler(rtcb); - nxsched_resume_scheduler(rtcb); + /* Restore the cpu lock */ - /* Restore the cpu lock */ + restore_critical_section(); - restore_critical_section(); + /* Then switch contexts */ - /* 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. + */ - 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/sim/src/sim/up_reprioritizertr.c b/arch/sim/src/sim/up_reprioritizertr.c index db2f143688f..2b5b0807b0e 100644 --- a/arch/sim/src/sim/up_reprioritizertr.c +++ b/arch/sim/src/sim/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/sparc/src/sparc_v8/up_blocktask.c b/arch/sparc/src/sparc_v8/up_blocktask.c index a80b4f48bbd..c932da5a841 100644 --- a/arch/sparc/src/sparc_v8/up_blocktask.c +++ b/arch/sparc/src/sparc_v8/up_blocktask.c @@ -45,112 +45,71 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of - * the ready to run list must be stopped. Save its context - * and move it to the inactive list specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally - * the task at the head of the list). It most be - * stopped, its context saved and moved into one of the - * waiting task lists. It it was the task at the head - * of the ready-to-run list, then a context to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should be - * hold the blocked task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we - * are blocking the task at the head of the task list (the - * most likely case), then a context switch to the next - * ready-to-run task is needed. In this case, it should - * also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + /* 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(); + + /* Reset 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); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + /* Get the context of the task at the head of the ready to + * run list. + */ - nxsched_suspend_scheduler(rtcb); + struct tcb_s *nexttcb = this_task(); - /* Are we in an interrupt handler? */ + /* Reset scheduler parameters */ - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + nxsched_resume_scheduler(nexttcb); - 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_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); - rtcb = this_task(); - - /* Reset 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); - } - - /* No, then we will need to perform the user context switch */ - - else - { - /* Get the context of the task at the head of the ready to - * run list. - */ - - struct tcb_s *nexttcb = this_task(); - - /* Reset 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/sparc/src/sparc_v8/up_reprioritizertr.c b/arch/sparc/src/sparc_v8/up_reprioritizertr.c index 1a8c575328e..cf5946fbaec 100644 --- a/arch/sparc/src/sparc_v8/up_reprioritizertr.c +++ b/arch/sparc/src/sparc_v8/up_reprioritizertr.c @@ -88,7 +88,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/x86/src/common/up_blocktask.c b/arch/x86/src/common/up_blocktask.c index e51dfae5401..0bcaccc60c9 100644 --- a/arch/x86/src/common/up_blocktask.c +++ b/arch/x86/src/common/up_blocktask.c @@ -44,117 +44,78 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* 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(); - - /* Reset 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); - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if up_saveusercontext returns a non-zero - * value, then this is really the previously running task - * restarting! + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the rtcb at the (new) - * head of the ready-to-run task list. - */ + up_savestate(rtcb->xcp.regs); - rtcb = this_task(); + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset 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); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task + * restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) + * head of the ready-to-run task list. + */ + + rtcb = this_task(); #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(rtcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(rtcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(rtcb->xcp.regs); } } diff --git a/arch/x86/src/common/up_reprioritizertr.c b/arch/x86/src/common/up_reprioritizertr.c index 7442508078a..3489854c87d 100644 --- a/arch/x86/src/common/up_reprioritizertr.c +++ b/arch/x86/src/common/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/x86_64/src/common/up_blocktask.c b/arch/x86_64/src/common/up_blocktask.c index f87c5e9a465..11d229fdbcd 100644 --- a/arch/x86_64/src/common/up_blocktask.c +++ b/arch/x86_64/src/common/up_blocktask.c @@ -44,118 +44,79 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (g_current_regs) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* 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); - - /* Reset 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); - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if up_saveusercontext returns a non-zero - * value, then this is really the previously running task restarting! + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. */ - else if (!up_saveusercontext(rtcb->xcp.regs)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + up_savestate(rtcb->xcp.regs); - rtcb = this_task(); - up_restore_auxstate(rtcb); + /* 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); + + /* Reset 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); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(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); #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(rtcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(rtcb); - /* Then switch contexts */ + /* Then switch contexts */ - up_fullcontextrestore(rtcb->xcp.regs); - } + up_fullcontextrestore(rtcb->xcp.regs); } } diff --git a/arch/x86_64/src/common/up_reprioritizertr.c b/arch/x86_64/src/common/up_reprioritizertr.c index 7b4f01da6aa..15f4ae9c7c8 100644 --- a/arch/x86_64/src/common/up_reprioritizertr.c +++ b/arch/x86_64/src/common/up_reprioritizertr.c @@ -87,7 +87,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/xtensa/src/common/xtensa_blocktask.c b/arch/xtensa/src/common/xtensa_blocktask.c index c62ad63064c..4c75cf099d4 100644 --- a/arch/xtensa/src/common/xtensa_blocktask.c +++ b/arch/xtensa/src/common/xtensa_blocktask.c @@ -45,108 +45,69 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(struct tcb_s *tcb, tstate_t task_state) +void up_block_task(struct tcb_s *rtcb) { - struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (CURRENT_REGS) { - switch_needed |= nxsched_merge_pending(); + /* Yes, then we have to do things differently. + * Just copy the CURRENT_REGS into the OLD rtcb. + */ + + xtensa_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(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + xtensa_restorestate(rtcb->xcp.regs); } - /* Now, perform the context switch if one is needed */ + /* No, then we will need to perform the user context switch */ - if (switch_needed) + else { - /* Update scheduler parameters */ + struct tcb_s *nexttcb = this_task(); - nxsched_suspend_scheduler(rtcb); + /* Switch context to the context of the task at the head of the + * ready to run list. + */ - /* Are we in an interrupt handler? */ + nxsched_resume_scheduler(nexttcb); - if (CURRENT_REGS) - { - /* Yes, then we have to do things differently. - * Just copy the CURRENT_REGS into the OLD rtcb. - */ + /* Then switch contexts */ - xtensa_savestate(rtcb->xcp.regs); + xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs); - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ - - rtcb = this_task(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* 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(); - - /* Switch context to the context of the task at the head of the - * ready to run list. - */ - - nxsched_resume_scheduler(nexttcb); - - /* Then switch contexts */ - - 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/xtensa/src/common/xtensa_reprioritizertr.c b/arch/xtensa/src/common/xtensa_reprioritizertr.c index 5360f7fff4c..55eec2dd826 100644 --- a/arch/xtensa/src/common/xtensa_reprioritizertr.c +++ b/arch/xtensa/src/common/xtensa_reprioritizertr.c @@ -89,7 +89,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/z16/src/common/z16_blocktask.c b/arch/z16/src/common/z16_blocktask.c index 0428f7c1878..b6d593b5ce1 100644 --- a/arch/z16/src/common/z16_blocktask.c +++ b/arch/z16/src/common/z16_blocktask.c @@ -43,109 +43,68 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) +void up_block_task(FAR struct tcb_s *rtcb) { - FAR struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* sinfo("Blocking TCB=%p\n", tcb); */ - - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (IN_INTERRUPT) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* Are we in an interrupt handler? */ - - if (IN_INTERRUPT) - { - /* Yes, then we have to do things differently. - * Just copy the current registers 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(); - - /* Reset scheduler parameters */ - - nxsched_resume_scheduler(rtcb); - - /* Then setup so that the context will be performed on exit - * from the interrupt. - */ - - SET_IRQCONTEXT(rtcb); - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if SAVE_USERCONTEXT returns a non-zero - * value, then this is really the previously running task restarting! + /* Yes, then we have to do things differently. + * Just copy the current registers into the OLD rtcb. */ - else if (!SAVE_USERCONTEXT(rtcb)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + SAVE_IRQCONTEXT(rtcb); - rtcb = this_task(); + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ - /* Reset scheduler parameters */ + rtcb = this_task(); - nxsched_resume_scheduler(rtcb); + /* Reset scheduler parameters */ - /* Then switch contexts */ + nxsched_resume_scheduler(rtcb); - RESTORE_USERCONTEXT(rtcb); - } + /* Then setup so that the context will be performed on exit + * from the interrupt. + */ + + SET_IRQCONTEXT(rtcb); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if SAVE_USERCONTEXT returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!SAVE_USERCONTEXT(rtcb)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + RESTORE_USERCONTEXT(rtcb); } } diff --git a/arch/z16/src/common/z16_reprioritizertr.c b/arch/z16/src/common/z16_reprioritizertr.c index 15a9124b7ad..8e57088d2af 100644 --- a/arch/z16/src/common/z16_reprioritizertr.c +++ b/arch/z16/src/common/z16_reprioritizertr.c @@ -88,7 +88,7 @@ void up_reprioritize_rtr(FAR struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/arch/z80/src/common/z80_blocktask.c b/arch/z80/src/common/z80_blocktask.c index ed40a561058..9cf83eb48cf 100644 --- a/arch/z80/src/common/z80_blocktask.c +++ b/arch/z80/src/common/z80_blocktask.c @@ -45,119 +45,78 @@ * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * Input Parameters: - * tcb: Refers to a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new - * ready to run task must be performed. - * task_state: Specifies which waiting task list should hold the blocked - * task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) +void up_block_task(FAR struct tcb_s *rtcb) { - FAR struct tcb_s *rtcb = this_task(); - bool switch_needed; + /* Update scheduler parameters */ - /* Verify that the context switch can be performed */ + nxsched_suspend_scheduler(rtcb); - DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && - (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + /* Are we in an interrupt handler? */ - /* _info("Blocking TCB=%p\n", tcb); */ - - /* Remove the tcb task from the ready-to-run list. If we are blocking the - * task at the head of the task list (the most likely case), then a - * context switch to the next ready-to-run task is needed. In this case, - * it should also be true that rtcb == tcb. - */ - - switch_needed = nxsched_remove_readytorun(tcb); - - /* Add the task to the specified blocked task list */ - - nxsched_add_blocked(tcb, (tstate_t)task_state); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head) + if (IN_INTERRUPT()) { - switch_needed |= nxsched_merge_pending(); - } - - /* Now, perform the context switch if one is needed */ - - if (switch_needed) - { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(rtcb); - - /* Are we in an interrupt handler? */ - - if (IN_INTERRUPT()) - { - /* Yes, then we have to do things differently. - * Just copy the current registers 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(); - - /* Reset 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); - } - - /* Copy the user C context into the TCB at the (old) head of the - * ready-to-run Task list. if SAVE_USERCONTEXT returns a non-zero - * value, then this is really the previously running task restarting! + /* Yes, then we have to do things differently. + * Just copy the current registers into the OLD rtcb. */ - else if (!SAVE_USERCONTEXT(rtcb)) - { - /* Restore the exception context of the rtcb at the (new) head - * of the ready-to-run task list. - */ + SAVE_IRQCONTEXT(rtcb); - rtcb = this_task(); + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset 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); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if SAVE_USERCONTEXT returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!SAVE_USERCONTEXT(rtcb)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); #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(rtcb); #endif - /* Reset scheduler parameters */ + /* Reset scheduler parameters */ - nxsched_resume_scheduler(rtcb); + nxsched_resume_scheduler(rtcb); - /* Then switch contexts */ + /* Then switch contexts */ - RESTORE_USERCONTEXT(rtcb); - } + RESTORE_USERCONTEXT(rtcb); } } diff --git a/arch/z80/src/common/z80_reprioritizertr.c b/arch/z80/src/common/z80_reprioritizertr.c index 5ceb2ca57d1..9d5f97bdca3 100644 --- a/arch/z80/src/common/z80_reprioritizertr.c +++ b/arch/z80/src/common/z80_reprioritizertr.c @@ -90,7 +90,7 @@ void up_reprioritize_rtr(FAR struct tcb_s *tcb, uint8_t priority) * remove the head of the ready to run list. */ - switch_needed = nxsched_remove_readytorun(tcb); + switch_needed = nxsched_remove_readytorun(tcb, false); /* Setup up the new task priority */ diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 6eee128995e..dd45c4de5d8 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -407,25 +407,20 @@ void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb); * Name: up_block_task * * Description: - * The currently executing task at the head of the ready to run list must - * be stopped. Save its context and move it to the inactive list - * specified by task_state. + * The currently executing task has already removed from ready-to-run list. + * Save its context and switch to the next running task at the head of the + * ready-to-run list. * * 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 a task in the ready-to-run list (normally the task at - * the head of the list). It must be stopped, its context saved and - * moved into one of the waiting task lists. If it was the task at the - * head of the ready-to-run list, then a context switch to the new ready - * to run task must be performed. - * task_state: Specifies which waiting task list should be - * hold the blocked task TCB. + * rtcb: Reference to the running task which is different to the + * task (next running task) at the head of the list. * ****************************************************************************/ -void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state); +void up_block_task(FAR struct tcb_s *rtcb); /**************************************************************************** * Name: up_release_pending diff --git a/sched/mqueue/mq_rcvinternal.c b/sched/mqueue/mq_rcvinternal.c index c22604658f6..ad1f74197fe 100644 --- a/sched/mqueue/mq_rcvinternal.c +++ b/sched/mqueue/mq_rcvinternal.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -135,6 +136,7 @@ int nxmq_wait_receive(FAR struct mqueue_inode_s *msgq, { FAR struct mqueue_msg_s *newmsg; FAR struct tcb_s *rtcb; + bool switch_needed; DEBUGASSERT(rcvmsg != NULL); @@ -181,7 +183,22 @@ int nxmq_wait_receive(FAR struct mqueue_inode_s *msgq, */ DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_MQNOTEMPTY); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_MQNOTEMPTY; + nxsched_add_prioritized(rtcb, MQ_WNELIST(msgq->cmn)); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* When we resume at this point, either (1) the message queue * is no longer empty, or (2) the wait has been interrupted by diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c index d74f9301c31..0df671bde97 100644 --- a/sched/mqueue/mq_sndinternal.c +++ b/sched/mqueue/mq_sndinternal.c @@ -213,6 +213,7 @@ FAR struct mqueue_msg_s *nxmq_alloc_msg(void) int nxmq_wait_send(FAR struct mqueue_inode_s *msgq, int oflags) { FAR struct tcb_s *rtcb; + bool switch_needed; #ifdef CONFIG_CANCELLATION_POINTS /* nxmq_wait_send() is not a cancellation point, but may be called via @@ -267,7 +268,22 @@ int nxmq_wait_send(FAR struct mqueue_inode_s *msgq, int oflags) */ DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_MQNOTFULL; + nxsched_add_prioritized(rtcb, MQ_WNFLIST(msgq->cmn)); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* When we resume at this point, either (1) the message queue * is no longer empty, or (2) the wait has been interrupted by diff --git a/sched/mqueue/msgrcv.c b/sched/mqueue/msgrcv.c index 23a33a6abfb..d4def19463c 100644 --- a/sched/mqueue/msgrcv.c +++ b/sched/mqueue/msgrcv.c @@ -43,6 +43,7 @@ static int msgrcv_wait(FAR struct msgq_s *msgq, FAR struct msgbuf_s **rcvmsg, FAR struct msgbuf_s *newmsg = NULL; FAR struct msgbuf_s *tmp; FAR struct tcb_s *rtcb; + bool switch_needed; #ifdef CONFIG_CANCELLATION_POINTS /* msgrcv_wait() is not a cancellation point, but it may be called @@ -125,7 +126,22 @@ static int msgrcv_wait(FAR struct msgq_s *msgq, FAR struct msgbuf_s **rcvmsg, */ DEBUGASSERT(NULL != rtcb->flink); - up_block_task(rtcb, TSTATE_WAIT_MQNOTEMPTY); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_MQNOTEMPTY; + nxsched_add_prioritized(rtcb, MQ_WNELIST(msgq->cmn)); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* When we resume at this point, either (1) the message queue * is no longer empty, or (2) the wait has been interrupted by diff --git a/sched/mqueue/msgsnd.c b/sched/mqueue/msgsnd.c index f10407b132e..343137e9cd9 100644 --- a/sched/mqueue/msgsnd.c +++ b/sched/mqueue/msgsnd.c @@ -40,6 +40,7 @@ static int msgsnd_wait(FAR struct msgq_s *msgq, int msgflg) { FAR struct tcb_s *rtcb; + bool switch_needed; #ifdef CONFIG_CANCELLATION_POINTS /* msgsnd_wait() is not a cancellation point, but may be called via @@ -91,7 +92,22 @@ static int msgsnd_wait(FAR struct msgq_s *msgq, int msgflg) */ DEBUGASSERT(NULL != rtcb->flink); - up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_MQNOTFULL; + nxsched_add_prioritized(rtcb, MQ_WNFLIST(msgq->cmn)); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* When we resume at this point, either (1) the message queue * is no longer empty, or (2) the wait has been interrupted by diff --git a/sched/paging/pg_miss.c b/sched/paging/pg_miss.c index 05ed83606e3..6584323083c 100644 --- a/sched/paging/pg_miss.c +++ b/sched/paging/pg_miss.c @@ -110,6 +110,7 @@ void pg_miss(void) { FAR struct tcb_s *ftcb = this_task(); FAR struct tcb_s *wtcb; + bool switch_needed; /* Sanity checking * @@ -134,7 +135,22 @@ void pg_miss(void) */ DEBUGASSERT(!is_idle_task(ftcb)); - up_block_task(ftcb, TSTATE_WAIT_PAGEFILL); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(ftcb, true); + + /* Add the task to the specified blocked task list */ + + ftcb->task_state = TSTATE_WAIT_PAGEFILL; + nxsched_add_prioritized(ftcb, &g_waitingforfill); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(ftcb); + } /* Boost the page fill worker thread priority. * - Check the priority of the task at the head of the g_waitingforfill diff --git a/sched/sched/sched.h b/sched/sched/sched.h index b32a0ddda4c..1a43f47dd40 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -314,7 +314,7 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority, /* Task list manipulation functions */ bool nxsched_add_readytorun(FAR struct tcb_s *rtrtcb); -bool nxsched_remove_readytorun(FAR struct tcb_s *rtrtcb); +bool nxsched_remove_readytorun(FAR struct tcb_s *rtrtcb, bool merge); bool nxsched_add_prioritized(FAR struct tcb_s *tcb, DSEG dq_queue_t *list); void nxsched_merge_prioritized(FAR dq_queue_t *list1, FAR dq_queue_t *list2, uint8_t task_state); diff --git a/sched/sched/sched_removereadytorun.c b/sched/sched/sched_removereadytorun.c index 0b168a15fbe..bd3c26ebd47 100644 --- a/sched/sched/sched_removereadytorun.c +++ b/sched/sched/sched_removereadytorun.c @@ -45,6 +45,7 @@ * * Input Parameters: * rtcb - Points to the TCB that is ready-to-run + * merge - Merge pending list or not * * Returned Value: * true if the currently active task (the head of the ready-to-run list) @@ -60,7 +61,7 @@ ****************************************************************************/ #ifndef CONFIG_SMP -bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb) +bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb, bool merge) { bool doswitch = false; @@ -92,6 +93,12 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb) /* Since the TCB is not in any list, it is now invalid */ rtcb->task_state = TSTATE_TASK_INVALID; + + if (g_pendingtasks.head && merge) + { + doswitch |= nxsched_merge_pending(); + } + return doswitch; } #endif /* !CONFIG_SMP */ @@ -104,6 +111,7 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb) * * Input Parameters: * rtcb - Points to the TCB that is ready-to-run + * merge - Merge pending list or not * * Returned Value: * true if the currently active task (the head of the ready-to-run list) @@ -119,7 +127,7 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb) ****************************************************************************/ #ifdef CONFIG_SMP -bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb) +bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb, bool merge) { FAR dq_queue_t *tasklist; bool doswitch = false; @@ -276,6 +284,11 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb) rtcb->task_state = TSTATE_TASK_INVALID; + if (g_pendingtasks.head && merge) + { + doswitch |= nxsched_merge_pending(); + } + return doswitch; } #endif /* CONFIG_SMP */ diff --git a/sched/sched/sched_setpriority.c b/sched/sched/sched_setpriority.c index 2ae5bc11e72..292efca14cb 100644 --- a/sched/sched/sched_setpriority.c +++ b/sched/sched/sched_setpriority.c @@ -236,7 +236,7 @@ static void nxsched_readytorun_setpriority(FAR struct tcb_s *tcb, * It should not be at the head of the list. */ - bool check = nxsched_remove_readytorun(tcb); + bool check = nxsched_remove_readytorun(tcb, false); DEBUGASSERT(check == false); UNUSED(check); diff --git a/sched/sched/sched_suspend.c b/sched/sched/sched_suspend.c index 7936b7c7d48..c8725f261eb 100644 --- a/sched/sched/sched_suspend.c +++ b/sched/sched/sched_suspend.c @@ -50,6 +50,7 @@ void nxsched_suspend(FAR struct tcb_s *tcb) { irqstate_t flags; + bool switch_needed; DEBUGASSERT(tcb != NULL); @@ -73,10 +74,13 @@ void nxsched_suspend(FAR struct tcb_s *tcb) /* Move the TCB to the g_stoppedtasks list. */ - nxsched_add_blocked(tcb, TSTATE_TASK_STOPPED); + tcb->task_state = TSTATE_TASK_STOPPED; + dq_addlast((FAR dq_entry_t *)tcb, &g_stoppedtasks); } else { + FAR struct tcb_s *rtcb = this_task(); + /* The task was running or runnable before being stopped. Simply * block it in the stopped state. If tcb refers to this task, then * this action will block this task. @@ -85,7 +89,22 @@ void nxsched_suspend(FAR struct tcb_s *tcb) */ DEBUGASSERT(!is_idle_task(tcb)); - up_block_task(tcb, TSTATE_TASK_STOPPED); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(tcb, true); + + /* Add the task to the specified blocked task list */ + + tcb->task_state = TSTATE_TASK_STOPPED; + dq_addlast((FAR dq_entry_t *)tcb, &g_stoppedtasks); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } } leave_critical_section(flags); diff --git a/sched/semaphore/sem_wait.c b/sched/semaphore/sem_wait.c index 67e17224699..421f37d92a2 100644 --- a/sched/semaphore/sem_wait.c +++ b/sched/semaphore/sem_wait.c @@ -72,6 +72,7 @@ int nxsem_wait(FAR sem_t *sem) { FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; + bool switch_needed; int ret; /* This API should not be called from interrupt handlers & idleloop */ @@ -150,7 +151,22 @@ int nxsem_wait(FAR sem_t *sem) */ DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_SEM); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_SEM; + nxsched_add_prioritized(rtcb, SEM_WAITLIST(sem)); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* When we resume at this point, either (1) the semaphore has been * assigned to this thread of execution, or (2) the semaphore wait diff --git a/sched/signal/sig_suspend.c b/sched/signal/sig_suspend.c index 0937095595a..bb45c49b7ac 100644 --- a/sched/signal/sig_suspend.c +++ b/sched/signal/sig_suspend.c @@ -80,6 +80,7 @@ int sigsuspend(FAR const sigset_t *set) FAR struct tcb_s *rtcb = this_task(); sigset_t saved_sigprocmask; irqstate_t flags; + bool switch_needed; /* sigsuspend() is a cancellation point */ @@ -123,7 +124,22 @@ int sigsuspend(FAR const sigset_t *set) */ DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_SIG; + dq_addlast((FAR dq_entry_t *)rtcb, &g_waitingforsignal); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* We are running again, restore the original sigprocmask */ diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index b0a877c2285..151842c29ab 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -243,6 +243,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, FAR sigpendq_t *sigpend; irqstate_t flags; int32_t waitticks; + bool switch_needed; int ret; DEBUGASSERT(set != NULL); @@ -351,7 +352,22 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, */ DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_SIG; + dq_addlast((FAR dq_entry_t *)rtcb, &g_waitingforsignal); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } /* We no longer need the watchdog */ @@ -378,7 +394,22 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, */ DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* Remove the tcb task from the ready-to-run list. */ + + switch_needed = nxsched_remove_readytorun(rtcb, true); + + /* Add the task to the specified blocked task list */ + + rtcb->task_state = TSTATE_WAIT_SIG; + dq_addlast((FAR dq_entry_t *)rtcb, &g_waitingforsignal); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + up_block_task(rtcb); + } } /* We are running again, clear the sigwaitmask */ diff --git a/sched/task/task_exit.c b/sched/task/task_exit.c index a66d01de3b5..72ced42e9bf 100644 --- a/sched/task/task_exit.c +++ b/sched/task/task_exit.c @@ -100,16 +100,7 @@ int nxtask_exit(void) * ready-to-run with state == TSTATE_TASK_RUNNING */ - nxsched_remove_readytorun(dtcb); - - /* If there are any pending tasks, then add them to the ready-to-run - * task list now - */ - - if (g_pendingtasks.head != NULL) - { - nxsched_merge_pending(); - } + nxsched_remove_readytorun(dtcb, true); /* Get the new task at the head of the ready to run list */