Skip to content

Commit

Permalink
Atomic bitwise operations
Browse files Browse the repository at this point in the history
  • Loading branch information
kjbracey committed Mar 18, 2019
1 parent 6b84b14 commit b8bf0f7
Show file tree
Hide file tree
Showing 2 changed files with 317 additions and 0 deletions.
221 changes: 221 additions & 0 deletions platform/mbed_critical.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,104 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
return newValue;
}

uint8_t core_util_atomic_fetch_and_u8(volatile uint8_t *valuePtr, uint8_t arg)
{
MBED_BARRIER();
uint8_t oldValue;
do {
oldValue = __LDREXB(valuePtr);
} while (__STREXB(oldValue & arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint16_t core_util_atomic_fetch_and_u16(volatile uint16_t *valuePtr, uint16_t arg)
{
MBED_BARRIER();
uint16_t oldValue;
do {
oldValue = __LDREXH(valuePtr);
} while (__STREXH(oldValue & arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint32_t core_util_atomic_fetch_and_u32(volatile uint32_t *valuePtr, uint32_t arg)
{
MBED_BARRIER();
uint32_t oldValue;
do {
oldValue = __LDREXW(valuePtr);
} while (__STREXW(oldValue & arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint8_t core_util_atomic_fetch_or_u8(volatile uint8_t *valuePtr, uint8_t arg)
{
MBED_BARRIER();
uint8_t oldValue;
do {
oldValue = __LDREXB(valuePtr);
} while (__STREXB(oldValue | arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint16_t core_util_atomic_fetch_or_u16(volatile uint16_t *valuePtr, uint16_t arg)
{
MBED_BARRIER();
uint16_t oldValue;
do {
oldValue = __LDREXH(valuePtr);
} while (__STREXH(oldValue | arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint32_t core_util_atomic_fetch_or_u32(volatile uint32_t *valuePtr, uint32_t arg)
{
MBED_BARRIER();
uint32_t oldValue;
do {
oldValue = __LDREXW(valuePtr);
} while (__STREXW(oldValue | arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint8_t core_util_atomic_fetch_xor_u8(volatile uint8_t *valuePtr, uint8_t arg)
{
MBED_BARRIER();
uint8_t oldValue;
do {
oldValue = __LDREXB(valuePtr);
} while (__STREXB(oldValue ^ arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint16_t core_util_atomic_fetch_xor_u16(volatile uint16_t *valuePtr, uint16_t arg)
{
MBED_BARRIER();
uint16_t oldValue;
do {
oldValue = __LDREXH(valuePtr);
} while (__STREXH(oldValue ^ arg, valuePtr));
MBED_BARRIER();
return oldValue;
}

uint32_t core_util_atomic_fetch_xor_u32(volatile uint32_t *valuePtr, uint32_t arg)
{
MBED_BARRIER();
uint32_t oldValue;
do {
oldValue = __LDREXW(valuePtr);
} while (__STREXW(oldValue ^ arg, valuePtr));
MBED_BARRIER();
return oldValue;
}
#else

bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
Expand Down Expand Up @@ -420,6 +518,99 @@ uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
return newValue;
}


uint8_t core_util_atomic_fetch_and_u8(volatile uint8_t *valuePtr, uint8_t arg)
{
uint8_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue & arg;
core_util_critical_section_exit();
return oldValue;
}

uint16_t core_util_atomic_fetch_and_u16(volatile uint16_t *valuePtr, uint16_t arg)
{
uint16_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue & arg;
core_util_critical_section_exit();
return oldValue;
}

uint32_t core_util_atomic_fetch_and_u32(volatile uint32_t *valuePtr, uint32_t arg)
{
uint32_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue & arg;
core_util_critical_section_exit();
return oldValue;
}


uint8_t core_util_atomic_fetch_or_u8(volatile uint8_t *valuePtr, uint8_t arg)
{
uint8_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue | arg;
core_util_critical_section_exit();
return oldValue;
}

uint16_t core_util_atomic_fetch_or_u16(volatile uint16_t *valuePtr, uint16_t arg)
{
uint16_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue | arg;
core_util_critical_section_exit();
return oldValue;
}

uint32_t core_util_atomic_fetch_or_u32(volatile uint32_t *valuePtr, uint32_t arg)
{
uint32_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue | arg;
core_util_critical_section_exit();
return oldValue;
}


uint8_t core_util_atomic_fetch_xor_u8(volatile uint8_t *valuePtr, uint8_t arg)
{
uint8_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue ^ arg;
core_util_critical_section_exit();
return oldValue;
}

uint16_t core_util_atomic_fetch_xor_u16(volatile uint16_t *valuePtr, uint16_t arg)
{
uint16_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue ^ arg;
core_util_critical_section_exit();
return oldValue;
}

uint32_t core_util_atomic_fetch_xor_u32(volatile uint32_t *valuePtr, uint32_t arg)
{
uint32_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue ^ arg;
core_util_critical_section_exit();
return oldValue;
}

#endif

/* No architecture we support has LDREXD/STREXD, so must always disable IRQs for 64-bit operations */
Expand Down Expand Up @@ -484,6 +675,36 @@ uint64_t core_util_atomic_decr_u64(volatile uint64_t *valuePtr, uint64_t delta)
return newValue;
}

uint64_t core_util_atomic_fetch_and_u64(volatile uint64_t *valuePtr, uint64_t arg)
{
uint64_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue & arg;
core_util_critical_section_exit();
return oldValue;
}

uint64_t core_util_atomic_fetch_or_u64(volatile uint64_t *valuePtr, uint64_t arg)
{
uint64_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue | arg;
core_util_critical_section_exit();
return oldValue;
}

uint64_t core_util_atomic_fetch_xor_u64(volatile uint64_t *valuePtr, uint64_t arg)
{
uint64_t oldValue;
core_util_critical_section_enter();
oldValue = *valuePtr;
*valuePtr = oldValue ^ arg;
core_util_critical_section_exit();
return oldValue;
}

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 Down
96 changes: 96 additions & 0 deletions platform/mbed_critical.h
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,102 @@ MBED_FORCEINLINE int64_t core_util_atomic_decr_s64(volatile int64_t *valuePtr, i
*/
void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta);

/**
* Atomic bitwise and.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint8_t core_util_atomic_fetch_and_u8(volatile uint8_t *valuePtr, uint8_t arg);

/**
* Atomic bitwise and.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint16_t core_util_atomic_fetch_and_u16(volatile uint16_t *valuePtr, uint16_t arg);

/**
* Atomic bitwise and.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint32_t core_util_atomic_fetch_and_u32(volatile uint32_t *valuePtr, uint32_t arg);

/**
* Atomic bitwise and.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint64_t core_util_atomic_fetch_and_u64(volatile uint64_t *valuePtr, uint64_t arg);

/**
* Atomic bitwise inclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint8_t core_util_atomic_fetch_or_u8(volatile uint8_t *valuePtr, uint8_t arg);

/**
* Atomic bitwise inclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint16_t core_util_atomic_fetch_or_u16(volatile uint16_t *valuePtr, uint16_t arg);

/**
* Atomic bitwise inclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint32_t core_util_atomic_fetch_or_u32(volatile uint32_t *valuePtr, uint32_t arg);

/**
* Atomic bitwise inclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint64_t core_util_atomic_fetch_or_u64(volatile uint64_t *valuePtr, uint64_t arg);

/**
* Atomic bitwise exclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint8_t core_util_atomic_fetch_xor_u8(volatile uint8_t *valuePtr, uint8_t arg);

/**
* Atomic bitwise exclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint16_t core_util_atomic_fetch_xor_u16(volatile uint16_t *valuePtr, uint16_t arg);

/**
* Atomic bitwise exclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint32_t core_util_atomic_fetch_xor_u32(volatile uint32_t *valuePtr, uint32_t arg);

/**
* Atomic bitwise exclusive or.
* @param valuePtr Target memory location being modified.
* @param arg The argument for the bitwise operation.
* @return The original value.
*/
uint64_t core_util_atomic_fetch_xor_u64(volatile uint64_t *valuePtr, uint64_t arg);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down

0 comments on commit b8bf0f7

Please sign in to comment.