arch & sched: task: Fix up_exit() and nxtask_exit() for SMP
Summary: - During repeating ostest with sabre-6quad:smp (QEMU), I noticed that pthread_rwlock_test sometimes stops - Finally, I found that nxtask_exit() released a critical section too early before context switching which resulted in selecting inappropriate TCB - This commit fixes this issue by moving nxsched_resume_scheduler() from nxtask_exit() to up_exit() and also removing spin_setbit() and spin_clrbit() from nxtask_exit() because the caller holds a critical section - To be consistent with non-SMP cases, the above changes were done for all CPU architectures Impact: - This commit affects all CPU architectures regardless of SMP Testing: - Tested with ostest with the following configs - sabre-6quad:smp (QEMU, dev board), sabre-6quad:nsh (QEMU) - spresense:wifi_smp - sim:smp, sim:ostest - maix-bit:smp (QEMU) - esp32-devkitc:smp (QEMU) - lc823450-xgevk:rndis Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
This commit is contained in:
parent
d5a1c8cae8
commit
ec73a4e69c
16 changed files with 78 additions and 23 deletions
|
@ -150,6 +150,12 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -165,6 +165,10 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -149,6 +149,10 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -167,6 +167,12 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -160,6 +160,10 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for RR & SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -158,6 +158,10 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -165,6 +165,10 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -149,6 +149,10 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for RR & SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -167,6 +167,12 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -86,6 +86,12 @@ void up_exit(int status)
|
|||
tcb = this_task();
|
||||
sinfo("New Active Task TCB=%p\n", tcb);
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* 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.
|
||||
|
|
|
@ -149,6 +149,12 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -153,6 +153,12 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Context switch, rearrange MMU */
|
||||
|
||||
up_restore_auxstate(tcb);
|
||||
|
|
|
@ -172,6 +172,12 @@ void up_exit(int status)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
|
||||
* NOTE: the API also adjusts the global IRQ control for SMP
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Set up the co-processor state for the newly started thread. */
|
||||
|
||||
|
|
|
@ -150,6 +150,10 @@ void up_exit(int status)
|
|||
tcb = this_task();
|
||||
sinfo("New Active Task TCB=%p\n", tcb);
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
RESTORE_USERCONTEXT(tcb);
|
||||
|
|
|
@ -152,6 +152,10 @@ void up_exit(int status)
|
|||
tcb = this_task();
|
||||
sinfo("New Active Task TCB=%p\n", tcb);
|
||||
|
||||
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
|
||||
|
||||
nxsched_resume_scheduler(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
|
||||
|
|
|
@ -119,12 +119,12 @@ int nxtask_exit(void)
|
|||
rtcb = this_task();
|
||||
#endif
|
||||
|
||||
/* Because clearing the global IRQ control in nxsched_remove_readytorun()
|
||||
* was moved to nxsched_resume_scheduler(). So call the API here.
|
||||
/* NOTE: nxsched_resume_scheduler() was moved to up_exit()
|
||||
* because the global IRQ control for SMP should be deferred until
|
||||
* context switching, otherwise, the context switching would be done
|
||||
* without a critical section
|
||||
*/
|
||||
|
||||
nxsched_resume_scheduler(rtcb);
|
||||
|
||||
/* We are now in a bad state -- the head of the ready to run task list
|
||||
* does not correspond to the thread that is running. Disabling pre-
|
||||
* emption on this TCB and marking the new ready-to-run task as not
|
||||
|
@ -162,19 +162,6 @@ int nxtask_exit(void)
|
|||
* To prevent from aquiring, increment rtcb->irqcount here.
|
||||
*/
|
||||
|
||||
if (rtcb->irqcount == 0)
|
||||
{
|
||||
/* NOTE: Need to aquire g_cpu_irqlock here again before
|
||||
* calling spin_setbit() becauses it was released in
|
||||
* the above nxsched_resume_scheduler()
|
||||
*/
|
||||
|
||||
DEBUGVERIFY(irq_waitlock(this_cpu()));
|
||||
|
||||
spin_setbit(&g_cpu_irqset, this_cpu(), &g_cpu_irqsetlock,
|
||||
&g_cpu_irqlock);
|
||||
}
|
||||
|
||||
rtcb->irqcount++;
|
||||
#endif
|
||||
|
||||
|
@ -182,12 +169,6 @@ int nxtask_exit(void)
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
rtcb->irqcount--;
|
||||
|
||||
if (rtcb->irqcount == 0)
|
||||
{
|
||||
spin_clrbit(&g_cpu_irqset, this_cpu(), &g_cpu_irqsetlock,
|
||||
&g_cpu_irqlock);
|
||||
}
|
||||
#endif
|
||||
|
||||
rtcb->task_state = TSTATE_TASK_RUNNING;
|
||||
|
|
Loading…
Reference in a new issue