Skip to content

Commit 694adaa

Browse files
committed
Add atomic exchange
1 parent a719840 commit 694adaa

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

UNITTESTS/stubs/mbed_critical_stub.c

Lines changed: 26 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;
@@ -112,6 +128,11 @@ void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredVal
112128
{
113129
}
114130

131+
uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
132+
{
133+
return 0;
134+
}
135+
115136
bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue)
116137
{
117138
return false;
@@ -133,6 +154,11 @@ bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue,
133154
return false;
134155
}
135156

157+
void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue)
158+
{
159+
return NULL;
160+
}
161+
136162
void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
137163
{
138164
return NULL;

platform/mbed_critical.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,39 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
167167
return true;
168168
}
169169

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+
170203
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
171204
{
172205
MBED_BARRIER();
@@ -298,6 +331,34 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
298331
}
299332

300333

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+
301362
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
302363
{
303364
uint8_t newValue;
@@ -377,6 +438,15 @@ void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredVal
377438
core_util_critical_section_exit();
378439
}
379440

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+
380450
bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue)
381451
{
382452
bool success;
@@ -414,6 +484,8 @@ uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta)
414484
return newValue;
415485
}
416486

487+
MBED_STATIC_ASSERT(sizeof(void *) == sizeof(uint32_t), "Alas, pointers must be 32-bit");
488+
417489
bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue)
418490
{
419491
return core_util_atomic_cas_u32(
@@ -422,6 +494,11 @@ bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue,
422494
(uint32_t)desiredValue);
423495
}
424496

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+
425502
void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
426503
{
427504
return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);

platform/mbed_critical.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,57 @@ MBED_FORCEINLINE void core_util_atomic_store_ptr(void *volatile *valuePtr, void
354354
MBED_BARRIER();
355355
}
356356

357+
/**
358+
* Atomic exchange.
359+
* @param valuePtr Target memory location.
360+
* @param desiredValue The value to store.
361+
* @return The previous value.
362+
*/
363+
uint8_t core_util_atomic_exchange_u8(volatile uint8_t *valuePtr, uint8_t desiredValue);
364+
365+
/**
366+
* Atomic exchange.
367+
* @param valuePtr Target memory location.
368+
* @param desiredValue The value to store.
369+
* @return The previous value.
370+
*/
371+
uint16_t core_util_atomic_exchange_u16(volatile uint16_t *valuePtr, uint16_t desiredValue);
372+
373+
/**
374+
* Atomic exchange.
375+
* @param valuePtr Target memory location.
376+
* @param desiredValue The value to store.
377+
* @return The previous value.
378+
*/
379+
uint32_t core_util_atomic_exchange_u32(volatile uint32_t *valuePtr, uint32_t desiredValue);
380+
381+
/**
382+
* Atomic exchange.
383+
* @param valuePtr Target memory location.
384+
* @param desiredValue The value to store.
385+
* @return The previous value.
386+
*/
387+
uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue);
388+
389+
/**
390+
* Atomic exchange.
391+
* @param valuePtr Target memory location.
392+
* @param desiredValue The value to store.
393+
* @return The previous value.
394+
*/
395+
MBED_FORCEINLINE bool core_util_atomic_exchange_bool(volatile bool *valuePtr, bool desiredValue)
396+
{
397+
return (bool)core_util_atomic_exchange_u8((volatile uint8_t *)valuePtr, desiredValue);
398+
}
399+
400+
/**
401+
* Atomic exchange.
402+
* @param valuePtr Target memory location.
403+
* @param desiredValue The value to store.
404+
* @return The previous value.
405+
*/
406+
void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue);
407+
357408
/**
358409
* Atomic increment.
359410
* @param valuePtr Target memory location being incremented.

0 commit comments

Comments
 (0)