mirror of https://github.com/ARMmbed/mbed-os.git
Add atomic_flag utility
An atomic flag primitive is sometimes wanted, and it is cumbersome to create it from the compare-and-swap operation - cumbersome enough that people often don't bother. Put in a core_util_atomic_flag that follows the C11/C++11 atomic_flag API, such that it could be mapped to it with #define later.pull/8328/head
parent
0b27736536
commit
c32984c3a8
|
@ -100,6 +100,11 @@ void core_util_critical_section_exit(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr)
|
||||||
|
{
|
||||||
|
flagPtr->_flag = false;
|
||||||
|
}
|
||||||
|
|
||||||
#if MBED_EXCLUSIVE_ACCESS
|
#if MBED_EXCLUSIVE_ACCESS
|
||||||
|
|
||||||
/* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */
|
/* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */
|
||||||
|
@ -107,6 +112,15 @@ void core_util_critical_section_exit(void)
|
||||||
#pragma diag_suppress 3731
|
#pragma diag_suppress 3731
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
|
||||||
|
{
|
||||||
|
uint8_t currentValue;
|
||||||
|
do {
|
||||||
|
currentValue = __LDREXB(&flagPtr->_flag);
|
||||||
|
} while (__STREXB(true, &flagPtr->_flag));
|
||||||
|
return currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
|
@ -204,6 +218,15 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
|
||||||
|
{
|
||||||
|
core_util_critical_section_enter();
|
||||||
|
uint8_t currentValue = flagPtr->_flag;
|
||||||
|
flagPtr->_flag = true;
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
return currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
|
|
|
@ -89,6 +89,43 @@ void core_util_critical_section_exit(void);
|
||||||
*/
|
*/
|
||||||
bool core_util_in_critical_section(void);
|
bool core_util_in_critical_section(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A lock-free, primitive atomic flag.
|
||||||
|
*
|
||||||
|
* Emulate C11's atomic_flag. The flag is initially in an indeterminate state
|
||||||
|
* unless explicitly initialised with CORE_UTIL_ATOMIC_FLAG_INIT.
|
||||||
|
*/
|
||||||
|
typedef struct core_util_atomic_flag {
|
||||||
|
uint8_t _flag;
|
||||||
|
} core_util_atomic_flag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialiser for a core_util_atomic_flag.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ~~~
|
||||||
|
* core_util_atomic_flag in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
|
||||||
|
* ~~~
|
||||||
|
*/
|
||||||
|
#define CORE_UTIL_ATOMIC_FLAG_INIT { 0 }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic test and set.
|
||||||
|
*
|
||||||
|
* Atomically tests then sets the flag to true, returning the previous value.
|
||||||
|
*
|
||||||
|
* @param flagPtr Target flag being tested and set.
|
||||||
|
* @return The previous value.
|
||||||
|
*/
|
||||||
|
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic clear.
|
||||||
|
*
|
||||||
|
* @param flagPtr Target flag being cleared.
|
||||||
|
*/
|
||||||
|
void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic compare and set. It compares the contents of a memory location to a
|
* Atomic compare and set. It compares the contents of a memory location to a
|
||||||
* given value and, only if they are the same, modifies the contents of that
|
* given value and, only if they are the same, modifies the contents of that
|
||||||
|
|
Loading…
Reference in New Issue