summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-07-01 10:48:28 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-07-04 13:17:19 +0200
commitfbda4a8834c5c88c138466fb94c4004be7d72d66 (patch)
treeda13bb222edf9c59b3923357e23fc6545c255f8a /cpukit/score/cpu/no_cpu/rtems/score/cpu.h
parentarm: Use local label in _CPU_Context_restore() (diff)
downloadrtems-fbda4a8834c5c88c138466fb94c4004be7d72d66.tar.bz2
score: PR2183: Fix context switch on SMP
Fix context switch on SMP for ARM, PowerPC and SPARC. Atomically test and set the is executing indicator of the heir context to ensure that at most one processor uses the heir context. Break the busy wait loop also due to heir updates.
Diffstat (limited to 'cpukit/score/cpu/no_cpu/rtems/score/cpu.h')
-rw-r--r--cpukit/score/cpu/no_cpu/rtems/score/cpu.h33
1 files changed, 31 insertions, 2 deletions
diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
index 9570fb6c8d..0fcc6e719c 100644
--- a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
+++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
@@ -578,11 +578,40 @@ typedef struct {
#ifdef RTEMS_SMP
/**
* @brief On SMP configurations the thread context must contain a boolean
- * indicator if this context is executing on a processor.
+ * indicator to signal if this context is executing on a processor.
*
* This field must be updated during a context switch. The context switch
* to the heir must wait until the heir context indicates that it is no
- * longer executing on a processor.
+ * longer executing on a processor. The context switch must also check if
+ * a thread dispatch is necessary to honor updates of the heir thread for
+ * this processor. This indicator must be updated using an atomic test and
+ * set operation to ensure that at most one processor uses the heir
+ * context at the same time.
+ *
+ * @code
+ * void _CPU_Context_switch(
+ * Context_Control *executing,
+ * Context_Control *heir
+ * )
+ * {
+ * save( executing );
+ *
+ * executing->is_executing = false;
+ * memory_barrier();
+ *
+ * if ( test_and_set( &heir->is_executing ) ) {
+ * do {
+ * Per_CPU_Control *cpu_self = _Per_CPU_Get_snapshot();
+ *
+ * if ( cpu_self->dispatch_necessary ) {
+ * heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
+ * }
+ * } while ( test_and_set( &heir->is_executing ) );
+ * }
+ *
+ * restore( heir );
+ * }
+ * @endcode
*/
volatile bool is_executing;
#endif