Skip to content

Commit 3ea1c56

Browse files
authored
Merge pull request #10147 from kjbracey-arm/atomic_bitwise
Assembler atomics
2 parents 1aa95c0 + 2bb4045 commit 3ea1c56

File tree

48 files changed

+2924
-1241
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2924
-1241
lines changed

TESTS/mbed_platform/atomic/main.cpp

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "mbed.h"
17+
#include "greentea-client/test_env.h"
18+
#include "unity/unity.h"
19+
#include "utest/utest.h"
20+
21+
#if !MBED_CONF_RTOS_PRESENT
22+
#error [NOT_SUPPORTED] test not supported
23+
#endif
24+
25+
#define THREAD_STACK 512
26+
27+
using utest::v1::Case;
28+
29+
30+
namespace {
31+
32+
/* Lock-free operations will be much faster - keep runtime down */
33+
#if MBED_ATOMIC_INT_LOCK_FREE
34+
#define ADD_ITERATIONS (SystemCoreClock / 1000)
35+
#else
36+
#define ADD_ITERATIONS (SystemCoreClock / 8000)
37+
#endif
38+
39+
template <typename T>
40+
void add_incrementer(T *ptr)
41+
{
42+
for (long i = ADD_ITERATIONS; i > 0; i--) {
43+
core_util_atomic_fetch_add(ptr, T(1));
44+
}
45+
}
46+
47+
template <typename T>
48+
void add_release_incrementer(T *ptr)
49+
{
50+
for (long i = ADD_ITERATIONS; i > 0; i--) {
51+
core_util_atomic_fetch_add_explicit(ptr, T(1), mbed_memory_order_release);
52+
}
53+
}
54+
55+
template <typename T>
56+
void sub_incrementer(T *ptr)
57+
{
58+
for (long i = ADD_ITERATIONS; i > 0; i--) {
59+
core_util_atomic_fetch_sub(ptr, T(-1));
60+
}
61+
}
62+
63+
template <typename T>
64+
void bitops_incrementer(T *ptr)
65+
{
66+
for (long i = ADD_ITERATIONS; i > 0; i--) {
67+
core_util_atomic_fetch_add(ptr, T(1));
68+
core_util_atomic_fetch_and(ptr, T(-1));
69+
core_util_atomic_fetch_or(ptr, T(0));
70+
}
71+
}
72+
73+
template <typename T>
74+
void weak_incrementer(T *ptr)
75+
{
76+
for (long i = ADD_ITERATIONS; i > 0; i--) {
77+
T val = core_util_atomic_load(ptr);
78+
do {
79+
} while (!core_util_atomic_compare_exchange_weak(ptr, &val, T(val + 1)));
80+
}
81+
}
82+
83+
template <typename T>
84+
void strong_incrementer(T *ptr)
85+
{
86+
for (long i = ADD_ITERATIONS; i > 0; i--) {
87+
T val = core_util_atomic_load(ptr);
88+
do {
89+
} while (!core_util_atomic_compare_exchange_strong(ptr, &val, T(val + 1)));
90+
}
91+
}
92+
93+
94+
/*
95+
* Run multiple threads incrementing each data item
96+
* ADD_ITERATIONS times, and at the end, check that
97+
* each item is <number of threads> * ADD_ITERATIONS.
98+
* Items are adjacent to catch any interference.
99+
*
100+
* Using core_util_atomic_ templates, and exercising
101+
* load and store briefly.
102+
*/
103+
template<typename T, void (*Fn)(T *)>
104+
void test_atomic_add()
105+
{
106+
struct {
107+
volatile T nonatomic1;
108+
T atomic1;
109+
T atomic2;
110+
volatile T nonatomic2;
111+
} data;
112+
113+
data.nonatomic1 = 0;
114+
core_util_atomic_store(&data.atomic1, T(0));
115+
core_util_atomic_store(&data.atomic2, T(0));
116+
data.nonatomic2 = 0;
117+
118+
Thread t1(osPriorityNormal, THREAD_STACK);
119+
Thread t2(osPriorityNormal, THREAD_STACK);
120+
Thread t3(osPriorityNormal, THREAD_STACK);
121+
Thread t4(osPriorityNormal, THREAD_STACK);
122+
123+
TEST_ASSERT_EQUAL(osOK, t1.start(callback(Fn, &data.atomic1)));
124+
TEST_ASSERT_EQUAL(osOK, t2.start(callback(Fn, &data.atomic1)));
125+
TEST_ASSERT_EQUAL(osOK, t3.start(callback(Fn, &data.atomic2)));
126+
TEST_ASSERT_EQUAL(osOK, t4.start(callback(Fn, &data.atomic2)));
127+
128+
for (long i = ADD_ITERATIONS; i > 0; i--) {
129+
data.nonatomic1++;
130+
data.nonatomic2++;
131+
}
132+
133+
t1.join();
134+
t2.join();
135+
t3.join();
136+
t4.join();
137+
138+
TEST_ASSERT_EQUAL(T(ADD_ITERATIONS), data.nonatomic1);
139+
TEST_ASSERT_EQUAL(T(2 * ADD_ITERATIONS), core_util_atomic_load(&data.atomic1));
140+
TEST_ASSERT_EQUAL(T(2 * ADD_ITERATIONS), core_util_atomic_load(&data.atomic2));
141+
TEST_ASSERT_EQUAL(T(ADD_ITERATIONS), data.nonatomic2);
142+
}
143+
144+
} // namespace
145+
146+
utest::v1::status_t test_setup(const size_t number_of_cases)
147+
{
148+
GREENTEA_SETUP(30, "default_auto");
149+
return utest::v1::verbose_test_setup_handler(number_of_cases);
150+
}
151+
152+
Case cases[] = {
153+
Case("Test atomic add 8-bit", test_atomic_add<uint8_t, add_incrementer>),
154+
Case("Test atomic add 16-bit", test_atomic_add<uint16_t, add_incrementer>),
155+
Case("Test atomic add 32-bit", test_atomic_add<uint32_t, add_incrementer>),
156+
Case("Test atomic add 64-bit", test_atomic_add<uint64_t, add_incrementer>),
157+
Case("Test atomic add signed 8-bit", test_atomic_add<int8_t, add_incrementer>),
158+
Case("Test atomic add signed 16-bit", test_atomic_add<int16_t, add_incrementer>),
159+
Case("Test atomic add signed 32-bit", test_atomic_add<int32_t, add_incrementer>),
160+
Case("Test atomic add signed 64-bit", test_atomic_add<int64_t, add_incrementer>),
161+
Case("Test atomic add release 32-bit", test_atomic_add<uint32_t, add_release_incrementer>),
162+
Case("Test atomic sub 8-bit", test_atomic_add<uint8_t, sub_incrementer>),
163+
Case("Test atomic sub 16-bit", test_atomic_add<uint16_t, sub_incrementer>),
164+
Case("Test atomic sub 32-bit", test_atomic_add<uint32_t, sub_incrementer>),
165+
Case("Test atomic sub 64-bit", test_atomic_add<uint64_t, sub_incrementer>),
166+
Case("Test atomic bitops 8-bit", test_atomic_add<uint8_t, bitops_incrementer>),
167+
Case("Test atomic bitops 16-bit", test_atomic_add<uint16_t, bitops_incrementer>),
168+
Case("Test atomic bitops 32-bit", test_atomic_add<uint32_t, bitops_incrementer>),
169+
Case("Test atomic bitops 64-bit", test_atomic_add<uint64_t, bitops_incrementer>),
170+
Case("Test atomic compare exchange weak 8-bit", test_atomic_add<uint8_t, weak_incrementer>),
171+
Case("Test atomic compare exchange weak 16-bit", test_atomic_add<uint16_t, weak_incrementer>),
172+
Case("Test atomic compare exchange weak 32-bit", test_atomic_add<uint32_t, weak_incrementer>),
173+
Case("Test atomic compare exchange weak 64-bit", test_atomic_add<uint64_t, weak_incrementer>),
174+
Case("Test atomic compare exchange strong 8-bit", test_atomic_add<uint8_t, strong_incrementer>),
175+
Case("Test atomic compare exchange strong 16-bit", test_atomic_add<uint16_t, strong_incrementer>),
176+
Case("Test atomic compare exchange strong 32-bit", test_atomic_add<uint32_t, strong_incrementer>),
177+
Case("Test atomic compare exchange strong 64-bit", test_atomic_add<uint64_t, strong_incrementer>)
178+
};
179+
180+
utest::v1::Specification specification(test_setup, cases);
181+
182+
int main()
183+
{
184+
return !utest::v1::Harness::run(specification);
185+
}

