nuttx/sched: remove nxsched_remove_blocked from up_unblock_task

It takes about 10 cycles to obtain the task list according to the task
status. In most cases, we know the task status, so we can directly
delete the task from the specified task list to reduce time consuming.
This commit is contained in:
zhangyuan21 2022-11-01 09:52:11 +08:00 committed by Masayuki Ishikawa
parent ae46cd4fa1
commit e54b602208
34 changed files with 933 additions and 1380 deletions

View File

@ -174,19 +174,17 @@ APIs Exported by Architecture-Specific Logic to NuttX
and threads must have come from memory that is accessible to
user
.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb)
.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
A task is currently in an inactive task list but
has been prepped to execute. Move the TCB to the ready-to-run
list, restore its context, and start execution.
A task is currently in the ready-to-run list but has been preppe
to execute. Restore its context, and start execution.
This function is called only from the NuttX scheduling logic.
Interrupts will always be disabled when this function is called.
:param tcb: Refers to the tcb to be unblocked. This tcb is in one
of the waiting tasks lists. It must be moved to the
ready-to-run list and, if it is the highest priority ready to
run tasks, executed.
:param tcb: Refers to the head task of the ready-to-run list
which will be executed.
:param rtcb: Refers to the running task which will be blocked.
.. c:function:: void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state)

View File

@ -43,93 +43,61 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
arm_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
arm_restorestate(tcb->xcp.regs);
}
arm_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
nxsched_resume_scheduler(rtcb);
arm_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
arm_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
arm_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
/* arm_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* arm_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -43,93 +43,61 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
arm64_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
arm64_restorestate(tcb->xcp.regs);
}
arm64_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
nxsched_resume_scheduler(rtcb);
arm64_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
arm64_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
arm64_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
/* arm_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* arm_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -42,91 +42,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts */
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_restorestate(tcb->xcp.regs);
}
up_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
nxsched_resume_scheduler(rtcb);
up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts */
up_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -43,106 +43,69 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any new address environment needed by
* the new thread will be instantiated before the return from
* interrupt.
*/
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_restorestate(tcb->xcp.regs);
}
up_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then switch contexts. Any new address environment needed by
* the new thread will be instantiated before the return from
* interrupt.
*/
up_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
struct tcb_s *nexttcb = this_task();
/* No, then we will need to perform the user context switch */
else
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(nexttcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -38,91 +38,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Inputs:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run taks, executed.
* Input Parameters:
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
sched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
sched_removeblocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (sched_addreadytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
rtcb->xcp.regs = CURRENT_REGS;
/* Update scheduler parameters */
sched_suspend_scheduler(rtcb);
sched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts */
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
CURRENT_REGS = tcb->xcp.regs;
}
rtcb->xcp.regs = CURRENT_REGS;
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
sched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
sched_resume_scheduler(rtcb);
up_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts */
CURRENT_REGS = rtcb->xcp.regs;
}
/* No, then we will need to perform the user context switch */
else
{
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
sched_resume_scheduler(nexttcb);
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
up_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -43,103 +43,66 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
up_restorestate(tcb->xcp.regs);
}
rtcb = this_task();
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(rtcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
up_fullcontextrestore(rtcb->xcp.regs);
}
up_fullcontextrestore(tcb->xcp.regs);
}
}

View File

@ -45,96 +45,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_restorestate(tcb->xcp.regs);
}
up_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Then switch contexts */
nxsched_resume_scheduler(rtcb);
up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Then switch contexts */
up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -45,96 +45,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_restorestate(tcb->xcp.regs);
}
up_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Then switch contexts */
nxsched_resume_scheduler(rtcb);
up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Then switch contexts */
up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -45,96 +45,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized ready-to-run
* task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do a context
* switch to the new task.
/* Yes, then we have to do things differently. Just copy the
* g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment changes
* will be made when the interrupt returns.
*/
if (g_current_regs)
{
/* Yes, then we have to do things differently. Just copy the
* g_current_regs into the OLD rtcb.
*/
up_restorestate(tcb->xcp.regs);
}
up_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head of
* the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Then switch contexts */
nxsched_resume_scheduler(rtcb);
up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment changes
* will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Then switch contexts */
up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the head
* of the ready-to-run list. It does not 'return' in the normal
* sense. When it does return, it is because the blocked task is
* again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the head
* of the ready-to-run list. It does not 'return' in the normal
* sense. When it does return, it is because the blocked task is
* again ready to run and has execution priority.
*/
}
}

