Skip to content

Atomic extensions: 64-bit, bool, exchange #9600

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions UNITTESTS/stubs/mbed_critical_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
}


uint8_t core_util_atomic_exchange_u8(volatile uint8_t *ptr, uint8_t desiredValue)
{
return 0;
}

uint16_t core_util_atomic_exchange_u16(volatile uint16_t *ptr, uint16_t desiredValue)
{
return 0;
}

uint32_t core_util_atomic_exchange_u32(volatile uint32_t *ptr, uint32_t desiredValue)
{
return 0;
}


uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
{
return 0;
Expand Down Expand Up @@ -103,11 +119,46 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
}


uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr)
{
return 0;
}

void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
{
}

uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
{
return 0;
}

bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue)
{
return false;
}

uint64_t core_util_atomic_incr_u64(volatile uint64_t *valuePtr, uint64_t delta)
{
return 0;
}

uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta)
{
return 0;
}


bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue)
{
return false;
}

void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue)
{
return NULL;
}

void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
{
return NULL;
Expand Down
142 changes: 137 additions & 5 deletions platform/mbed_critical.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ void core_util_critical_section_exit(void)
}
}

/* Inline bool implementations in the header use uint8_t versions to manipulate the bool */
MBED_STATIC_ASSERT(sizeof(bool) == sizeof(uint8_t), "Surely bool is a byte");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😮


#if MBED_EXCLUSIVE_ACCESS

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

bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
{
uint8_t currentValue;
MBED_BARRIER();
uint8_t currentValue;
do {
currentValue = __LDREXB(&flagPtr->_flag);
} while (__STREXB(true, &flagPtr->_flag));
Expand Down Expand Up @@ -164,6 +167,39 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
return true;
}

uint8_t core_util_atomic_exchange_u8(volatile uint8_t *valuePtr, uint8_t desiredValue)
{
MBED_BARRIER();
uint8_t currentValue;
do {
currentValue = __LDREXB(valuePtr);
} while (__STREXB(desiredValue, valuePtr));
MBED_BARRIER();
return currentValue;
}

uint16_t core_util_atomic_exchange_u16(volatile uint16_t *valuePtr, uint16_t desiredValue)
{
MBED_BARRIER();
uint16_t currentValue;
do {
currentValue = __LDREXH(valuePtr);
} while (__STREXH(desiredValue, valuePtr));
MBED_BARRIER();
return currentValue;
}

uint32_t core_util_atomic_exchange_u32(volatile uint32_t *valuePtr, uint32_t desiredValue)
{
MBED_BARRIER();
uint32_t currentValue;
do {
currentValue = __LDREXW(valuePtr);
} while (__STREXW(desiredValue, valuePtr));
MBED_BARRIER();
return currentValue;
}

uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
{
MBED_BARRIER();
Expand All @@ -188,8 +224,8 @@ uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta)

uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
{
uint32_t newValue;
MBED_BARRIER();
uint32_t newValue;
do {
newValue = __LDREXW(valuePtr) + delta;
} while (__STREXW(newValue, valuePtr));
Expand All @@ -200,8 +236,8 @@ uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)

uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
{
uint8_t newValue;
MBED_BARRIER();
uint8_t newValue;
do {
newValue = __LDREXB(valuePtr) - delta;
} while (__STREXB(newValue, valuePtr));
Expand All @@ -211,8 +247,8 @@ uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)

uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
{
uint16_t newValue;
MBED_BARRIER();
uint16_t newValue;
do {
newValue = __LDREXH(valuePtr) - delta;
} while (__STREXH(newValue, valuePtr));
Expand All @@ -222,8 +258,8 @@ uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)

uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
{
uint32_t newValue;
MBED_BARRIER();
uint32_t newValue;
do {
newValue = __LDREXW(valuePtr) - delta;
} while (__STREXW(newValue, valuePtr));
Expand Down Expand Up @@ -295,6 +331,34 @@ bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentV
}


uint8_t core_util_atomic_exchange_u8(volatile uint8_t *ptr, uint8_t desiredValue)
{
core_util_critical_section_enter();
uint8_t currentValue = *ptr;
*ptr = desiredValue;
core_util_critical_section_exit();
return currentValue;
}

uint16_t core_util_atomic_exchange_u16(volatile uint16_t *ptr, uint16_t desiredValue)
{
core_util_critical_section_enter();
uint16_t currentValue = *ptr;
*ptr = desiredValue;
core_util_critical_section_exit();
return currentValue;
}

uint32_t core_util_atomic_exchange_u32(volatile uint32_t *ptr, uint32_t desiredValue)
{
core_util_critical_section_enter();
uint32_t currentValue = *ptr;
*ptr = desiredValue;
core_util_critical_section_exit();
return currentValue;
}


uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
{
uint8_t newValue;
Expand Down Expand Up @@ -358,6 +422,69 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)

#endif

/* No architecture we support has LDREXD/STREXD, so must always disable IRQs for 64-bit operations */
uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr)
{
core_util_critical_section_enter();
uint64_t currentValue = *valuePtr;
core_util_critical_section_exit();
return currentValue;
}

void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
{
core_util_critical_section_enter();
*valuePtr = desiredValue;
core_util_critical_section_exit();
}

uint64_t core_util_atomic_exchange_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
{
core_util_critical_section_enter();
uint64_t currentValue = *valuePtr;
*valuePtr = desiredValue;
core_util_critical_section_exit();
return currentValue;
}

bool core_util_atomic_cas_u64(volatile uint64_t *ptr, uint64_t *expectedCurrentValue, uint64_t desiredValue)
{
bool success;
uint64_t currentValue;
core_util_critical_section_enter();
currentValue = *ptr;
if (currentValue == *expectedCurrentValue) {
*ptr = desiredValue;
success = true;
} else {
*expectedCurrentValue = currentValue;
success = false;
}
core_util_critical_section_exit();
return success;
}

uint64_t core_util_atomic_incr_u64(volatile uint64_t *valuePtr, uint64_t delta)
{
uint64_t newValue;
core_util_critical_section_enter();
newValue = *valuePtr + delta;
*valuePtr = newValue;
core_util_critical_section_exit();
return newValue;
}

uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta)
{
uint64_t newValue;
core_util_critical_section_enter();
newValue = *valuePtr - delta;
*valuePtr = newValue;
core_util_critical_section_exit();
return newValue;
}

MBED_STATIC_ASSERT(sizeof(void *) == sizeof(uint32_t), "Alas, pointers must be 32-bit");

bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue)
{
Expand All @@ -367,6 +494,11 @@ bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue,
(uint32_t)desiredValue);
}

void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue)
{
return (void *)core_util_atomic_exchange_u32((volatile uint32_t *)valuePtr, (uint32_t)desiredValue);
}

void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
{
return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);
Expand Down
Loading