score: Add SMP barrier

This commit is contained in:
Sebastian Huber
2014-02-14 12:57:53 +01:00
parent 0344ce0385
commit ad7292f264
6 changed files with 197 additions and 98 deletions

View File

@@ -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

View File

@@ -0,0 +1,127 @@
/**
* @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@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, see also Herlihy and
* Shavit, "The Art of Multiprocessor Programming", 17.3 Sense-Reversing
* 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 */

View File

@@ -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

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@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 */
}
}
}

View File

@@ -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

View File

@@ -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) {