[PATCH 5/5] score: Add SMP barrier

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Feb 14 13:07:28 UTC 2014


---
 cpukit/score/Makefile.am                      |    2 +
 cpukit/score/include/rtems/score/smpbarrier.h |  125 +++++++++++++++++++++++++
 cpukit/score/preinstall.am                    |    4 +
 cpukit/score/src/smpbarrierwait.c             |   48 ++++++++++
 testsuites/smptests/smpatomic01/init.c        |   48 +---------
 testsuites/smptests/smplock01/init.c          |   66 +++----------
 6 files changed, 195 insertions(+), 98 deletions(-)
 create mode 100644 cpukit/score/include/rtems/score/smpbarrier.h
 create mode 100644 cpukit/score/src/smpbarrierwait.c

diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 267e8b2..482e78d 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -59,6 +59,7 @@ include_rtems_score_HEADERS += include/rtems/score/schedulersimpleimpl.h
 include_rtems_score_HEADERS += include/rtems/score/schedulersmp.h
 include_rtems_score_HEADERS += include/rtems/score/schedulersmpimpl.h
 include_rtems_score_HEADERS += include/rtems/score/smp.h
+include_rtems_score_HEADERS += include/rtems/score/smpbarrier.h
 include_rtems_score_HEADERS += include/rtems/score/smplock.h
 include_rtems_score_HEADERS += include/rtems/score/stack.h
 include_rtems_score_HEADERS += include/rtems/score/stackimpl.h
@@ -276,6 +277,7 @@ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
     src/threadblockingoperationcancel.c
 
 if HAS_SMP
+libscore_a_SOURCES += src/smpbarrierwait.c
 libscore_a_SOURCES += src/threaddispatchdisablelevel.c
 endif
 
