diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-06-01 09:50:44 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-06-01 09:53:43 +0200 |
commit | a9cc6a84c50c7745155192ca8fda2ba36e43dd69 (patch) | |
tree | ff464e2f53f67c8b1a14703a2cd0c9d7fb7aea72 /testsuites/smptests/smpatomic01/init.c | |
parent | arm/raspberrypi: add fbcons support for rpi bsp (diff) | |
download | rtems-a9cc6a84c50c7745155192ca8fda2ba36e43dd69.tar.bz2 |
smptests/smpatomic01: New test cases
Demonstrate that a read-modify-write atomic operation may be necessary
on some archtitectures to observe the latest value written.
Diffstat (limited to 'testsuites/smptests/smpatomic01/init.c')
-rw-r--r-- | testsuites/smptests/smpatomic01/init.c | 175 |
1 files changed, 173 insertions, 2 deletions
diff --git a/testsuites/smptests/smpatomic01/init.c b/testsuites/smptests/smpatomic01/init.c index 5d0f665cca..673ff28d74 100644 --- a/testsuites/smptests/smpatomic01/init.c +++ b/testsuites/smptests/smpatomic01/init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013, 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -19,7 +19,9 @@ #endif #include <rtems/score/atomic.h> +#include <rtems/score/smpbarrier.h> #include <rtems.h> +#include <rtems/bsd.h> #include <rtems/test.h> #include <limits.h> #include <string.h> @@ -28,6 +30,8 @@ const char rtems_test_name[] = "SMPATOMIC 1"; +#define MS_PER_TICK 10 + #define MASTER_PRIORITY 1 #define WORKER_PRIORITY 2 @@ -42,6 +46,14 @@ typedef struct { char unused_space_for_cache_line_separation[128]; unsigned long second_value; Atomic_Flag global_flag; + SMP_barrier_Control barrier; + SMP_barrier_State barrier_state[CPU_COUNT]; + sbintime_t load_trigger_time; + sbintime_t load_change_time[CPU_COUNT]; + int load_count[CPU_COUNT]; + sbintime_t rmw_trigger_time; + sbintime_t rmw_change_time[CPU_COUNT]; + int rmw_count[CPU_COUNT]; } smpatomic01_context; static smpatomic01_context test_instance; @@ -410,6 +422,159 @@ static void test_atomic_fence_fini( ); } +static rtems_interval test_atomic_store_load_rmw_init( + rtems_test_parallel_context *base, + void *arg, + size_t active_workers +) +{ + smpatomic01_context *ctx = (smpatomic01_context *) base; + size_t i; + + _Atomic_Init_ulong(&ctx->atomic_value, 0); + + _SMP_barrier_Control_initialize(&ctx->barrier); + + for (i = 0; i < active_workers; ++i) { + _SMP_barrier_State_initialize(&ctx->barrier_state[i]); + } + + return 0; +} + +static sbintime_t now(void) +{ + struct bintime bt; + + rtems_bsd_binuptime(&bt); + return bttosbt(bt); +} + +static void test_atomic_store_load_rmw_body( + rtems_test_parallel_context *base, + void *arg, + size_t active_workers, + size_t worker_index +) +{ + smpatomic01_context *ctx = (smpatomic01_context *) base; + uint32_t cpu_self_index; + sbintime_t t; + int counter; + + if (rtems_test_parallel_is_master_worker(worker_index)) { + rtems_status_code sc; + + sc = rtems_task_wake_after(1); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + t = now(); + t += (MS_PER_TICK / 2) * SBT_1MS; + ctx->load_trigger_time = t; + t += MS_PER_TICK * SBT_1MS; + ctx->rmw_trigger_time = t; + } + + _Atomic_Fence(ATOMIC_ORDER_SEQ_CST); + + _SMP_barrier_Wait( + &ctx->barrier, + &ctx->barrier_state[worker_index], + active_workers + ); + + /* + * Use the physical processor index, to observe timing differences introduced + * by the system topology. + */ + cpu_self_index = rtems_get_current_processor(); + + /* Store release and load acquire test case */ + + counter = 0; + t = ctx->load_trigger_time; + + while (now() < t) { + /* Wait */ + } + + if (cpu_self_index == 0) { + _Atomic_Store_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELEASE); + } else { + while (_Atomic_Load_ulong(&ctx->atomic_value, ATOMIC_ORDER_ACQUIRE) == 0) { + ++counter; + } + } + + ctx->load_change_time[cpu_self_index] = now(); + ctx->load_count[cpu_self_index] = counter; + + /* Read-modify-write test case */ + + if (cpu_self_index == 0) { + _Atomic_Store_ulong(&ctx->atomic_value, 0, ATOMIC_ORDER_RELAXED); + } + + counter = 0; + t = ctx->rmw_trigger_time; + + while (now() < t) { + /* Wait */ + } + + if (cpu_self_index == 0) { + _Atomic_Store_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELAXED); + } else { + while ( + (_Atomic_Fetch_or_ulong(&ctx->atomic_value, 2, ATOMIC_ORDER_RELAXED) & 1) + == 0 + ) { + ++counter; + } + } + + ctx->rmw_change_time[cpu_self_index] = now(); + ctx->rmw_count[cpu_self_index] = counter; +} + +static void test_atomic_store_load_rmw_fini( + rtems_test_parallel_context *base, + void *arg, + size_t active_workers +) +{ + smpatomic01_context *ctx = (smpatomic01_context *) base; + size_t i; + struct bintime bt; + struct timespec ts; + + printf("=== atomic store release and load acquire test case ===\n"); + + for (i = 0; i < active_workers; ++i) { + bt = sbttobt(ctx->load_change_time[i] - ctx->load_trigger_time); + bintime2timespec(&bt, &ts); + printf( + "processor %zu delta %lins, load count %i\n", + i, + ts.tv_nsec, + ctx->load_count[i] + ); + } + + printf("=== atomic read-modify-write test case ===\n"); + + for (i = 0; i < active_workers; ++i) { + bt = sbttobt(ctx->rmw_change_time[i] - ctx->rmw_trigger_time); + bintime2timespec(&bt, &ts); + printf( + "processor %zu delta %lins, read-modify-write count %i\n", + i, + ts.tv_nsec, + ctx->rmw_count[i] + ); + } +} + static const rtems_test_parallel_job test_jobs[] = { { .init = test_atomic_add_init, @@ -435,7 +600,11 @@ static const rtems_test_parallel_job test_jobs[] = { .init = test_atomic_fence_init, .body = test_atomic_fence_body, .fini = test_atomic_fence_fini - }, + }, { + .init = test_atomic_store_load_rmw_init, + .body = test_atomic_store_load_rmw_body, + .fini = test_atomic_store_load_rmw_fini + } }; static void setup_worker( @@ -471,6 +640,8 @@ static void Init(rtems_task_argument arg) #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_MICROSECONDS_PER_TICK (MS_PER_TICK * 1000) + #define CONFIGURE_SMP_APPLICATION #define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT |