[rtems commit] score: Critical fix for SMP
Sebastian Huber
sebh at rtems.org
Wed Apr 16 07:03:46 UTC 2014
Module: rtems
Branch: master
Commit: 33d0666d02832f63dfd035c7ac9890b4397a1fdc
Changeset: http://git.rtems.org/rtems/commit/?id=33d0666d02832f63dfd035c7ac9890b4397a1fdc
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Tue Apr 15 16:20:17 2014 +0200
score: Critical fix for SMP
The _Scheduler_SMP_Allocate_processor() and _Thread_Dispatch() exchange
information without locks. Make sure we use the right load/store
ordering.
---
cpukit/score/include/rtems/score/cpustdatomic.h | 16 +++-------------
.../score/include/rtems/score/schedulersmpimpl.h | 10 ++++++----
cpukit/score/src/threaddispatch.c | 13 ++++++++++++-
3 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/cpukit/score/include/rtems/score/cpustdatomic.h b/cpukit/score/include/rtems/score/cpustdatomic.h
index 222ad78..a663a06 100644
--- a/cpukit/score/include/rtems/score/cpustdatomic.h
+++ b/cpukit/score/include/rtems/score/cpustdatomic.h
@@ -54,23 +54,13 @@ typedef atomic_uintptr_t Atomic_Pointer;
typedef atomic_flag Atomic_Flag;
/**
- * @brief the enumeration Atomic_Memory_barrier specifies the detailed regular
- * memory synchronization operations used in the atomic operation API
- * definitions.
+ * @brief Memory order according to ISO/IEC 9899:2011.
*/
typedef enum {
- /** no operation orders memory. */
ATOMIC_ORDER_RELAXED = memory_order_relaxed,
- /** a load operation performs an acquire operation on the affected memory
- * location. This flag guarantees that the effects of load operation are
- * completed before the effects of any later data accesses.
- */
ATOMIC_ORDER_ACQUIRE = memory_order_acquire,
- /** a store operation performs a release operation on the affected memory
- * location. This flag guarantee that all effects of all previous data
- * accesses are completed before the store operation takes place.
- */
- ATOMIC_ORDER_RELEASE = memory_order_release
+ ATOMIC_ORDER_RELEASE = memory_order_release,
+ ATOMIC_ORDER_SEQ_CST = memory_order_seq_cst
} Atomic_Order;
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index 61fbff5..20c5d17 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -92,12 +92,14 @@ static inline void _Scheduler_SMP_Allocate_processor(
_Thread_Set_CPU( heir, cpu_of_victim );
+ cpu_of_victim->heir = heir;
+
/*
- * FIXME: Here we need atomic store operations with a relaxed memory order.
- * The _CPU_SMP_Send_interrupt() will ensure that the change can be
- * observed consistently.
+ * It is critical that we first update the heir and then the dispatch
+ * necessary so that _Thread_Dispatch() cannot miss an update.
*/
- cpu_of_victim->heir = heir;
+ _Atomic_Fence( ATOMIC_ORDER_RELEASE );
+
cpu_of_victim->dispatch_necessary = true;
if ( cpu_of_victim != cpu_of_executing ) {
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
index 40a2efb..9e3f86e 100644
--- a/cpukit/score/src/threaddispatch.c
+++ b/cpukit/score/src/threaddispatch.c
@@ -97,9 +97,20 @@ void _Thread_Dispatch( void )
#else
while ( per_cpu->dispatch_necessary ) {
#endif
- heir = per_cpu->heir;
per_cpu->dispatch_necessary = false;
+
+#if defined( RTEMS_SMP )
+ /*
+ * It is critical that we first update the dispatch necessary and then the
+ * read the heir so that we don't miss an update by
+ * _Scheduler_SMP_Allocate_processor().
+ */
+ _Atomic_Fence( ATOMIC_ORDER_SEQ_CST );
+#endif
+
+ heir = per_cpu->heir;
per_cpu->executing = heir;
+
#if defined( RTEMS_SMP )
executing->is_executing = false;
heir->is_executing = true;
More information about the vc
mailing list