mirror of https://github.com/ARMmbed/mbed-os.git
Make LDREX/STREX CAS functions strong
The LDREX/STREX implementations of the compare-and-swap functions were weak (they could spuriously fail when the value was expected), whereas the critial section implementation was strong, and the documentation has no suggestion that there might be spurious failures. Rationalise by adding a retry loop for STREX failure, so that it only returns false when the value is not expected. Fixes https://github.com/ARMmbed/mbed-os/issues/5556pull/5596/head
parent
4e222952d7
commit
cfa6d07a3b
|
@ -110,39 +110,42 @@ MBED_WEAK void core_util_critical_section_exit(void)
|
|||
|
||||
bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
||||
{
|
||||
uint8_t currentValue = __LDREXB((volatile uint8_t*)ptr);
|
||||
if (currentValue != *expectedCurrentValue) {
|
||||
*expectedCurrentValue = currentValue;
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
|
||||
return !__STREXB(desiredValue, (volatile uint8_t*)ptr);
|
||||
do {
|
||||
uint8_t currentValue = __LDREXB((volatile uint8_t*)ptr);
|
||||
if (currentValue != *expectedCurrentValue) {
|
||||
*expectedCurrentValue = currentValue;
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
} while (__STREXB(desiredValue, (volatile uint8_t*)ptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
|
||||
{
|
||||
uint16_t currentValue = __LDREXH((volatile uint16_t*)ptr);
|
||||
if (currentValue != *expectedCurrentValue) {
|
||||
*expectedCurrentValue = currentValue;
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
|
||||
return !__STREXH(desiredValue, (volatile uint16_t*)ptr);
|
||||
do {
|
||||
uint16_t currentValue = __LDREXH((volatile uint16_t*)ptr);
|
||||
if (currentValue != *expectedCurrentValue) {
|
||||
*expectedCurrentValue = currentValue;
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
} while (__STREXH(desiredValue, (volatile uint16_t*)ptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
|
||||
{
|
||||
uint32_t currentValue = __LDREXW((volatile uint32_t*)ptr);
|
||||
if (currentValue != *expectedCurrentValue) {
|
||||
*expectedCurrentValue = currentValue;
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
|
||||
return !__STREXW(desiredValue, (volatile uint32_t*)ptr);
|
||||
do {
|
||||
uint32_t currentValue = __LDREXW((volatile uint32_t*)ptr);
|
||||
if (currentValue != *expectedCurrentValue) {
|
||||
*expectedCurrentValue = currentValue;
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
} while (__STREXW(desiredValue, (volatile uint32_t*)ptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta)
|
||||
|
|
Loading…
Reference in New Issue