Skip to content

Commit 709e6ff

Browse files
author
Cruz Monrreal
authored
Merge pull request #9600 from kjbracey-arm/atomic_exchange_64
Atomic extensions: 64-bit, bool, exchange
2 parents 270ff3b + 9e7c659 commit 709e6ff

File tree

3 files changed

+552
-170
lines changed

3 files changed

+552
-170
lines changed

UNITTESTS/stubs/mbed_critical_stub.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
7171
}
7272

7373

74+
uint8_t core_util_atomic_exchange_u8(volatile uint8_t *ptr, uint8_t desiredValue)
75+
{
76+
return 0;
77+
}
78+
79+
uint16_t core_util_atomic_exchange_u16(volatile uint16_t *ptr, uint16_t desiredValue)
80+
{
81+
return 0;
82+
}
83+
84+
uint32_t core_util_atomic_exchange_u32(volatile uint32_t *ptr, uint32_t desiredValue)
85+
{
86+
return 0;
87+
}
88+
89+
7490
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
7591
{
7692
return 0;
@@ -103,11 +119,46 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
103119
}
104120

105121

122+
uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr)
123+
{
124+
return 0;
125+
}
126+
127+
void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
128+
{
129+
}
130+
131+
uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
132+
{
133+
return 0;
134+
}
135+
136+
bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue)
137+
{
138+
return false;
139+
}
140+
141+
uint64_t core_util_atomic_incr_u64(volatile uint64_t *valuePtr, uint64_t delta)
142+
{
143+
return 0;
144+
}
145+
146+
uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta)
147+
{
148+
return 0;
149+
}
150+
151+
106152
bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue)
107153
{
108154
return false;
109155
}
110156

157+
void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue)
158+
{
159+
return NULL;
160+
}
161+
111162
void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
112163
{
113164
return NULL;

platform/mbed_critical.c

Lines changed: 137 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ void core_util_critical_section_exit(void)
100100
}
101101
}
102102

103+
/* Inline bool implementations in the header use uint8_t versions to manipulate the bool */
104+
MBED_STATIC_ASSERT(sizeof(bool) == sizeof(uint8_t), "Surely bool is a byte");
105+
103106
#if MBED_EXCLUSIVE_ACCESS
104107

105108
/* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */
@@ -109,8 +112,8 @@ void core_util_critical_section_exit(void)
109112

110113
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
111114
{
112-
uint8_t currentValue;
113115
MBED_BARRIER();
116+
uint8_t currentValue;
114117
do {
115118
currentValue = __LDREXB(&flagPtr->_flag);
116119
} while (__STREXB(true, &flagPtr->_flag));
@@ -164,6 +167,39 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
164167
return true;
165168
}
166169

170+
uint8_t core_util_atomic_exchange_u8(volatile uint8_t *valuePtr, uint8_t desiredValue)
171+
{
172+
MBED_BARRIER();
173+
uint8_t currentValue;
174+
do {
175+
currentValue = __LDREXB(valuePtr);
176+
} while (__STREXB(desiredValue, valuePtr));
177+
MBED_BARRIER();
178+
return currentValue;
179+
}
180+
181+
uint16_t core_util_atomic_exchange_u16(volatile uint16_t *valuePtr, uint16_t desiredValue)
182+
{
183+
MBED_BARRIER();
184+
uint16_t currentValue;
185+
do {
186+
currentValue = __LDREXH(valuePtr);
187+
} while (__STREXH(desiredValue, valuePtr));
188+
MBED_BARRIER();
189+
return currentValue;
190+
}
191+
192+
uint32_t core_util_atomic_exchange_u32(volatile uint32_t *valuePtr, uint32_t desiredValue)
193+
{
194+
MBED_BARRIER();
195+
uint32_t currentValue;
196+
do {
197+
currentValue = __LDREXW(valuePtr);
198+
} while (__STREXW(desiredValue, valuePtr));
199+
MBED_BARRIER();
200+
return currentValue;
201+
}
202+
167203
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
168204
{
169205
MBED_BARRIER();
@@ -188,8 +224,8 @@ uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta)
188224