TESTS/mbed_platform/critical_section/main.cpp

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
using utest::v1::Case;
2323

2424

25-
volatile bool callback_called;
25+
bool callback_called;
2626

2727
void tiemout_callback(void)
2828
{
29-
callback_called = true;
29+
core_util_atomic_store(&callback_called, true);
3030
}
3131

3232
template<int N>
@@ -49,7 +49,7 @@ void critical_section_raii_recursive(Timeout &timeout)
4949
wait_us(wait_time_us);
5050
}
5151
TEST_ASSERT_TRUE(core_util_in_critical_section());
52-
TEST_ASSERT_FALSE(callback_called);
52+
TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called));
5353
}
5454

5555

@@ -82,31 +82,30 @@ void test_C_API(void)
8282

8383
TEST_ASSERT_FALSE(core_util_in_critical_section());
8484

85-
callback_called = false;
85+
core_util_atomic_store(&callback_called, false);
8686
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
8787
wait_us(wait_time_us);
88-
TEST_ASSERT_TRUE(callback_called);
88+
TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false));
8989

9090
for (int i = 0; i < N; i++) {
9191
core_util_critical_section_enter();
9292
TEST_ASSERT_TRUE(core_util_in_critical_section());
9393
}
9494

95-
callback_called = false;
9695
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
9796
wait_us(wait_time_us);
98-
TEST_ASSERT_FALSE(callback_called);
97+
TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called));
9998
TEST_ASSERT_TRUE(core_util_in_critical_section());
10099