View File

@ -43,107 +43,70 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
#if 0 /* REVISIT */
if (CURRENT_REGS)
#else
if (0)
#endif
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
#if 0 /* REVISIT */
if (CURRENT_REGS)
#else
if (0)
#endif
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
up_restorestate(tcb->xcp.regs);
}
rtcb = this_task();
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(rtcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
up_fullcontextrestore(rtcb->xcp.regs);
}
up_fullcontextrestore(tcb->xcp.regs);
}
}

View File

@ -43,103 +43,66 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
g_current_regs = rtcb->xcp.regs;
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
g_current_regs = tcb->xcp.regs;
}
rtcb = this_task();
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(rtcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
up_fullcontextrestore(rtcb->xcp.regs);
}
up_fullcontextrestore(tcb->xcp.regs);
}
}

View File

@ -45,96 +45,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
riscv_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
riscv_restorestate(tcb->xcp.regs);
}
riscv_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Then switch contexts */
nxsched_resume_scheduler(rtcb);
riscv_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
riscv_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Then switch contexts */
riscv_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
/* riscv_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* riscv_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -42,109 +42,75 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Verify that the context switch can be performed */
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
sinfo("Unblocking TCB=%p\n", tcb);
/* Remove the task from the blocked task list */
/* Update scheduler parameters */
nxsched_remove_blocked(tcb);
nxsched_suspend_scheduler(rtcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
/* Are we in an interrupt handler? */
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! */
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Restore the cpu lock */
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
restore_critical_section();
up_savestate(rtcb->xcp.regs);
/* Then switch contexts */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
up_restorestate(tcb->xcp.regs);
}
rtcb = this_task();
/* Copy the exception context into the TCB of the task that was
* previously active. if setjmp returns a non-zero value, then
* this is really the previously running task restarting!
*/
/* Update scheduler parameters */
else if (!setjmp(rtcb->xcp.regs))
{
sinfo("New Active Task TCB=%p\n", tcb);
nxsched_resume_scheduler(rtcb);
/* Update scheduler parameters */
/* Restore the cpu lock */
nxsched_resume_scheduler(tcb);
restore_critical_section();
/* Restore the cpu lock */
/* Then switch contexts */
restore_critical_section();
up_restorestate(rtcb->xcp.regs);
}
/* Then switch contexts */
/* Copy the exception context into the TCB of the task that was
* previously active. if setjmp returns a non-zero value, then
* this is really the previously running task restarting!
longjmp(tcb->xcp.regs, 1);
}
else
{
/* The way that we handle signals in the simulation is kind of
* a kludge. This would be unsafe in a truly multi-threaded,
* interrupt driven environment.
*/
else if (!setjmp(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
rtcb = this_task();
sinfo("New Active Task TCB=%p\n", rtcb);
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Restore the cpu lock */
restore_critical_section();
/* Then switch contexts */
longjmp(rtcb->xcp.regs, 1);
}
else
{
/* The way that we handle signals in the simulation is kind of
* a kludge. This would be unsafe in a truly multi-threaded,
* interrupt driven environment.
*/
sim_sigdeliver();
}
sim_sigdeliver();
}
}

View File

@ -45,96 +45,59 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
up_restorestate(tcb->xcp.regs);
}
up_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Update scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Then switch contexts */
nxsched_resume_scheduler(rtcb);
up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
struct tcb_s *nexttcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Then switch contexts */
up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* up_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -43,102 +43,66 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list but has been prepped to
* execute. Move the TCB to the ready-to-run list, restore its context,
* and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is in one of the
* waiting tasks lists. It must be moved to the ready-to-run list and,
* if it is the highest priority ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
up_restorestate(tcb->xcp.regs);
}
rtcb = this_task();
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(rtcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
up_fullcontextrestore(rtcb->xcp.regs);
}
up_fullcontextrestore(tcb->xcp.regs);
}
}

View File

