smptests/smpatomic01: Add seqlock test case

This commit is contained in:
Sebastian Huber
2016-06-07 15:26:52 +02:00
parent 6fc34e43f5
commit cc8bb9e337
2 changed files with 235 additions and 0 deletions

View File

@@ -575,6 +575,183 @@ static void test_atomic_store_load_rmw_fini(
}
}
/*
* See also Hans-J. Boehm, HP Laboratories,
* "Can Seqlocks Get Along With Programming Language Memory Models?",
* http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
*/
static rtems_interval test_seqlock_init(
rtems_test_parallel_context *base,
void *arg,
size_t active_workers
)
{
smpatomic01_context *ctx = (smpatomic01_context *) base;
ctx->normal_value = 0;
ctx->second_value = 0;
_Atomic_Store_ulong(&ctx->atomic_value, 0, ATOMIC_ORDER_RELEASE);
return test_duration();
}
static unsigned long seqlock_read(smpatomic01_context *ctx)
{
unsigned long counter = 0;
while (!rtems_test_parallel_stop_job(&ctx->base)) {
unsigned long seq0;
unsigned long seq1;
unsigned long a;
unsigned long b;
do {
seq0 = _Atomic_Load_ulong(&ctx->atomic_value, ATOMIC_ORDER_ACQUIRE);
a = ctx->normal_value;
b = ctx->second_value;
seq1 =
_Atomic_Fetch_add_ulong(&ctx->atomic_value, 0, ATOMIC_ORDER_RELEASE);
} while (seq0 != seq1 || seq0 % 2 != 0);
++counter;
rtems_test_assert(a == b);
}
return counter;
}
static void test_single_writer_seqlock_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;
unsigned long counter;
/*
* Use the physical processor index, to observe timing differences introduced
* by the system topology.
*/
cpu_self_index = rtems_get_current_processor();
if (cpu_self_index == 0) {
counter = 0;
while (!rtems_test_parallel_stop_job(&ctx->base)) {
unsigned long seq;
seq = _Atomic_Load_ulong(&ctx->atomic_value, ATOMIC_ORDER_RELAXED);
_Atomic_Store_ulong(&ctx->atomic_value, seq + 1, ATOMIC_ORDER_RELAXED);
_Atomic_Fence(ATOMIC_ORDER_ACQUIRE);
++counter;
ctx->normal_value = counter;
ctx->second_value = counter;
_Atomic_Store_ulong(&ctx->atomic_value, seq + 2, ATOMIC_ORDER_RELEASE);
}
} else {
counter = seqlock_read(ctx);
}
ctx->per_worker_value[cpu_self_index] = counter;
}
static void test_single_writer_seqlock_fini(
rtems_test_parallel_context *base,
void *arg,
size_t active_workers
)
{
smpatomic01_context *ctx = (smpatomic01_context *) base;
size_t i;
printf("=== single writer seqlock test case ===\n");
for (i = 0; i < active_workers; ++i) {
printf(
"processor %zu count %lu\n",
i,
ctx->per_worker_value[i]
);
}
}
static void test_multi_writer_seqlock_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;
unsigned long counter;
/*
* Use the physical processor index, to observe timing differences introduced
* by the system topology.
*/
cpu_self_index = rtems_get_current_processor();
if (cpu_self_index % 2 == 0) {
counter = 0;
while (!rtems_test_parallel_stop_job(&ctx->base)) {
unsigned long seq;
do {
seq = _Atomic_Load_ulong(&ctx->atomic_value, ATOMIC_ORDER_RELAXED);
} while (
seq % 2 != 0
|| !_Atomic_Compare_exchange_ulong(
&ctx->atomic_value,
&seq,
seq + 1,
ATOMIC_ORDER_ACQ_REL,
ATOMIC_ORDER_RELAXED
)
);
++counter;
ctx->normal_value = counter;
ctx->second_value = counter;
_Atomic_Store_ulong(&ctx->atomic_value, seq + 2, ATOMIC_ORDER_RELEASE);
}
} else {
counter = seqlock_read(ctx);
}
ctx->per_worker_value[cpu_self_index] = counter;
}
static void test_multi_writer_seqlock_fini(
rtems_test_parallel_context *base,
void *arg,
size_t active_workers
)
{
smpatomic01_context *ctx = (smpatomic01_context *) base;
size_t i;
printf("=== multi writer seqlock test case ===\n");
for (i = 0; i < active_workers; ++i) {
printf(
"processor %zu count %lu\n",
i,
ctx->per_worker_value[i]
);
}
}
static const rtems_test_parallel_job test_jobs[] = {
{
.init = test_atomic_add_init,
@@ -604,6 +781,14 @@ static const rtems_test_parallel_job test_jobs[] = {
.init = test_atomic_store_load_rmw_init,
.body = test_atomic_store_load_rmw_body,
.fini = test_atomic_store_load_rmw_fini
}, {
.init = test_seqlock_init,
.body = test_single_writer_seqlock_body,
.fini = test_single_writer_seqlock_fini
}, {
.init = test_seqlock_init,
.body = test_multi_writer_seqlock_body,
.fini = test_multi_writer_seqlock_fini
}
};

View File

@@ -181,4 +181,54 @@ 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
=== single writer seqlock test case ===
processor 0 count 2451021
processor 1 count 1
processor 2 count 8
processor 3 count 31
processor 4 count 52
processor 5 count 23
processor 6 count 23
processor 7 count 49
processor 8 count 703
processor 9 count 750
processor 10 count 684
processor 11 count 770
processor 12 count 710
processor 13 count 691
processor 14 count 687
processor 15 count 695
processor 16 count 774
processor 17 count 828
processor 18 count 732
processor 19 count 719
processor 20 count 728
processor 21 count 761
processor 22 count 685
processor 23 count 764
=== multi writer seqlock test case ===
processor 0 count 124410
processor 1 count 7865
processor 2 count 123950
processor 3 count 7797
processor 4 count 124253
processor 5 count 7773
processor 6 count 124763
processor 7 count 7817
processor 8 count 124593
processor 9 count 7781
processor 10 count 124647
processor 11 count 7753
processor 12 count 124322
processor 13 count 7692
processor 14 count 124906
processor 15 count 7715
processor 16 count 124568
processor 17 count 7605
processor 18 count 125060
processor 19 count 7908
processor 20 count 124499
processor 21 count 7804
processor 22 count 124538
processor 23 count 7874
*** END OF TEST SMPATOMIC 1 ***