diff --git a/TESTS/mbed_platform/atomic/main.cpp b/TESTS/mbed_platform/atomic/main.cpp index 3229846d41..62d7179147 100644 --- a/TESTS/mbed_platform/atomic/main.cpp +++ b/TESTS/mbed_platform/atomic/main.cpp @@ -39,8 +39,7 @@ static inline long add_iterations(A &a) } template -struct add_incrementer -{ +struct add_incrementer { static void op(A *ptr) { for (long i = add_iterations(*ptr); i > 0; i--) { @@ -50,8 +49,7 @@ struct add_incrementer }; template -struct add_release_incrementer -{ +struct add_release_incrementer { static void op(A *ptr) { for (long i = add_iterations(*ptr); i > 0; i--) { @@ -61,8 +59,7 @@ struct add_release_incrementer }; template -struct sub_incrementer -{ +struct sub_incrementer { static void op(A *ptr) { for (long i = add_iterations(*ptr); i > 0; i--) { @@ -72,8 +69,7 @@ struct sub_incrementer }; template -struct bitops_incrementer -{ +struct bitops_incrementer { static void op(A *ptr) { for (long i = add_iterations(*ptr); i > 0; i--) { @@ -85,8 +81,7 @@ struct bitops_incrementer }; template -struct weak_incrementer -{ +struct weak_incrementer { static void op(A *ptr) { for (long i = add_iterations(*ptr); i > 0; i--) { @@ -98,8 +93,7 @@ struct weak_incrementer }; template -struct strong_incrementer -{ +struct strong_incrementer { static void op(A *ptr) { for (long i = add_iterations(*ptr); i > 0; i--) { @@ -164,6 +158,79 @@ void test_atomic_add() TEST_ASSERT_EQUAL(T(ADD_UNLOCKED_ITERATIONS), data.nonatomic2); } +// This should fit into a uint32_t container, and there +// will be 1 byte of padding to ignore. +struct small { + uint8_t a; + uint8_t b; + uint8_t c; +}; + +// An 11-byte weird structure. Should work with critical sections. +struct large { + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t dummy[8]; +}; + +template +void struct_incrementer_a(A *data) +{ + for (long i = add_iterations(*data); i > 0; i--) { + typename A::value_type curval = *data, newval; + do { + newval = curval; + newval.a++; + } while (!data->compare_exchange_weak(curval, newval)); + } +} + +template +void struct_incrementer_b(A *data) +{ + for (long i = add_iterations(*data); i > 0; i--) { + typename A::value_type curval = *data, newval; + do { + newval = curval; + newval.b++; + } while (!data->compare_exchange_weak(curval, newval)); + } +} + +template +void test_atomic_struct() +{ + TEST_ASSERT_EQUAL(N, sizeof(Atomic)); + + // Small structures don't have value constructor implemented; + Atomic data; + atomic_init(&data, T{0, 0, 0}); + + Thread t1(osPriorityNormal, THREAD_STACK); + Thread t2(osPriorityNormal, THREAD_STACK); + + TEST_ASSERT_EQUAL(osOK, t1.start(callback(struct_incrementer_a >, &data))); + TEST_ASSERT_EQUAL(osOK, t2.start(callback(struct_incrementer_b >, &data))); + + for (long i = add_iterations(data); i > 0; i--) { + T curval = data, newval; + do { + newval = curval; + newval.c++; + } while (!data.compare_exchange_weak(curval, newval)); + } + + t1.join(); + t2.join(); + + T final_val = data; + + TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.a); + TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.b); + TEST_ASSERT_EQUAL(uint8_t(add_iterations(data)), final_val.c); +} + } // namespace utest::v1::status_t test_setup(const size_t number_of_cases) @@ -197,7 +264,9 @@ Case cases[] = { Case("Test atomic compare exchange strong 8-bit", test_atomic_add), Case("Test atomic compare exchange strong 16-bit", test_atomic_add), Case("Test atomic compare exchange strong 32-bit", test_atomic_add), - Case("Test atomic compare exchange strong 64-bit", test_atomic_add) + Case("Test atomic compare exchange strong 64-bit", test_atomic_add), + Case("Test small atomic custom structure", test_atomic_struct), + Case("Test large atomic custom structure", test_atomic_struct) }; utest::v1::Specification specification(test_setup, cases);