[PATCH 5/5] score: Add SMP barrier

Gedare Bloom gedare at rtems.org
Fri Feb 14 14:30:19 UTC 2014


I glanced, nothing looks wrong.. is there any reference/documentation
for the barrier implementation?

On Fri, Feb 14, 2014 at 8:07 AM, Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
> ---
>  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
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel



More information about the devel mailing list