Xtensa SMP: Avoid a nasty situation in SMP by assuring that up_release_pending() is not re-entered.

This commit is contained in:
Gregory Nutt
2016-12-21 09:07:54 -06:00
parent c1e2606526
commit 733a57b4df
2 changed files with 83 additions and 56 deletions
+6
View File
@@ -229,6 +229,9 @@ int up_cpu_pause(int cpu)
* handler from returning until up_cpu_resume() is called; g_cpu_paused * handler from returning until up_cpu_resume() is called; g_cpu_paused
* is a handshake that will prefent this function from returning until * is a handshake that will prefent this function from returning until
* the CPU is actually paused. * the CPU is actually paused.
*
* REVISIT: OR should there be logic to just skip this if the other CPU
* is already paused.
*/ */
DEBUGASSERT(!spin_islocked(&g_cpu_wait[cpu]) && DEBUGASSERT(!spin_islocked(&g_cpu_wait[cpu]) &&
@@ -297,6 +300,9 @@ int up_cpu_resume(int cpu)
/* Release the spinlock. Releasing the spinlock will cause the SGI2 /* Release the spinlock. Releasing the spinlock will cause the SGI2
* handler on 'cpu' to continue and return from interrupt to the newly * handler on 'cpu' to continue and return from interrupt to the newly
* established thread. * established thread.
*
* REVISIT: Should there be a more positive handshake to assure that the
* resumption is complete before returning.
*/ */
DEBUGASSERT(spin_islocked(&g_cpu_wait[cpu]) && DEBUGASSERT(spin_islocked(&g_cpu_wait[cpu]) &&
@@ -39,6 +39,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdbool.h>
#include <sched.h> #include <sched.h>
#include <debug.h> #include <debug.h>
@@ -68,9 +69,24 @@
void up_release_pending(void) void up_release_pending(void)
{ {
struct tcb_s *rtcb = this_task(); struct tcb_s *rtcb = this_task();
#ifdef CONFIG_SMP
static bool busy = false;
#endif
sinfo("From TCB=%p\n", rtcb); sinfo("From TCB=%p\n", rtcb);
/* In SMP configurations, this function will be called as part of leaving
* the critical section. In that case, it may be re-entered as part of
* the sched_addreadytorun() processing. We have to guard against that
* case.
*/
#ifdef CONFIG_SMP
if (!busy)
{
busy = true;
#endif
/* Merge the g_pendingtasks list into the ready-to-run task list */ /* Merge the g_pendingtasks list into the ready-to-run task list */
/* sched_lock(); */ /* sched_lock(); */
@@ -156,4 +172,9 @@ void up_release_pending(void)
xtensa_context_restore(rtcb->xcp.regs); xtensa_context_restore(rtcb->xcp.regs);
} }
} }
#ifdef CONFIG_SMP
busy = false;
}
#endif
} }