[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