101100
for (int i = 0; i < N - 1; i++) {
102101
core_util_critical_section_exit();
103102
TEST_ASSERT_TRUE(core_util_in_critical_section());
104-
TEST_ASSERT_FALSE(callback_called);
103+
TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called));
105104
}
106105

107106
core_util_critical_section_exit();
108107
TEST_ASSERT_FALSE(core_util_in_critical_section());
109-
TEST_ASSERT_TRUE(callback_called);
108+
TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called));
110109
}
111110

112111
/** Template for tests
@@ -138,16 +137,15 @@ void test_CPP_API_constructor_destructor(void)
138137

139138
TEST_ASSERT_FALSE(core_util_in_critical_section());
140139

141-
callback_called = false;
140+
core_util_atomic_store(&callback_called, false);
142141
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
143142
wait_us(wait_time_us);
144-
TEST_ASSERT_TRUE(callback_called);
143+
TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false));
145144

146-
callback_called = false;
147145
critical_section_raii_recursive<N>(timeout);
148146

149147
TEST_ASSERT_FALSE(core_util_in_critical_section());
150-
TEST_ASSERT_TRUE(callback_called);
148+
TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called));
151149
}
152150

153151
/** Template for tests
@@ -179,31 +177,30 @@ void test_CPP_API_enable_disable(void)
179177

180178
TEST_ASSERT_FALSE(core_util_in_critical_section());
181179

182-
callback_called = false;
180+
core_util_atomic_store(&callback_called, false);
183181
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
184182
wait_us(wait_time_us);
185-
TEST_ASSERT_TRUE(callback_called);
183+
TEST_ASSERT_TRUE(core_util_atomic_exchange(&callback_called, false));
186184

187185
for (int i = 0; i < N; i++) {
188186
CriticalSectionLock::enable();
189187
TEST_ASSERT_TRUE(core_util_in_critical_section());
190188
}
191189

192-
callback_called = false;
193190
timeout.attach_us(callback(tiemout_callback), timeout_time_us);
194191
wait_us(wait_time_us);
195-
TEST_ASSERT_FALSE(callback_called);
192+
TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called));
196193
TEST_ASSERT_TRUE(core_util_in_critical_section());
197194

198195
for (int i = 0; i < N - 1; i++) {
199196
CriticalSectionLock::disable();
200197
TEST_ASSERT_TRUE(core_util_in_critical_section());
201-
TEST_ASSERT_FALSE(callback_called);
198+
TEST_ASSERT_FALSE(core_util_atomic_load(&callback_called));
202199
}
203200

204201
CriticalSectionLock::disable();
205202
TEST_ASSERT_FALSE(core_util_in_critical_section());
206-
TEST_ASSERT_TRUE(callback_called);
203+
TEST_ASSERT_TRUE(core_util_atomic_load(&callback_called));
207204
}
208205

209206

UNITTESTS/features/lorawan/lorawanstack/unittest.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ set(unittest-test-sources
3535
stubs/LoRaPHY_stub.cpp
3636
stubs/LoRaMac_stub.cpp
3737
stubs/mbed_assert_stub.c
38-
stubs/mbed_critical_stub.c
38+
stubs/mbed_atomic_stub.c
3939
stubs/LoRaMacCrypto_stub.cpp
4040
stubs/LoRaMacChannelPlan_stub.cpp
4141
stubs/LoRaWANTimer_stub.cpp

UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set(unittest-test-sources
2222
features/netsocket/DTLSSocket/test_DTLSSocket.cpp
2323
stubs/Mutex_stub.cpp
2424
stubs/mbed_assert_stub.c
25+
stubs/mbed_atomic_stub.c
2526
stubs/mbed_critical_stub.c
2627
stubs/equeue_stub.c
2728
../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c

UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(unittest-test-sources
2121
features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp
2222
stubs/Mutex_stub.cpp
2323
stubs/mbed_assert_stub.c
24+
stubs/mbed_atomic_stub.c
2425
stubs/mbed_critical_stub.c
2526
stubs/equeue_stub.c
2627
../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c

UNITTESTS/features/netsocket/InternetSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ set(unittest-test-sources
1818
features/netsocket/InternetSocket/test_InternetSocket.cpp
1919
stubs/Mutex_stub.cpp
2020
stubs/mbed_assert_stub.c
21+
stubs/mbed_atomic_stub.c
2122
stubs/mbed_critical_stub.c
2223
stubs/equeue_stub.c
2324
stubs/EventQueue_stub.cpp

UNITTESTS/features/netsocket/TCPServer/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set(unittest-sources
2222
set(unittest-test-sources
2323
stubs/Mutex_stub.cpp
2424
stubs/mbed_assert_stub.c
25+
stubs/mbed_atomic_stub.c
2526
stubs/mbed_critical_stub.c
2627
stubs/equeue_stub.c
2728
stubs/EventQueue_stub.cpp

UNITTESTS/features/netsocket/TCPSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ set(unittest-test-sources
1919
features/netsocket/TCPSocket/test_TCPSocket.cpp
2020
stubs/Mutex_stub.cpp
2121
stubs/mbed_assert_stub.c
22+
stubs/mbed_atomic_stub.c
2223
stubs/mbed_critical_stub.c
2324
stubs/equeue_stub.c
2425
stubs/EventQueue_stub.cpp

UNITTESTS/features/netsocket/TLSSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(unittest-test-sources
2121
features/netsocket/TLSSocket/test_TLSSocket.cpp
2222
stubs/Mutex_stub.cpp
2323
stubs/mbed_assert_stub.c
24+
stubs/mbed_atomic_stub.c
2425
stubs/mbed_critical_stub.c
2526
stubs/equeue_stub.c
2627
../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c

UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ set(unittest-test-sources
2020
features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp
2121
stubs/Mutex_stub.cpp
2222
stubs/mbed_assert_stub.c
23+
stubs/mbed_atomic_stub.c
2324
stubs/mbed_critical_stub.c
2425
stubs/equeue_stub.c
2526
../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c

UNITTESTS/features/netsocket/UDPSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ set(unittest-test-sources
1919
features/netsocket/UDPSocket/test_UDPSocket.cpp
2020
stubs/Mutex_stub.cpp
2121
stubs/mbed_assert_stub.c
22+
stubs/mbed_atomic_stub.c
2223
stubs/mbed_critical_stub.c
2324
stubs/equeue_stub.c
2425
stubs/EventQueue_stub.cpp

0 commit comments

Comments
 (0)