diff --git a/platform/mbed_critical.c b/platform/mbed_critical.c index db6c05bb2a..d9aa0963ab 100644 --- a/platform/mbed_critical.c +++ b/platform/mbed_critical.c @@ -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) diff --git a/platform/mbed_critical.h b/platform/mbed_critical.h index 0b7cb2a8b1..c1c5689889 100644 --- a/platform/mbed_critical.h +++ b/platform/mbed_critical.h @@ -121,7 +121,7 @@ void core_util_critical_section_exit(void); * } * * @note: In the failure case (where the destination isn't set), the value - * pointed to by expectedCurrentValue is still updated with the current value. + * pointed to by expectedCurrentValue is instead updated with the current value. * This property helps writing concise code for the following incr: * * function incr(p : pointer to int, a : int) returns int { @@ -132,6 +132,10 @@ void core_util_critical_section_exit(void); * } * return value + a * } + * + * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it + * always succeeds if the current value is expected, as per the pseudocode + * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. */ bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); @@ -174,7 +178,7 @@ bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_ * } * * @note: In the failure case (where the destination isn't set), the value - * pointed to by expectedCurrentValue is still updated with the current value. + * pointed to by expectedCurrentValue is instead updated with the current value. * This property helps writing concise code for the following incr: * * function incr(p : pointer to int, a : int) returns int { @@ -185,6 +189,10 @@ bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_ * } * return value + a * } + * + * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it + * always succeeds if the current value is expected, as per the pseudocode + * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. */ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); @@ -227,7 +235,7 @@ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uin * } * * @note: In the failure case (where the destination isn't set), the value - * pointed to by expectedCurrentValue is still updated with the current value. + * pointed to by expectedCurrentValue is instead updated with the current value. * This property helps writing concise code for the following incr: * * function incr(p : pointer to int, a : int) returns int { @@ -237,6 +245,10 @@ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uin * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success * } * return value + a + * + * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it + * always succeeds if the current value is expected, as per the pseudocode + * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. * } */ bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); @@ -280,7 +292,7 @@ bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uin * } * * @note: In the failure case (where the destination isn't set), the value - * pointed to by expectedCurrentValue is still updated with the current value. + * pointed to by expectedCurrentValue is instead updated with the current value. * This property helps writing concise code for the following incr: * * function incr(p : pointer to int, a : int) returns int { @@ -291,6 +303,10 @@ bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uin * } * return value + a * } + * + * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it + * always succeeds if the current value is expected, as per the pseudocode + * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. */ bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *desiredValue);