@ -45,104 +45,70 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list but has been prepped to
* execute. Move the TCB to the ready-to-run list, restore its context,
* and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is in one of the
* waiting tasks lists. It must be moved to the ready-to-run list and,
* if it is the highest priority ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (g_current_regs)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
up_restore_auxstate(tcb);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
if (g_current_regs)
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/
up_savestate(rtcb->xcp.regs);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
up_restore_auxstate(rtcb);
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
up_restorestate(rtcb->xcp.regs);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
up_restorestate(tcb->xcp.regs);
}
rtcb = this_task();
up_restore_auxstate(rtcb);
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* up_saveusercontext returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!up_saveusercontext(rtcb->xcp.regs))
{
up_restore_auxstate(tcb);
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(rtcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
up_fullcontextrestore(rtcb->xcp.regs);
}
up_fullcontextrestore(tcb->xcp.regs);
}
}

View File

@ -45,93 +45,61 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(struct tcb_s *tcb)
void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
{
struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (CURRENT_REGS)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
xtensa_savestate(rtcb->xcp.regs);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
if (CURRENT_REGS)
{
/* Yes, then we have to do things differently.
* Just copy the CURRENT_REGS into the OLD rtcb.
*/
xtensa_restorestate(tcb->xcp.regs);
}
xtensa_savestate(rtcb->xcp.regs);
/* No, then we will need to perform the user context switch */
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
else
{
/* Reset scheduler parameters */
rtcb = this_task();
nxsched_resume_scheduler(tcb);
/* Update scheduler parameters */
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
nxsched_resume_scheduler(rtcb);
xtensa_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
xtensa_restorestate(rtcb->xcp.regs);
}
/* No, then we will need to perform the user context switch */
else
{
struct tcb_s *nexttcb = this_task();
/* Reset scheduler parameters */
nxsched_resume_scheduler(nexttcb);
/* Switch context to the context of the task at the head of the
* ready to run list.
*/
xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
/* xtensa_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
/* xtensa_switchcontext forces a context switch to the task at the
* head of the ready-to-run list. It does not 'return' in the
* normal sense. When it does return, it is because the blocked
* task is again ready to run and has execution priority.
*/
}
}

View File

@ -44,96 +44,57 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(FAR struct tcb_s *tcb)
void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
{
FAR struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* sinfo("Unblocking TCB=%p\n", tcb); */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (IN_INTERRUPT)
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the current context into the OLD rtcb.
*/
SAVE_IRQCONTEXT(rtcb);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
if (IN_INTERRUPT)
{
/* Yes, then we have to do things differently.
* Just copy the current context into the OLD rtcb.
*/
SAVE_IRQCONTEXT(rtcb);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then setup so that the context will be performed on exit
* from the interrupt.
*/
SET_IRQCONTEXT(rtcb);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* SAVE_USERCONTEXT returns a non-zero value, then this is really the
* previously running task restarting!
/* Then setup so that the context will be performed on exit
* from the interrupt.
*/
else if (!SAVE_USERCONTEXT(rtcb))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
SET_IRQCONTEXT(tcb);
}
rtcb = this_task();
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* SAVE_USERCONTEXT returns a non-zero value, then this is really the
* previously running task restarting!
*/
/* Update scheduler parameters */
else if (!SAVE_USERCONTEXT(rtcb))
{
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
RESTORE_USERCONTEXT(rtcb);
}
RESTORE_USERCONTEXT(tcb);
}
}

View File

