From 82ce44d8826b860b24a108dcd8cda72dda46f25a Mon Sep 17 00:00:00 2001 From: Philip Elcan Date: Thu, 18 Apr 2019 15:57:37 -0400 Subject: [PATCH] gpu: nvgpu: unit: atomics: add cmpxchg threaded test Add a threaded test for nvgpu_cmpxchg API. This test implements an atomic increment using cmpxchg. It uses the existing arithmetic threaded framework to use the cmpxchg_inc() function to verify 100 parallel threads increment the atomic the correct number of times. These are L1 tests since they have longer run times and are unlikely to regress. JIRA NVGPU-2251 Change-Id: I9c2b68052b3a1b6ef20adfa24e7d50746902f754 Signed-off-by: Philip Elcan Reviewed-on: https://git-master.nvidia.com/r/2100748 Reviewed-by: svc-mobile-coverity GVS: Gerrit_Virtual_Submit Reviewed-by: Alex Waterman Reviewed-by: mobile promotions Tested-by: mobile promotions --- userspace/required_tests.json | 15 +++++++++ userspace/units/interface/atomic/atomic.c | 41 ++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/userspace/required_tests.json b/userspace/required_tests.json index 8b706de80..bb5339460 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -44,11 +44,26 @@ "test_level": 0, "unit": "atomic" }, + { + "test": "atomic_cmpxchg_32_threaded", + "test_level": 0, + "unit": "atomic" + }, { "test": "atomic_cmpxchg_64", "test_level": 0, "unit": "atomic" }, + { + "test": "atomic_cmpxchg_64_threaded", + "test_level": 0, + "unit": "atomic" + }, + { + "test": "atomic_cmpxchg_not_atomic_threaded", + "test_level": 0, + "unit": "atomic" + }, { "test": "atomic_dec_32", "test_level": 0, diff --git a/userspace/units/interface/atomic/atomic.c b/userspace/units/interface/atomic/atomic.c index 9c84958b7..a91ae87ee 100644 --- a/userspace/units/interface/atomic/atomic.c +++ b/userspace/units/interface/atomic/atomic.c @@ -47,6 +47,7 @@ enum atomic_op { op_dec_and_test, op_sub_and_test, op_add_unless, + op_cmpxchg, }; struct atomic_test_args { enum atomic_op op; @@ -558,6 +559,19 @@ static int test_atomic_arithmetic(struct unit_module *m, return UNIT_SUCCESS; } +static void cmpxchg_inc(enum atomic_type type, struct atomic_struct *ref) +{ + bool done = false; + long old; + + while (!done) { + old = func_read(type, ref); + if (old == func_cmpxchg(type, ref, old, old + 1)) { + done = true; + } + } +} + /* * Support function that runs in the threads for the arithmetic threaded * test below @@ -570,7 +584,10 @@ static void *arithmetic_thread(void *__args) pthread_barrier_wait(&thread_barrier); for (i = 0; i < targs->margs->loop_count; i++) { - if (targs->margs->op == op_inc) { + if (targs->margs->op == op_cmpxchg) { + /* special case with special function */ + cmpxchg_inc(targs->margs->type, targs->atomic); + } else if (targs->margs->op == op_inc) { func_inc(targs->margs->type, targs->atomic); } else if (targs->margs->op == op_dec) { func_dec(targs->margs->type, targs->atomic); @@ -750,6 +767,7 @@ static int test_atomic_arithmetic_threaded(struct unit_module *m, case op_sub: case op_inc: case op_dec: + case op_cmpxchg: expected_val = args->start_val + (args->loop_count * num_threads * ATOMIC_OP_SIGN(args->op) * args->value); @@ -797,7 +815,13 @@ static int test_atomic_arithmetic_threaded(struct unit_module *m, exit: pthread_barrier_destroy(&thread_barrier); - return ret; + + if (args->type == NOT_ATOMIC) { + /* For the non-atomics, pass is fail and fail is pass */ + return INVERTED_RESULT(ret); + } else { + return ret; + } } /* @@ -1386,20 +1410,26 @@ static struct atomic_test_args sub_and_test_64_arg = { .repeat_count = 5000, /* for threaded test */ }; struct atomic_test_args xchg_not_atomic_arg = { + .op = op_cmpxchg, .type = NOT_ATOMIC, .start_val = 1, + .value = 1, .loop_count = 10000, - .repeat_count = 2000, /* for threaded test */ + .repeat_count = 10000, /* for threaded test */ }; struct atomic_test_args xchg_32_arg = { + .op = op_cmpxchg, .type = ATOMIC_32, .start_val = 1, + .value = 1, .loop_count = 10000, - .repeat_count = 2000, /* for threaded test */ + .repeat_count = 10000, /* for threaded test */ }; struct atomic_test_args xchg_64_arg = { + .op = op_cmpxchg, .type = ATOMIC_64, .start_val = INT_MAX, + .value = 1, .loop_count = 10000, .repeat_count = 2000, /* for threaded test */ }; @@ -1452,6 +1482,9 @@ struct unit_module_test atomic_tests[] = { UNIT_TEST(atomic_add_64_threaded, test_atomic_arithmetic_threaded, &add_64_arg, 0), UNIT_TEST(atomic_sub_32_threaded, test_atomic_arithmetic_threaded, &sub_32_arg, 0), UNIT_TEST(atomic_sub_64_threaded, test_atomic_arithmetic_threaded, &sub_64_arg, 0), + UNIT_TEST(atomic_cmpxchg_not_atomic_threaded, test_atomic_arithmetic_threaded, &xchg_not_atomic_arg, 0), + UNIT_TEST(atomic_cmpxchg_32_threaded, test_atomic_arithmetic_threaded, &xchg_32_arg, 0), + UNIT_TEST(atomic_cmpxchg_64_threaded, test_atomic_arithmetic_threaded, &xchg_64_arg, 0), /* Level 1 tests */ UNIT_TEST(atomic_inc_and_test_not_atomic_threaded, test_atomic_arithmetic_and_test_threaded, &inc_and_test_not_atomic_arg, 1),