189225
uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
190226
{
191-
uint32_t newValue;
192227
MBED_BARRIER();
228+
uint32_t newValue;
193229
do {
194230
newValue = __LDREXW(valuePtr) + delta;
195231
} while (__STREXW(newValue, valuePtr));
@@ -200,8 +236,8 @@ uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
200236

201237
uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
202238
{
203-
uint8_t newValue;
204239
MBED_BARRIER();
240+
uint8_t newValue;
205241
do {
206242
newValue = __LDREXB(valuePtr) - delta;
207243
} while (__STREXB(newValue, valuePtr));
@@ -211,8 +247,8 @@ uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
211247

212248
uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
213249
{
214-
uint16_t newValue;
215250
MBED_BARRIER();
251+
uint16_t newValue;
216252
do {
217253
newValue = __LDREXH(valuePtr) - delta;
218254
} while (__STREXH(newValue, valuePtr));
@@ -222,8 +258,8 @@ uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
222258

223259
uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
224260
{
225-
uint32_t newValue;
226261
MBED_BARRIER();
262+
uint32_t newValue;
227263
do {
228264
newValue = __LDREXW(valuePtr) - delta;
229265
} while (__STREXW(newValue, valuePtr));
@@ -295,6 +331,34 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
295331
}
296332

297333

334+
uint8_t core_util_atomic_exchange_u8(volatile uint8_t *ptr, uint8_t desiredValue)
335+
{
336+
core_util_critical_section_enter();
337+
uint8_t currentValue = *ptr;
338+
*ptr = desiredValue;
339+
core_util_critical_section_exit();
340+
return currentValue;
341+
}
342+
343+
uint16_t core_util_atomic_exchange_u16(volatile uint16_t *ptr, uint16_t desiredValue)
344+
{
345+
core_util_critical_section_enter();
346+
uint16_t currentValue = *ptr;
347+
*ptr = desiredValue;
348+
core_util_critical_section_exit();
349+
return currentValue;
350+
}
351+
352+
uint32_t core_util_atomic_exchange_u32(volatile uint32_t *ptr, uint32_t desiredValue)
353+
{
354+
core_util_critical_section_enter();
355+
uint32_t currentValue = *ptr;
356+
*ptr = desiredValue;
357+
core_util_critical_section_exit();
358+
return currentValue;
359+
}
360+
361+
298362
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
299363
{
300364
uint8_t newValue;
@@ -358,6 +422,69 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
358422

359423
#endif
360424

425+
/* No architecture we support has LDREXD/STREXD, so must always disable IRQs for 64-bit operations */
426+
uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr)
427+
{
428+
core_util_critical_section_enter();
429+
uint64_t currentValue = *valuePtr;
430+
core_util_critical_section_exit();
431+
return currentValue;
432+
}
433+
434+
void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
435+
{
436+
core_util_critical_section_enter();
437+
*valuePtr = desiredValue;
438+
core_util_critical_section_exit();
439+
}
440+
441+
uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
442+
{
443+
core_util_critical_section_enter();
444+
uint64_t currentValue = *valuePtr;
445+
*valuePtr = desiredValue;
446+
core_util_critical_section_exit();
447+
return currentValue;
448+
}
449+
450+
bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue)
451+
{
452+
bool success;
453+
uint64_t currentValue;
454+
core_util_critical_section_enter();
455+
currentValue = *ptr;
456+
if (currentValue == *expectedCurrentValue) {
457+
*ptr = desiredValue;
458+
success = true;
459+
} else {
460+
*expectedCurrentValue = currentValue;
461+
success = false;
462+
}
463+
core_util_critical_section_exit();
464+
return success;
465+
}
466+
467+
uint64_t core_util_atomic_incr_u64(volatile uint64_t *valuePtr, uint64_t delta)
468+
{
469+
uint64_t newValue;
470+
core_util_critical_section_enter();
471+
newValue = *valuePtr + delta;
472+
*valuePtr = newValue;
473+
core_util_critical_section_exit();
474+
return newValue;
475+
}
476+
477+
uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta)
478+
{
479+
uint64_t newValue;
480+
core_util_critical_section_enter();
481+
newValue = *valuePtr - delta;
482+
*valuePtr = newValue;
483+
core_util_critical_section_exit();
484+
return newValue;
485+
}
486+
487+
MBED_STATIC_ASSERT(sizeof(void *) == sizeof(uint32_t), "Alas, pointers must be 32-bit");
361488

362489
bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue)
363490
{
@@ -367,6 +494,11 @@ bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue,
367494
(uint32_t)desiredValue);
368495
}
369496

497+
void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue)
498+
{
499+
return (void *)core_util_atomic_exchange_u32((volatile uint32_t *)valuePtr, (uint32_t)desiredValue);
500+
}
501+
370502
void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
371503
{
372504
return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);

0 commit comments

Comments
 (0)