@ -46,106 +46,67 @@
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(FAR struct tcb_s *tcb)
void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
{
FAR struct tcb_s *rtcb = this_task();
/* Update scheduler parameters */
/* Verify that the context switch can be performed */
nxsched_suspend_scheduler(rtcb);
DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
(tcb->task_state <= LAST_BLOCKED_STATE));
/* Are we in an interrupt handler? */
/* _info("Unblocking TCB=%p\n", tcb); */
/* Remove the task from the blocked task list */
nxsched_remove_blocked(tcb);
/* Add the task in the correct location in the prioritized
* ready-to-run task list
*/
if (nxsched_add_readytorun(tcb))
if (IN_INTERRUPT())
{
/* The currently active task has changed! We need to do
* a context switch to the new task.
/* Yes, then we have to do things differently.
* Just copy the current context into the OLD rtcb.
*/
SAVE_IRQCONTEXT(rtcb);
/* Update scheduler parameters */
nxsched_suspend_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Are we in an interrupt handler? */
if (IN_INTERRUPT())
{
/* Yes, then we have to do things differently.
* Just copy the current context into the OLD rtcb.
*/
SAVE_IRQCONTEXT(rtcb);
/* Restore the exception context of the rtcb at the (new) head
* of the ready-to-run task list.
*/
rtcb = this_task();
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
/* Then setup so that the context will be performed on exit
* from the interrupt. Any necessary address environment
* changes will be made when the interrupt returns.
*/
SET_IRQCONTEXT(rtcb);
}
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* SAVE_USERCONTEXT returns a non-zero value, then this is really the
* previously running task restarting!
/* Then setup so that the context will be performed on exit
* from the interrupt. Any necessary address environment
* changes will be made when the interrupt returns.
*/
else if (!SAVE_USERCONTEXT(rtcb))
{
/* Restore the exception context of the new task that is ready to
* run (probably tcb). This is the new rtcb at the head of the
* ready-to-run task list.
*/
SET_IRQCONTEXT(tcb);
}
rtcb = this_task();
/* We are not in an interrupt handler. Copy the user C context
* into the TCB of the task that was previously active. if
* SAVE_USERCONTEXT returns a non-zero value, then this is really the
* previously running task restarting!
*/
else if (!SAVE_USERCONTEXT(rtcb))
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
* thread at the head of the ready-to-run list.
*/
group_addrenv(rtcb);
group_addrenv(tcb);
#endif
/* Update scheduler parameters */
/* Update scheduler parameters */
nxsched_resume_scheduler(rtcb);
nxsched_resume_scheduler(tcb);
/* Then switch contexts */
/* Then switch contexts */
RESTORE_USERCONTEXT(rtcb);
}
RESTORE_USERCONTEXT(tcb);
}
}

View File

@ -387,23 +387,21 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype);
* Name: up_unblock_task
*
* Description:
* A task is currently in an inactive task list
* but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution.
* A task is currently in the ready-to-run list but has been prepped
* to execute. Restore its context, and start execution.
*
* This function is called only from the NuttX scheduling
* logic. Interrupts will always be disabled when this
* function is called.
*
* Input Parameters:
* tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to
* the ready-to-run list and, if it is the highest priority
* ready to run task, executed.
* tcb: Refers to the head task of the ready-to-run list
* which will be executed.
* rtcb: Refers to the running task which will be blocked.
*
****************************************************************************/
void up_unblock_task(FAR struct tcb_s *tcb);
void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb);
/****************************************************************************
* Name: up_block_task

View File

@ -57,6 +57,7 @@
static int group_continue_handler(pid_t pid, FAR void *arg)
{
FAR struct tcb_s *tcb = this_task();
FAR struct tcb_s *rtcb;
/* Resume all threads */
@ -64,7 +65,18 @@ static int group_continue_handler(pid_t pid, FAR void *arg)
rtcb = nxsched_get_tcb(pid);
if (rtcb != NULL)
{
up_unblock_task(rtcb);
/* Remove the task from waitting list */
nxsched_remove_blocked(rtcb);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(rtcb))
{
up_unblock_task(rtcb, tcb);
}
}
/* Always return zero. We need to visit each member of the group */

View File

@ -279,13 +279,15 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq,
if (msgq->cmn.nwaitnotfull > 0)
{
FAR struct tcb_s *rtcb = this_task();
/* Find the highest priority task that is waiting for
* this queue to be not-full in waitfornotfull list.
* This must be performed in a critical section because
* messages can be sent from interrupt handlers.
*/
btcb = (FAR struct tcb_s *)dq_peek(MQ_WNFLIST(msgq->cmn));
btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn));
/* If one was found, unblock it. NOTE: There is a race
* condition here: the queue might be full again by the
@ -300,7 +302,19 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq,
}
msgq->cmn.nwaitnotfull--;
up_unblock_task(btcb);
/* Indicate that the wait is over. */
btcb->waitobj = NULL;
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(btcb))
{
up_unblock_task(btcb, rtcb);
}
}
/* Return the length of the message transferred to the user buffer */

View File

