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 <pelcan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2100748
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Philip Elcan
2019-04-18 15:57:37 -04:00
committed by mobile promotions
parent 1bfc68ef46
commit 82ce44d882
2 changed files with 52 additions and 4 deletions

View File

@@ -44,11 +44,26 @@
"test_level": 0, "test_level": 0,
"unit": "atomic" "unit": "atomic"
}, },
{
"test": "atomic_cmpxchg_32_threaded",
"test_level": 0,
"unit": "atomic"
},
{ {
"test": "atomic_cmpxchg_64", "test": "atomic_cmpxchg_64",
"test_level": 0, "test_level": 0,
"unit": "atomic" "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": "atomic_dec_32",
"test_level": 0, "test_level": 0,

View File

@@ -47,6 +47,7 @@ enum atomic_op {
op_dec_and_test, op_dec_and_test,
op_sub_and_test, op_sub_and_test,
op_add_unless, op_add_unless,
op_cmpxchg,
}; };
struct atomic_test_args { struct atomic_test_args {
enum atomic_op op; enum atomic_op op;
@@ -558,6 +559,19 @@ static int test_atomic_arithmetic(struct unit_module *m,
return UNIT_SUCCESS; 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 * Support function that runs in the threads for the arithmetic threaded
* test below * test below
@@ -570,7 +584,10 @@ static void *arithmetic_thread(void *__args)
pthread_barrier_wait(&thread_barrier); pthread_barrier_wait(&thread_barrier);
for (i = 0; i < targs->margs->loop_count; i++) { 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); func_inc(targs->margs->type, targs->atomic);
} else if (targs->margs->op == op_dec) { } else if (targs->margs->op == op_dec) {
func_dec(targs->margs->type, targs->atomic); 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_sub:
case op_inc: case op_inc:
case op_dec: case op_dec:
case op_cmpxchg:
expected_val = args->start_val + expected_val = args->start_val +
(args->loop_count * num_threads * (args->loop_count * num_threads *
ATOMIC_OP_SIGN(args->op) * args->value); ATOMIC_OP_SIGN(args->op) * args->value);
@@ -797,8 +815,14 @@ static int test_atomic_arithmetic_threaded(struct unit_module *m,
exit: exit:
pthread_barrier_destroy(&thread_barrier); pthread_barrier_destroy(&thread_barrier);
if (args->type == NOT_ATOMIC) {
/* For the non-atomics, pass is fail and fail is pass */
return INVERTED_RESULT(ret);
} else {
return ret; return ret;
} }
}
/* /*
* Thread function for the test_atomic_arithmetic_and_test_threaded() test. * Thread function for the test_atomic_arithmetic_and_test_threaded() test.
@@ -1386,20 +1410,26 @@ static struct atomic_test_args sub_and_test_64_arg = {
.repeat_count = 5000, /* for threaded test */ .repeat_count = 5000, /* for threaded test */
}; };
struct atomic_test_args xchg_not_atomic_arg = { struct atomic_test_args xchg_not_atomic_arg = {
.op = op_cmpxchg,
.type = NOT_ATOMIC, .type = NOT_ATOMIC,
.start_val = 1, .start_val = 1,
.value = 1,
.loop_count = 10000, .loop_count = 10000,
.repeat_count = 2000, /* for threaded test */ .repeat_count = 10000, /* for threaded test */
}; };
struct atomic_test_args xchg_32_arg = { struct atomic_test_args xchg_32_arg = {
.op = op_cmpxchg,
.type = ATOMIC_32, .type = ATOMIC_32,
.start_val = 1, .start_val = 1,
.value = 1,
.loop_count = 10000, .loop_count = 10000,
.repeat_count = 2000, /* for threaded test */ .repeat_count = 10000, /* for threaded test */
}; };
struct atomic_test_args xchg_64_arg = { struct atomic_test_args xchg_64_arg = {
.op = op_cmpxchg,
.type = ATOMIC_64, .type = ATOMIC_64,
.start_val = INT_MAX, .start_val = INT_MAX,
.value = 1,
.loop_count = 10000, .loop_count = 10000,
.repeat_count = 2000, /* for threaded test */ .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_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_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_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 */ /* 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), UNIT_TEST(atomic_inc_and_test_not_atomic_threaded, test_atomic_arithmetic_and_test_threaded, &inc_and_test_not_atomic_arg, 1),