SMP: fix crash when switch to new task which is still running
cpu0 thread0: cpu1: sched_yield() nxsched_set_priority() nxsched_running_setpriority() nxsched_reprioritize_rtr() nxsched_add_readytorun() up_cpu_pause() IRQ enter arm64_pause_handler() enter_critical_section() begin up_cpu_paused() pick thread0 arm64_restorestate() set thread0 tcb->xcp.regs to CURRENT_REGS up_switch_context() thread0 -> thread1 arm64_syscall() case SYS_switch_context change thread0 tcb->xcp.regs restore_critical_section() enter_critical_section() done leave_critical_section() IRQ leave with restore CURRENT_REGS ERROR !!! Reason: As descript above, cpu0 swith task: thread0 -> thread1, and the syscall() execute slowly, this time cpu1 pick thread0 to run at up_cpu_paused(). Then cpu0 syscall execute, cpu1 IRQ leave error. Resolve: Move arm64_restorestate() after enter_critical_section() done This is a continued fix with: https://github.com/apache/nuttx/pull/6833 Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
parent
27ef7576ff
commit
2241969e5a
@ -84,6 +84,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -113,24 +155,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Release the g_cpu_paused spinlock to synchronize with the
|
||||
* requesting CPU.
|
||||
*/
|
||||
@ -147,11 +171,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* This CPU has been resumed. Restore the exception context of the TCB at
|
||||
* the (new) head of the assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -168,8 +212,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -84,6 +84,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -113,24 +155,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Release the g_cpu_paused spinlock to synchronize with the
|
||||
* requesting CPU.
|
||||
*/
|
||||
@ -147,11 +171,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* This CPU has been resumed. Restore the exception context of the TCB at
|
||||
* the (new) head of the assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -168,8 +212,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -166,6 +166,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -202,24 +244,6 @@ int up_cpu_paused(int cpu)
|
||||
return OK;
|
||||
}
|
||||
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -230,11 +254,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -251,8 +295,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -94,6 +94,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -123,24 +165,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -151,11 +175,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -173,10 +217,6 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -307,7 +347,7 @@ int up_cpu_pause(int cpu)
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -357,5 +397,5 @@ int up_cpu_resume(int cpu)
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
@ -134,6 +134,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -163,24 +205,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -191,11 +215,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -212,8 +256,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -357,7 +399,7 @@ int up_cpu_pause(int cpu)
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -406,7 +448,7 @@ int up_cpu_resume(int cpu)
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -96,6 +96,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -125,24 +167,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -153,11 +177,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -174,8 +218,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -83,6 +83,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm64_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -112,24 +154,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm64_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Release the g_cpu_paused spinlock to synchronize with the
|
||||
* requesting CPU.
|
||||
*/
|
||||
@ -150,7 +174,31 @@ int up_cpu_paused(int cpu)
|
||||
* the (new) head of the assigned task list.
|
||||
*/
|
||||
|
||||
tcb = this_task();
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -167,8 +215,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
arm64_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -84,6 +84,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
riscv_savecontext(tcb);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -113,24 +155,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
riscv_savecontext(tcb);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -141,11 +165,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -163,9 +207,6 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
riscv_restorecontext(tcb);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -280,7 +321,7 @@ int up_cpu_pause(int cpu)
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -330,5 +371,5 @@ int up_cpu_resume(int cpu)
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
@ -127,6 +127,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
sim_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -156,24 +198,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = current_task(cpu);
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
sim_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -184,16 +208,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = current_task(cpu);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -214,8 +253,6 @@ int up_cpu_paused(int cpu)
|
||||
*/
|
||||
|
||||
sim_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -84,6 +84,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
sparc_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -113,24 +155,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
sparc_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -141,11 +165,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -163,9 +207,6 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
sparc_restorestate(tcb->xcp.regs);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -283,7 +324,7 @@ int up_cpu_pause(int cpu)
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -333,5 +374,5 @@ int up_cpu_resume(int cpu)
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
@ -69,6 +69,48 @@ bool up_cpu_pausereq(int cpu)
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
xtensa_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -98,24 +140,6 @@ bool up_cpu_pausereq(int cpu)
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
xtensa_savestate(tcb->xcp.regs);
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
@ -126,11 +150,31 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
*/
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
tcb = this_task();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
@ -148,9 +192,6 @@ int up_cpu_paused(int cpu)
|
||||
|
||||
xtensa_restorestate(tcb->xcp.regs);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -2256,6 +2256,29 @@ int up_cpu_pause(int cpu);
|
||||
bool up_cpu_pausereq(int cpu);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
int up_cpu_paused_save(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
@ -2287,6 +2310,26 @@ bool up_cpu_pausereq(int cpu);
|
||||
int up_cpu_paused(int cpu);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
int up_cpu_paused_restore(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_resume
|
||||
*
|
||||
|
@ -252,6 +252,8 @@ try_again:
|
||||
|
||||
else
|
||||
{
|
||||
int paused = false;
|
||||
|
||||
/* Make sure that the g_cpu_irqset was not already set
|
||||
* by previous logic on this CPU that was executed by the
|
||||
* interrupt handler. We know that the bit in g_cpu_irqset
|
||||
@ -273,7 +275,13 @@ try_again_in_irq:
|
||||
* handling the pause request now.
|
||||
*/
|
||||
|
||||
if (!paused)
|
||||
{
|
||||
up_cpu_paused_save();
|
||||
}
|
||||
|
||||
DEBUGVERIFY(up_cpu_paused(cpu));
|
||||
paused = true;
|
||||
|
||||
/* NOTE: As the result of up_cpu_paused(cpu), this CPU
|
||||
* might set g_cpu_irqset in nxsched_resume_scheduler()
|
||||
@ -305,6 +313,10 @@ try_again_in_irq:
|
||||
|
||||
spin_setbit(&g_cpu_irqset, cpu, &g_cpu_irqsetlock,
|
||||
&g_cpu_irqlock);
|
||||
if (paused)
|
||||
{
|
||||
up_cpu_paused_restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user