@ -388,6 +388,8 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
if (msgq->cmn.nwaitnotempty > 0)
{
FAR struct tcb_s *rtcb = this_task();
/* Find the highest priority task that is waiting for
* this queue to be non-empty in waitfornotempty
* list. leave_critical_section() should give us sufficient
@ -395,7 +397,7 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
* in this list
*/
btcb = (FAR struct tcb_s *)dq_peek(MQ_WNELIST(msgq->cmn));
btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn));
/* If one was found, unblock it */
@ -407,7 +409,19 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
}
msgq->cmn.nwaitnotempty--;
up_unblock_task(btcb);
/* Indicate that the wait is over. */
btcb->waitobj = NULL;
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(btcb))
{
up_unblock_task(btcb, rtcb);
}
}
return OK;

View File

@ -33,6 +33,7 @@
#include <nuttx/mqueue.h>
#include "mqueue/mqueue.h"
#include "sched/sched.h"
/****************************************************************************
* Public Functions
@ -61,6 +62,7 @@
void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode)
{
FAR struct tcb_s *rtcb = this_task();
FAR struct mqueue_inode_s *msgq;
/* It is possible that an interrupt/context switch beat us to the punch and
@ -80,18 +82,29 @@ void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode)
{
DEBUGASSERT(msgq->cmn.nwaitnotempty > 0);
msgq->cmn.nwaitnotempty--;
dq_rem((FAR dq_entry_t *)wtcb, MQ_WNELIST(msgq->cmn));
}
else
{
DEBUGASSERT(msgq->cmn.nwaitnotfull > 0);
msgq->cmn.nwaitnotfull--;
dq_rem((FAR dq_entry_t *)wtcb, MQ_WNFLIST(msgq->cmn));
}
/* Indicate that the wait is over. */
wtcb->waitobj = NULL;
/* Mark the error value for the thread. */
wtcb->errcode = errcode;
/* Restart the task. */
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
up_unblock_task(wtcb);
if (nxsched_add_readytorun(wtcb))
{
up_unblock_task(wtcb, rtcb);
}
}

View File

@ -221,13 +221,15 @@ ssize_t msgrcv(int msqid, FAR void *msgp, size_t msgsz, long msgtyp,
if (msgq->cmn.nwaitnotfull > 0)
{
FAR struct tcb_s *rtcb = this_task();
/* Find the highest priority task that is waiting for
* this queue to be not-full in g_waitingformqnotfull list.
* This must be performed in a critical section because
* messages can be sent from interrupt handlers.
*/
btcb = (FAR struct tcb_s *)dq_peek(MQ_WNFLIST(msgq->cmn));
btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn));
/* If one was found, unblock it. NOTE: There is a race
* condition here: the queue might be full again by the
@ -242,7 +244,19 @@ ssize_t msgrcv(int msqid, FAR void *msgp, size_t msgsz, long msgtyp,
}
msgq->cmn.nwaitnotfull--;
up_unblock_task(btcb);
/* Indicate that the wait is over. */
btcb->waitobj = NULL;
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(btcb))
{
up_unblock_task(btcb, rtcb);
}
}
errout_with_critical:

View File

@ -216,6 +216,8 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg)
if (msgq->cmn.nwaitnotempty > 0)
{
FAR struct tcb_s *rtcb = this_task();
/* Find the highest priority task that is waiting for
* this queue to be non-empty in g_waitingformqnotempty
* list. enter_critical_section() should give us sufficient
@ -223,7 +225,7 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg)
* in this list
*/
btcb = (FAR struct tcb_s *)dq_peek(MQ_WNELIST(msgq->cmn));
btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn));
/* If one was found, unblock it */
@ -235,7 +237,19 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg)
}
msgq->cmn.nwaitnotempty--;
up_unblock_task(btcb);
/* Indicate that the wait is over. */
btcb->waitobj = NULL;
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(btcb))
{
up_unblock_task(btcb, rtcb);
}
}
}

View File

