diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 292b6e4ad..6866a8ea0 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -32,6 +32,7 @@ * * - @ref SWUTS-enabled * - @ref SWUTS-init + * - @ref SWUTS-interface-atomic * - @ref SWUTS-mm-vm * */ diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index 313dad319..893a5c932 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -1,5 +1,6 @@ INPUT += ../../../userspace/SWUTS.h INPUT += ../../../userspace/units/enabled/nvgpu-enabled.h INPUT += ../../../userspace/units/init/nvgpu-init.h +INPUT += ../../../userspace/units/interface/atomic/atomic.h INPUT += ../../../userspace/units/mm/vm/vm.h diff --git a/userspace/units/interface/atomic/atomic.c b/userspace/units/interface/atomic/atomic.c index 4125c44ce..d7dbdd044 100644 --- a/userspace/units/interface/atomic/atomic.c +++ b/userspace/units/interface/atomic/atomic.c @@ -28,6 +28,8 @@ #include #include +#include "atomic.h" + struct atomic_struct { long not_atomic; nvgpu_atomic_t atomic; @@ -429,14 +431,8 @@ static int single_set_and_read(struct unit_module *m, return UNIT_SUCCESS; } -/* - * Test atomic read and set operations single threaded for proper functionality - * - * Tests setting the limit values for each size. - * Loops through setting each bit in a 32/64bit value. - */ -static int test_atomic_set_and_read(struct unit_module *m, - struct gk20a *g, void *__args) +int test_atomic_set_and_read(struct unit_module *m, + struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; const unsigned int loop_limit = args->type == ATOMIC_32 ? @@ -462,18 +458,8 @@ static int test_atomic_set_and_read(struct unit_module *m, return UNIT_SUCCESS; } -/* - * Test arithmetic atomic operations single threaded for proper functionality - * inc, dec, add, sub and friends (except add_unless) - * Sets a start value from args - * Loops (iterations per args param) - * Validates final result - * - * For *_and_test ops, the args should make sure the loop traverses across 0 - * to test the "test" part. - */ -static int test_atomic_arithmetic(struct unit_module *m, - struct gk20a *g, void *__args) +int test_atomic_arithmetic(struct unit_module *m, + struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; struct atomic_struct atomic = {0}; @@ -682,17 +668,7 @@ static bool correct_thread_iteration_count(struct unit_module *m, return true; } -/* - * Test arithmetic operations in threads to verify atomicity. - * - * Sets initial start value - * Kicks off threads to loop running ops - * When threads finish loops, verify values - * - * With the ops that have a return, save the final value for each thread and - * use that to try to ensure that the threads aren't executing sequentially. - */ -static int test_atomic_arithmetic_threaded(struct unit_module *m, +int test_atomic_arithmetic_threaded(struct unit_module *m, struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; @@ -883,18 +859,7 @@ static void *arithmetic_and_test_updater_thread(void *__args) return NULL; } -/* - * Test arithmetic *_and_test functions in threads to verify atomicity - * - * Set the atomic to a value to allow the arithmetic op to pass 0. - * Start a lot of threads that will each execute the atomic op once. - * Check iteration count to make sure only one thread saw 0. - * Note: The final value isn't verified because we are testing the atomicity - * of the operation and the testing. And the non-atomic case may fail - * the final value before failing the test being tested for. - * Repeat until reaching the input argument repeat_count or seeing a failure. - */ -static int test_atomic_arithmetic_and_test_threaded(struct unit_module *m, +int test_atomic_arithmetic_and_test_threaded(struct unit_module *m, struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; @@ -945,6 +910,12 @@ static int test_atomic_arithmetic_and_test_threaded(struct unit_module *m, result = UNIT_FAIL; break; } + /* + * Note: The final value isn't verified because we are testing + * the atomicity of the operation and the testing. And the + * non-atomic case may fail the final value before failing the + * test being tested for. + */ } while (repeat-- > 0); /* signal the end to the threads, then wake them */ @@ -966,14 +937,8 @@ static int test_atomic_arithmetic_and_test_threaded(struct unit_module *m, } } -/* - * Test xchg op single threaded for proper functionality - * - * Loops calling xchg op with different values making sure the returned - * value is the last one written. - */ -static int test_atomic_xchg(struct unit_module *m, - struct gk20a *g, void *__args) +int test_atomic_xchg(struct unit_module *m, + struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; struct atomic_struct atomic = {0}; @@ -1035,17 +1000,8 @@ static void *xchg_thread(void *__args) return NULL; } -/* - * Test atomic exchange operation - * - * Set the atomic to a starting value. - * Setup and start the exchange threads. - * Setup includes setting each thread's "xchg_val" to its thread number. - * When threads complete, loop through the thread's xchg_val and make sure - * each number is unique and someone still has the starting value. - */ -static int test_atomic_xchg_threaded(struct unit_module *m, - struct gk20a *g, void *__args) +int test_atomic_xchg_threaded(struct unit_module *m, + struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; struct atomic_struct atomic = {0}; @@ -1131,14 +1087,8 @@ exit: } } -/* - * Test cmpxchg single threaded for proper functionality - * - * Loop calling cmpxchg. Alternating between matching and not matching. - * Verify correct behavior for each call. - */ -static int test_atomic_cmpxchg(struct unit_module *m, - struct gk20a *g, void *__args) +int test_atomic_cmpxchg(struct unit_module *m, + struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; struct atomic_struct atomic = {0}; @@ -1202,17 +1152,8 @@ static int test_atomic_cmpxchg(struct unit_module *m, return UNIT_SUCCESS; } -/* - * Test add_unless op single threaded for proper functionality - * - * Note: there is only a 32-bit operation - * - * Loop through calling the operation. Alternating whether the add should - * occur or not (i.e. changing the "unless" value). - * Verify correct behavior for each operation. - */ -static int test_atomic_add_unless(struct unit_module *m, - struct gk20a *g, void *__args) +int test_atomic_add_unless(struct unit_module *m, + struct gk20a *g, void *__args) { struct atomic_test_args *args = (struct atomic_test_args *)__args; struct atomic_struct atomic = {0}; diff --git a/userspace/units/interface/atomic/atomic.h b/userspace/units/interface/atomic/atomic.h new file mode 100644 index 000000000..6d8eff34a --- /dev/null +++ b/userspace/units/interface/atomic/atomic.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef UNIT_INTERFACE_ATOMIC_H +#define UNIT_INTERFACE_ATOMIC_H + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-interface-atomic + * @{ + * + * Software Unit Test Specification for interface-atomic + */ + +/** + * Test specification for: test_atomic_set_and_read + * + * Description: Test atomic set and read operations. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Set the limit values for each atomic's size and read back to verify. + * - Loop through setting each bit in the atomic, reading each time to verify. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_set_and_read(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_arithmetic + * + * Description: Test arithemtic atomic operations inc, dec, add, sub and friends + * (except add_unless) single threaded for proper functionality. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * For *_and_test ops, the args should make sure the loop traverses + * across 0 to test the "test" part. + * + * Steps: + * - Sets a start value from args. + * - Loops (iterations per args param). + * - Validates final result. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_arithmetic(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_arithmetic_threaded + * + * Description: Test atomic operations inc, dec, add, sub, cmpxchg, in threads + * to verify atomicity. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Sets initial start value. + * - Kicks off threads to loop running ops. + * - When threads finish loops, verify values. + * - With the ops that have a return, save the final value for each thread and + * use that to try to ensure that the threads aren't executing sequentially. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_arithmetic_threaded(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_arithmetic_and_test_threaded + * + * Description: Test arithmetic *_and_test functions in threads to verify + * atomicity. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Set the atomic to a value to allow the arithmetic op to pass 0. + * - Start a lot of threads that will each execute the atomic op many times to + * ensure concurrency. + * - If the atomic op reports the value is zero, this iteration is recorded. + * - Check iteration count to make sure only 0 was observed exactly once. + * - Repeat above steps until reaching the input argument repeat_count or seeing + * a failure. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_arithmetic_and_test_threaded(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_xchg + * + * Description: Test xchg op single threaded for proper functionality. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Loops calling xchg op with different values making sure the returned + * value is the last one written. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_xchg(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_xchg_threaded + * + * Description: Test atomic exchange operation with threads to test atomicity. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Set the atomic to a starting value. + * - Setup and start the exchange threads. + * - Setup includes setting each thread's "xchg_val" to its thread number. + * - When threads complete, loop through the thread's xchg_val and make sure + * each number is unique and someone still has the starting value. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_xchg_threaded(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_cmpxchg + * + * Description: Test cmpxchg single threaded for proper functionality. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Loop calling cmpxchg. Alternating between matching and not matching. + * - Verify correct behavior for each call to the operation. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_cmpxchg(struct unit_module *m, + struct gk20a *g, void *__args); + +/** + * Test specification for: test_atomic_add_unless + * + * Description: Test add_unless op single threaded for proper functionality. + * + * Test Type: Feature based + * + * Input: struct atomic_test_args passed via the __args parameter. + * + * Steps: + * - Loop through calling the operation. Alternating whether the add should + * occur or not (i.e. changing the "unless" value). + * - Verify correct behavior for each operation. + * + * Output: Returns SUCCESS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_atomic_add_unless(struct unit_module *m, + struct gk20a *g, void *__args); + +#endif /* UNIT_INTERFACE_ATOMIC_H */ \ No newline at end of file