diff --git a/cpukit/score/include/rtems/score/smpbarrier.h b/cpukit/score/include/rtems/score/smpbarrier.h
new file mode 100644
index 0000000..fe9a1cf
--- /dev/null
+++ b/cpukit/score/include/rtems/score/smpbarrier.h
@@ -0,0 +1,125 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSMPBarrier
+ *
+ * @brief SMP Barrier API
+ */
+
+/*
+ * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_SMPBARRIER_H
+#define _RTEMS_SCORE_SMPBARRIER_H
+
+#include <rtems/score/cpuopts.h>
+
+#if defined( RTEMS_SMP )
+
+#include <rtems/score/atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreSMPBarrier SMP Barriers
+ *
+ * @ingroup Score
+ *
+ * @brief The SMP barrier provides barrier synchronization for SMP systems at
+ * the lowest level.
+ *
+ * The SMP barrier is implemented as a sense barrier.
+ *
+ * @{
+ */
+
+/**
+ * @brief SMP barrier control.
+ */
+typedef struct {
+  Atomic_Uint value;
+  Atomic_Uint sense;
+} SMP_barrier_Control;
+
+/**
+ * @brief SMP barrier per-thread state.
+ *
+ * Each user of the barrier must provide this per-thread state.
+ */
+typedef struct {
+  unsigned int sense;
+} SMP_barrier_State;
+
+/**
+ * @brief SMP barrier control initializer for static initialization.
+ */
+#define SMP_BARRIER_CONTROL_INITIALIZER \
+  { ATOMIC_INITIALIZER_UINT( 0U ), ATOMIC_INITIALIZER_UINT( 0U ) }
+
+/**
+ * @brief SMP barrier per-thread state initializer for static initialization.
+ */
+#define SMP_BARRIER_STATE_INITIALIZER { 0U }
+
+/**
+ * @brief Initializes a SMP barrier control.
+ *
+ * Concurrent initialization leads to unpredictable results.
+ *
+ * @param[out] control The SMP barrier control.
+ */
+static inline void _SMP_barrier_Control_initialize(
+  SMP_barrier_Control *control
+)
+{
+  _Atomic_Init_uint( &control->value, 0U );
+  _Atomic_Init_uint( &control->sense, 0U );
+}
+
+/**
+ * @brief Initializes a SMP barrier per-thread state.
+ *
+ * @param[out] state The SMP barrier control.
+ */
+static inline void _SMP_barrier_State_initialize(
+  SMP_barrier_State *state
+)
+{
+  state->sense = 0U;
+}
+
+/**
+ * @brief Waits on the SMP barrier until count threads rendezvoused.
+ *
+ * @param[in, out] control The SMP barrier control.
+ * @param[in, out] state The SMP barrier per-thread state.
+ * @param[in] count The thread count bound to rendezvous.
+ */
+void _SMP_barrier_Wait(
+  SMP_barrier_Control *control,
+  SMP_barrier_State *state,
+  unsigned int count
+);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* defined( RTEMS_SMP ) */
+
+#endif /* _RTEMS_SCORE_SMPBARRIER_H */
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index a3c9685..ceefbe7 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -219,6 +219,10 @@ $(PROJECT_INCLUDE)/rtems/score/smp.h: include/rtems/score/smp.h $(PROJECT_INCLUD
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smp.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smp.h
 
+$(PROJECT_INCLUDE)/rtems/score/smpbarrier.h: include/rtems/score/smpbarrier.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smpbarrier.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smpbarrier.h
+
 $(PROJECT_INCLUDE)/rtems/score/smplock.h: include/rtems/score/smplock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smplock.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smplock.h
diff --git a/cpukit/score/src/smpbarrierwait.c b/cpukit/score/src/smpbarrierwait.c
new file mode 100644
index 0000000..0a3cedb
--- /dev/null
+++ b/cpukit/score/src/smpbarrierwait.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/score/smpbarrier.h>
+
+void _SMP_barrier_Wait(
+  SMP_barrier_Control *control,
+  SMP_barrier_State *state,
+  unsigned int count
+)
+{
+  unsigned int sense = ~state->sense;
+  unsigned int previous_value;
+
+  state->sense = sense;
+
+  previous_value = _Atomic_Fetch_add_uint(
+    &control->value,
+    1U,
+    ATOMIC_ORDER_RELAXED
+  );
+
+  if ( previous_value + 1U == count ) {
+    _Atomic_Store_uint( &control->value, 0U, ATOMIC_ORDER_RELAXED );
+    _Atomic_Store_uint( &control->sense, sense, ATOMIC_ORDER_RELEASE );
+  } else {
+    while (
+      _Atomic_Load_uint( &control->sense, ATOMIC_ORDER_ACQUIRE ) != sense
+    ) {
+      /* Wait */
+    }
+  }
+}
diff --git a/testsuites/smptests/smpatomic01/init.c b/testsuites/smptests/smpatomic01/init.c
index 2901a98..792a17b 100644
--- a/testsuites/smptests/smpatomic01/init.c
+++ b/testsuites/smptests/smpatomic01/init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -19,56 +19,12 @@
 #endif
 
 #include <rtems/score/atomic.h>
+#include <rtems/score/smpbarrier.h>
 #include <rtems.h>
 #include <string.h>
 
 #include "tmacros.h"
 
-/* FIXME: Add barrier to Score */
-
-typedef struct {
-	Atomic_Ulong value;
-	Atomic_Ulong sense;
-} SMP_barrier_Control;
-
-typedef struct {
-	unsigned long sense;
-} SMP_barrier_State;
-
-#define SMP_BARRIER_CONTROL_INITIALIZER \
-  { ATOMIC_INITIALIZER_ULONG( 0 ), ATOMIC_INITIALIZER_ULONG( 0 ) }
-
-#define SMP_BARRIER_STATE_INITIALIZER { 0 }
-
-static void _SMP_barrier_Wait(
-  SMP_barrier_Control *control,
-  SMP_barrier_State *state,
-  unsigned long count
-)
-{
-  unsigned long sense = ~state->sense;
-  unsigned long previous_value;
-
-  state->sense = sense;
-
-  previous_value = _Atomic_Fetch_add_ulong(
-    &control->value,
-    1,
-    ATOMIC_ORDER_RELAXED
-  );
-
-  if ( previous_value + 1 == count ) {
-    _Atomic_Store_ulong( &control->value, 0, ATOMIC_ORDER_RELAXED );
-    _Atomic_Store_ulong( &control->sense, sense, ATOMIC_ORDER_RELEASE );
-  } else {
-    while (
-      _Atomic_Load_ulong( &control->sense, ATOMIC_ORDER_ACQUIRE ) != sense
-    ) {
-      /* Wait */
-    }
-  }
-}
-
 #define MASTER_PRIORITY 1
 
 #define WORKER_PRIORITY 2
diff --git a/testsuites/smptests/smplock01/init.c b/testsuites/smptests/smplock01/init.c
index 6257ee1..d454487 100644
--- a/testsuites/smptests/smplock01/init.c
+++ b/testsuites/smptests/smplock01/init.c
@@ -17,50 +17,12 @@
 #endif
 
 #include <rtems/score/smplock.h>
+#include <rtems/score/smpbarrier.h>
 #include <rtems/score/atomic.h>
 #include <rtems.h>
 
 #include "tmacros.h"
 
-/* FIXME: Add barrier to Score */
-
-typedef struct {
-	Atomic_Uint value;
-	Atomic_Uint sense;
-} barrier_control;
-
-typedef struct {
-	unsigned int sense;
-} barrier_state;
-
-#define BARRIER_CONTROL_INITIALIZER \
-  { ATOMIC_INITIALIZER_UINT(0), ATOMIC_INITIALIZER_UINT(0) }
-
-#define BARRIER_STATE_INITIALIZER { 0 }
-
-static void barrier_wait(
-  barrier_control *control,
-  barrier_state *state,
-  unsigned int cpu_count
-)
-{
-  unsigned int sense = ~state->sense;
-  unsigned int value;
-
-  state->sense = sense;
-
-  value = _Atomic_Fetch_add_uint(&control->value, 1, ATOMIC_ORDER_RELAXED);
-
-  if (value + 1 == cpu_count) {
-    _Atomic_Store_uint(&control->value, 0, ATOMIC_ORDER_RELAXED);
-    _Atomic_Store_uint(&control->sense, sense, ATOMIC_ORDER_RELEASE);
-  } else {
-    while (_Atomic_Load_uint(&control->sense, ATOMIC_ORDER_ACQUIRE) != sense) {
-      /* Wait */
-    }
-  }
-}
-
 #define TASK_PRIORITY 1
 
 #define CPU_COUNT 32
@@ -75,7 +37,7 @@ typedef enum {
 
 typedef struct {
   Atomic_Uint state;
-  barrier_control barrier;
+  SMP_barrier_Control barrier;
   rtems_id timer_id;
   rtems_interval timeout;
   unsigned long counter[TEST_COUNT];
@@ -85,7 +47,7 @@ typedef struct {
 
 static global_context context = {
   .state = ATOMIC_INITIALIZER_UINT(INITIAL),
-  .barrier = BARRIER_CONTROL_INITIALIZER,
+  .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
   .lock = SMP_LOCK_INITIALIZER
 };
 
@@ -121,7 +83,7 @@ static bool assert_state(global_context *ctx, int desired_state)
 typedef void (*test_body)(
   int test,
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self
 );
@@ -129,7 +91,7 @@ typedef void (*test_body)(
 static void test_0_body(
   int test,
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self
 )
@@ -148,7 +110,7 @@ static void test_0_body(
 static void test_1_body(
   int test,
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self
 )
@@ -168,7 +130,7 @@ static void test_1_body(
 static void test_2_body(
   int test,
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self
 )
@@ -188,7 +150,7 @@ static void test_2_body(
 static void test_3_body(
   int test,
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self
 )
@@ -221,7 +183,7 @@ static void busy_section(void)
 static void test_4_body(
   int test,
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self
 )
@@ -248,7 +210,7 @@ static const test_body test_bodies[TEST_COUNT] = {
 
 static void run_tests(
   global_context *ctx,
-  barrier_state *bs,
+  SMP_barrier_State *bs,
   unsigned int cpu_count,
   unsigned int cpu_self,
   bool master
@@ -257,7 +219,7 @@ static void run_tests(
   int test;
 
   for (test = 0; test < TEST_COUNT; ++test) {
-    barrier_wait(&ctx->barrier, bs, cpu_count);
+    _SMP_barrier_Wait(&ctx->barrier, bs, cpu_count);
 
     if (master) {
       rtems_status_code sc = rtems_timer_fire_after(
@@ -276,7 +238,7 @@ static void run_tests(
     (*test_bodies[test])(test, ctx, bs, cpu_count, cpu_self);
   }
 
-  barrier_wait(&ctx->barrier, bs, cpu_count);
+  _SMP_barrier_Wait(&ctx->barrier, bs, cpu_count);
 }
 
 static void task(rtems_task_argument arg)
@@ -285,7 +247,7 @@ static void task(rtems_task_argument arg)
   uint32_t cpu_count = rtems_smp_get_processor_count();
   uint32_t cpu_self = rtems_smp_get_current_processor();
   rtems_status_code sc;
-  barrier_state bs = BARRIER_STATE_INITIALIZER;
+  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
 
   run_tests(ctx, &bs, cpu_count, cpu_self, false);
 
@@ -301,7 +263,7 @@ static void test(void)
   uint32_t cpu;
   int test;
   rtems_status_code sc;
-  barrier_state bs = BARRIER_STATE_INITIALIZER;
+  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
 
   for (cpu = 0; cpu < cpu_count; ++cpu) {
     if (cpu != cpu_self) {
-- 
1.7.7




More information about the devel mailing list