@ -215,6 +215,8 @@ static void pg_callback(FAR struct tcb_s *tcb, int result)
static inline bool pg_dequeue(void)
{
FAR struct tcb_s *wtcb = this_task();
/* Loop until either (1) the TCB of a task that requires a fill is found,
* OR (2) the g_watingforfill list becomes empty.
*/
@ -253,7 +255,6 @@ static inline bool pg_dequeue(void)
* if a new higher priority fill is required).
*/
FAR struct tcb_s *wtcb = this_task();
if (wtcb->sched_priority > CONFIG_PAGING_DEFPRIO &&
wtcb->sched_priority > g_pftcb->sched_priority)
{
@ -287,7 +288,15 @@ static inline bool pg_dequeue(void)
*/
pginfo("Restarting TCB: %p\n", g_pftcb);
up_unblock_task(g_pftcb);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(g_pftcb))
{
up_unblock_task(g_pftcb, wtcb);
}
}
}
while (g_pftcb != NULL);
@ -469,12 +478,22 @@ static inline void pg_alldone(void)
static inline void pg_fillcomplete(void)
{
FAR struct tcb_s *wtcb = this_task();
/* Call up_unblocktask(g_pftcb) to make the task that just
* received the fill ready-to-run.
*/
pginfo("Restarting TCB: %p\n", g_pftcb);
up_unblock_task(g_pftcb);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(g_pftcb))
{
up_unblock_task(g_pftcb, wtcb);
}
}
/****************************************************************************
@ -506,6 +525,8 @@ static inline void pg_fillcomplete(void)
int pg_worker(int argc, char *argv[])
{
FAR struct tcb_s *wtcb = this_task();
/* Loop forever -- Notice that interrupts will be disabled at all times
* that this thread runs. That is so that we can't lose signals or have
* asynchronous page faults.
@ -567,7 +588,15 @@ int pg_worker(int argc, char *argv[])
*/
pginfo("Restarting TCB: %p\n", g_pftcb);
up_unblock_task(g_pftcb);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(g_pftcb))
{
up_unblock_task(g_pftcb, wtcb);
}
/* Yes .. Start the next asynchronous fill. Check the return
* value to see a fill was actually started (false means that
@ -644,7 +673,15 @@ int pg_worker(int argc, char *argv[])
*/
pginfo("Restarting TCB: %p\n", g_pftcb);
up_unblock_task(g_pftcb);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(g_pftcb))
{
up_unblock_task(g_pftcb, wtcb);
}
}
/* All queued fills have been processed */

View File

@ -186,6 +186,14 @@ extern dq_queue_t g_waitingforsignal;
extern dq_queue_t g_waitingforfill;
#endif
/* This is the list of all tasks that have been stopped
* via SIGSTOP or SIGTSTP
*/
#ifdef CONFIG_SIG_SIGSTOP_ACTION
extern dq_queue_t g_stoppedtasks;
#endif
/* This the list of all tasks that have been initialized, but not yet
* activated. NOTE: This is the only list that is not prioritized.
*/

View File

@ -132,10 +132,12 @@ int nxsem_post(FAR sem_t *sem)
* that we want.
*/
stcb = (FAR struct tcb_s *)dq_peek(SEM_WAITLIST(sem));
stcb = (FAR struct tcb_s *)dq_remfirst(SEM_WAITLIST(sem));
if (stcb != NULL)
{
FAR struct tcb_s *rtcb = this_task();
/* The task will be the new holder of the semaphore when
* it is awakened.
*/
@ -149,9 +151,18 @@ int nxsem_post(FAR sem_t *sem)
wd_cancel(&stcb->waitdog);
}
/* Restart the waiting task. */
/* Indicate that the wait is over. */
up_unblock_task(stcb);
stcb->waitobj = NULL;
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(stcb))
{
up_unblock_task(stcb, rtcb);
}
}
#if 0 /* REVISIT: This can fire on IOB throttle semaphore */
else

View File

@ -31,6 +31,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include "sched/sched.h"
#include "semaphore/semaphore.h"
/****************************************************************************
@ -67,6 +68,7 @@
void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
{
FAR struct tcb_s *rtcb = this_task();
FAR sem_t *sem = wtcb->waitobj;
/* It is possible that an interrupt/context switch beat us to the punch
@ -89,11 +91,24 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
sem->semcount++;
/* Remove task from waiting list */
dq_rem((FAR dq_entry_t *)wtcb, SEM_WAITLIST(sem));
/* Indicate that the wait is over. */
wtcb->waitobj = NULL;
/* Mark the errno value for the thread. */
wtcb->errcode = errcode;
/* Restart the task. */
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
up_unblock_task(wtcb);
if (nxsched_add_readytorun(wtcb))
{
up_unblock_task(wtcb, rtcb);
}
}

View File

