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.
This commit is contained in:
Sebastian Huber
2016-06-01 09:50:44 +02:00
parent 6b5df955a6
commit a9cc6a84c5
3 changed files with 352 additions and 19 deletions

View File

@@ -68,7 +68,9 @@ static void run_tests(
if (rtems_test_parallel_is_master_worker(worker_index)) {
rtems_interval duration = (*job->init)(ctx, job->arg, active_worker);
start_worker_stop_timer(ctx, duration);
if (duration > 0) {
start_worker_stop_timer(ctx, duration);
}
}
_SMP_barrier_Wait(&ctx->barrier, &bs, ctx->worker_count);

View File

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

View File

@@ -1,24 +1,184 @@
*** TEST SMPATOMIC 1 ***
*** BEGIN OF TEST SMPATOMIC 1 ***
=== atomic add test case ===
worker 0 value: 16686
worker 1 value: 36405
atomic value: expected = 53091, actual = 53091
worker 0 value: 68020
worker 1 value: 355745
worker 2 value: 341230
worker 3 value: 395115
worker 4 value: 341233
worker 5 value: 352026
worker 6 value: 381492
worker 7 value: 357940
worker 8 value: 422258
worker 9 value: 244645
worker 10 value: 246474
worker 11 value: 197385
worker 12 value: 256213
worker 13 value: 233617
worker 14 value: 234606
worker 15 value: 260702
worker 16 value: 214706
worker 17 value: 86201
worker 18 value: 104268
worker 19 value: 67940
worker 20 value: 68509
worker 21 value: 98021
worker 22 value: 66668
worker 23 value: 87962
atomic value: expected = 5482976, actual = 5482976
=== atomic flag test case ===
worker 0 value: 5588
worker 1 value: 16019
atomic value: expected = 21607, actual = 21607
worker 0 value: 90301
worker 1 value: 90507
worker 2 value: 91048
worker 3 value: 90930
worker 4 value: 91129
worker 5 value: 90994
worker 6 value: 91677
worker 7 value: 91086
worker 8 value: 90729
worker 9 value: 90540
worker 10 value: 91358
worker 11 value: 90859
worker 12 value: 90954
worker 13 value: 90816
worker 14 value: 91052
worker 15 value: 90994
worker 16 value: 90961
worker 17 value: 89741
worker 18 value: 90144
worker 19 value: 90270
worker 20 value: 90301
worker 21 value: 90054
worker 22 value: 89782
worker 23 value: 90108
atomic value: expected = 2176335, actual = 2176335
=== atomic sub test case ===
worker 0 value: 4294950967
worker 1 value: 4294930886
atomic value: expected = 4294914557, actual = 4294914557
worker 0 value: 4294821032
worker 1 value: 4294618821
worker 2 value: 4294631020
worker 3 value: 4294597642
worker 4 value: 4294626165
worker 5 value: 4294629962
worker 6 value: 4294601673
worker 7 value: 4294668647
worker 8 value: 4294687608
worker 9 value: 4294691802
worker 10 value: 4294770759
worker 11 value: 4294700436
worker 12 value: 4294715096
worker 13 value: 4294716993
worker 14 value: 4294708426
worker 15 value: 4294725595
worker 16 value: 4294732565
worker 17 value: 4294893135
worker 18 value: 4294857801
worker 19 value: 4294892291
worker 20 value: 4294874959
worker 21 value: 4294839944
worker 22 value: 4294874753
worker 23 value: 4294875135
atomic value: expected = 4289504452, actual = 4289504452
=== atomic compare exchange test case ===
worker 0 value: 2950
worker 1 value: 22456
atomic value: expected = 25406, actual = 25406
worker 0 value: 121131
worker 1 value: 134839
worker 2 value: 139422
worker 3 value: 123158
worker 4 value: 122908
worker 5 value: 134536
worker 6 value: 134554
worker 7 value: 133142
worker 8 value: 129816
worker 9 value: 133474
worker 10 value: 129722
worker 11 value: 140019
worker 12 value: 129180
worker 13 value: 122164
worker 14 value: 135158
worker 15 value: 126391
worker 16 value: 132336
worker 17 value: 123469
worker 18 value: 122731
worker 19 value: 124443
worker 20 value: 125119
worker 21 value: 121813
worker 22 value: 123291
worker 23 value: 121235
atomic value: expected = 3084051, actual = 3084051
=== atomic or/and test case ===
worker 0 value: 1
worker 0 value: 0
worker 1 value: 0
atomic value: expected = 1, actual = 1
worker 2 value: 4
worker 3 value: 8
worker 4 value: 0
worker 5 value: 32
worker 6 value: 64
worker 7 value: 0
worker 8 value: 0
worker 9 value: 512
worker 10 value: 0
worker 11 value: 0
worker 12 value: 0
worker 13 value: 8192
worker 14 value: 16384
worker 15 value: 0
worker 16 value: 0
worker 17 value: 131072
worker 18 value: 0
worker 19 value: 524288
worker 20 value: 1048576
worker 21 value: 2097152
worker 22 value: 0
worker 23 value: 8388608
atomic value: expected = 12214892, actual = 12214892
=== atomic fence test case ===
normal value = 10759507, second value = 10759507
normal value = 10931635, second value = 10931635
=== atomic store release and load acquire test case ===
processor 0 delta 1040ns, load count 0
processor 1 delta 1573ns, load count 59
processor 2 delta 1840ns, load count 21
processor 3 delta 1307ns, load count 71
processor 4 delta 1440ns, load count 45
processor 5 delta 1973ns, load count 0
processor 6 delta 1173ns, load count 84
processor 7 delta 1707ns, load count 34
processor 8 delta 1867ns, load count 39
processor 9 delta 1360ns, load count 84
processor 10 delta 1227ns, load count 0
processor 11 delta 1760ns, load count 51
processor 12 delta 1493ns, load count 13
processor 13 delta 2000ns, load count 64
processor 14 delta 2133ns, load count 77
processor 15 delta 1627ns, load count 26
processor 16 delta 2240ns, load count 41
processor 17 delta 1733ns, load count 0
processor 18 delta 2000ns, load count 29
processor 19 delta 1467ns, load count 74
processor 20 delta 1600ns, load count 16
processor 21 delta 1200ns, load count 66
processor 22 delta 1867ns, load count 3
processor 23 delta 1333ns, load count 53
=== atomic read-modify-write test case ===
processor 0 delta 1067ns, read-modify-write count 0
processor 1 delta 3921ns, read-modify-write count 0
processor 2 delta 3067ns, read-modify-write count 0
processor 3 delta 1200ns, read-modify-write count 0
processor 4 delta 3600ns, read-modify-write count 0
processor 5 delta 3334ns, read-modify-write count 0
processor 6 delta 1334ns, read-modify-write count 0
processor 7 delta 2187ns, read-modify-write count 0
processor 8 delta 1147ns, read-modify-write count 0
processor 9 delta 3947ns, read-modify-write count 0
processor 10 delta 2321ns, read-modify-write count 0
processor 11 delta 3734ns, read-modify-write count 0
processor 12 delta 2827ns, read-modify-write count 1
processor 13 delta 2481ns, read-modify-write count 0
processor 14 delta 1254ns, read-modify-write count 0
processor 15 delta 2667ns, read-modify-write count 0
processor 16 delta 3467ns, read-modify-write count 0
processor 17 delta 2054ns, read-modify-write count 0
processor 18 delta 1707ns, read-modify-write count 1
processor 19 delta 1894ns, read-modify-write count 0
processor 20 delta 2934ns, read-modify-write count 0
processor 21 delta 1547ns, read-modify-write count 0
processor 22 delta 1361ns, read-modify-write count 0
processor 23 delta 3200ns, read-modify-write count 0
*** END OF TEST SMPATOMIC 1 ***