[rtems commit] score: Fix SMP message handling
Sebastian Huber
sebh at rtems.org
Wed Jun 29 08:39:00 UTC 2016
Module: rtems
Branch: master
Commit: 9bb3ce3918261c5392abbe4b65902e5d4b6dff07
Changeset: http://git.rtems.org/rtems/commit/?id=9bb3ce3918261c5392abbe4b65902e5d4b6dff07
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Wed Jun 29 09:50:47 2016 +0200
score: Fix SMP message handling
According to the C11 standard only atomic read-modify-write operations
guarantee that the last value written in modification order is read, see
"7.17.3 Order and consistency". Thus we must use a read-modify-write in
_SMP_Inter_processor_interrupt_handler() to make sure we read an
up-to-date message.
---
c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c | 1 -
c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c | 5 -----
cpukit/score/include/rtems/score/percpu.h | 5 -----
cpukit/score/include/rtems/score/smpimpl.h | 18 +++++++++--------
cpukit/score/include/rtems/score/threaddispatch.h | 24 +++++++++++++++++++++++
cpukit/score/include/rtems/score/threadimpl.h | 16 ++-------------
cpukit/score/src/smp.c | 2 +-
7 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c
index 7e939ff..a3a95f4 100644
--- a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c
+++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c
@@ -62,7 +62,6 @@ void _CPU_SMP_Prepare_start_multitasking( void )
void _CPU_SMP_Send_interrupt( uint32_t target_processor_index )
{
- _ARM_Data_memory_barrier();
arm_gic_irq_generate_software_irq(
ARM_GIC_IRQ_SGI_0,
ARM_GIC_IRQ_SOFTWARE_IRQ_TO_ALL_IN_LIST,
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c
index 844f2b6..7bc7ec3 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c
@@ -267,10 +267,5 @@ void _CPU_SMP_Prepare_start_multitasking(void)
void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
{
-#ifdef __PPC_CPU_E6500__
- ppc_light_weight_synchronize();
-#else
- ppc_synchronize_data();
-#endif
qoriq.pic.ipidr [IPI_INDEX].reg = 1U << target_processor_index;
}
diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h
index 55f799e..8d47aac 100644
--- a/cpukit/score/include/rtems/score/percpu.h
+++ b/cpukit/score/include/rtems/score/percpu.h
@@ -619,11 +619,6 @@ static inline bool _Per_CPU_Is_boot_processor(
#if defined( RTEMS_SMP )
-static inline void _Per_CPU_Send_interrupt( const Per_CPU_Control *cpu )
-{
- _CPU_SMP_Send_interrupt( _Per_CPU_Get_index( cpu ) );
-}
-
/**
* @brief Allocate and Initialize Per CPU Structures
*
diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h
index d1b7214..7f2de5f 100644
--- a/cpukit/score/include/rtems/score/smpimpl.h
+++ b/cpukit/score/include/rtems/score/smpimpl.h
@@ -167,8 +167,10 @@ void _SMP_Multicast_actions_process( void );
*/
static inline long unsigned _SMP_Inter_processor_interrupt_handler( void )
{
- Per_CPU_Control *cpu_self = _Per_CPU_Get();
- unsigned long message = 0;
+ Per_CPU_Control *cpu_self;
+ unsigned long message;
+
+ cpu_self = _Per_CPU_Get();
/*
* In the common case the inter-processor interrupt is issued to carry out a
@@ -176,13 +178,13 @@ static inline long unsigned _SMP_Inter_processor_interrupt_handler( void )
*/
cpu_self->dispatch_necessary = true;
- if ( _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED ) != 0 ) {
- message = _Atomic_Exchange_ulong(
- &cpu_self->message,
- 0UL,
- ATOMIC_ORDER_RELAXED
- );
+ message = _Atomic_Exchange_ulong(
+ &cpu_self->message,
+ 0,
+ ATOMIC_ORDER_ACQUIRE
+ );
+ if ( message != 0 ) {
if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
_SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE );
/* does not continue past here */
diff --git a/cpukit/score/include/rtems/score/threaddispatch.h b/cpukit/score/include/rtems/score/threaddispatch.h
index 573d1be..4cb223b 100644
--- a/cpukit/score/include/rtems/score/threaddispatch.h
+++ b/cpukit/score/include/rtems/score/threaddispatch.h
@@ -226,6 +226,30 @@ RTEMS_INLINE_ROUTINE void _Thread_Dispatch_unnest( Per_CPU_Control *cpu_self )
--cpu_self->thread_dispatch_disable_level;
}
+/**
+ * @brief Requests a thread dispatch on the target processor.
+ *
+ * @param[in] cpu_self The current processor.
+ * @param[in] cpu_target The target processor to request a thread dispatch.
+ */
+RTEMS_INLINE_ROUTINE void _Thread_Dispatch_request(
+ Per_CPU_Control *cpu_self,
+ Per_CPU_Control *cpu_target
+)
+{
+#if defined( RTEMS_SMP )
+ if ( cpu_self == cpu_target ) {
+ cpu_self->dispatch_necessary = true;
+ } else {
+ _Atomic_Fetch_or_ulong( &cpu_target->message, 0, ATOMIC_ORDER_RELEASE );
+ _CPU_SMP_Send_interrupt( _Per_CPU_Get_index( cpu_target ) );
+ }
+#else
+ cpu_self->dispatch_necessary = true;
+ (void) cpu_target;
+#endif
+}
+
/** @} */
#ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 6bb7815..c878266 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -844,11 +844,7 @@ RTEMS_INLINE_ROUTINE void _Thread_Dispatch_update_heir(
cpu_for_heir->heir = heir;
- if ( cpu_for_heir == cpu_self ) {
- cpu_self->dispatch_necessary = true;
- } else {
- _Per_CPU_Send_interrupt( cpu_for_heir );
- }
+ _Thread_Dispatch_request( cpu_self, cpu_for_heir );
}
#endif
@@ -885,15 +881,7 @@ RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action(
action->handler = handler;
-#if defined(RTEMS_SMP)
- if ( _Per_CPU_Get() == cpu_of_thread ) {
- cpu_of_thread->dispatch_necessary = true;
- } else {
- _Per_CPU_Send_interrupt( cpu_of_thread );
- }
-#else
- cpu_of_thread->dispatch_necessary = true;
-#endif
+ _Thread_Dispatch_request( _Per_CPU_Get(), cpu_of_thread );
_Chain_Append_if_is_off_chain_unprotected(
&the_thread->Post_switch_actions.Chain,
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index e26de42..d6aad85 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -167,7 +167,7 @@ void _SMP_Send_message( uint32_t cpu_index, unsigned long message )
{
Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
- _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELAXED );
+ _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELEASE );
_CPU_SMP_Send_interrupt( cpu_index );
}
More information about the vc
mailing list