@ -36,6 +36,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/signal.h>
#include <nuttx/queue.h>
#include "sched/sched.h"
#include "group/group.h"
@ -296,6 +297,7 @@ static void nxsig_add_pendingsignal(FAR struct tcb_s *stcb,
int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
{
FAR struct tcb_s *rtcb = this_task();
irqstate_t flags;
int masked;
int ret = OK;
@ -369,7 +371,19 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
wd_cancel(&stcb->waitdog);
}
up_unblock_task(stcb);
/* Remove the task from waitting list */
dq_rem((FAR dq_entry_t *)stcb, &g_waitingforsignal);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(stcb))
{
up_unblock_task(stcb, rtcb);
}
leave_critical_section(flags);
}
@ -411,7 +425,18 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
wd_cancel(&stcb->waitdog);
}
up_unblock_task(stcb);
/* Remove the task from waitting list */
dq_rem((FAR dq_entry_t *)stcb, &g_waitingforsignal);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(stcb))
{
up_unblock_task(stcb, rtcb);
}
}
leave_critical_section(flags);
@ -464,7 +489,18 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
#ifdef HAVE_GROUP_MEMBERS
group_continue(stcb);
#else
up_unblock_task(stcb);
/* Remove the task from waitting list */
dq_rem((FAR dq_entry_t *)stcb, &g_stoppedtasks);
/* Add the task to ready-to-run task list and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(stcb))
{
up_unblock_task(stcb, rtcb);
}
#endif
}
#endif

View File

@ -39,6 +39,7 @@
#include <nuttx/wdog.h>
#include <nuttx/signal.h>
#include <nuttx/cancelpt.h>
#include <nuttx/queue.h>
#include "sched/sched.h"
#include "signal/signal.h"
@ -96,6 +97,8 @@ static void nxsig_timeout(wdparm_t arg)
if (wtcb->task_state == TSTATE_WAIT_SIG)
{
FAR struct tcb_s *rtcb = this_task();
wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT;
wtcb->sigunbinfo.si_code = SI_TIMER;
wtcb->sigunbinfo.si_errno = ETIMEDOUT;
@ -104,7 +107,19 @@ static void nxsig_timeout(wdparm_t arg)
wtcb->sigunbinfo.si_pid = 0; /* Not applicable */
wtcb->sigunbinfo.si_status = OK;
#endif
up_unblock_task(wtcb);
/* Remove the task from waitting list */
dq_rem((FAR dq_entry_t *)wtcb, &g_waitingforsignal);
/* Add the task to ready-to-run task list, and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(wtcb))
{
up_unblock_task(wtcb, rtcb);
}
}
#ifdef CONFIG_SMP
@ -149,6 +164,8 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode)
if (wtcb->task_state == TSTATE_WAIT_SIG)
{
FAR struct tcb_s *rtcb = this_task();
wtcb->sigunbinfo.si_signo = SIG_CANCEL_TIMEOUT;
wtcb->sigunbinfo.si_code = SI_USER;
wtcb->sigunbinfo.si_errno = errcode;
@ -157,7 +174,19 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode)
wtcb->sigunbinfo.si_pid = 0; /* Not applicable */
wtcb->sigunbinfo.si_status = OK;
#endif
up_unblock_task(wtcb);
/* Remove the task from waitting list */
dq_rem((FAR dq_entry_t *)wtcb, &g_waitingforsignal);
/* Add the task to ready-to-run task list, and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(wtcb))
{
up_unblock_task(wtcb, rtcb);
}
}
#ifdef CONFIG_SMP

View File

@ -32,6 +32,8 @@
#include <nuttx/arch.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
/****************************************************************************
* Public Functions
****************************************************************************/
@ -56,6 +58,7 @@
void nxtask_activate(FAR struct tcb_s *tcb)
{
irqstate_t flags = enter_critical_section();
FAR struct tcb_s *rtcb = this_task();
#ifdef CONFIG_SCHED_INSTRUMENTATION
@ -77,6 +80,18 @@ void nxtask_activate(FAR struct tcb_s *tcb)
sched_note_start(tcb);
#endif
up_unblock_task(tcb);
/* Remove the task from waitting list */
nxsched_remove_blocked(tcb);
/* Add the task to ready-to-run task list, and
* perform the context switch if one is needed
*/
if (nxsched_add_readytorun(tcb))
{
up_unblock_task(tcb, rtcb);
}
leave_critical_section(flags);
}