Skip to content

Commit 53b4074

Browse files
committed
Add non-volatile atomic loads and stores
Volatile makes no real difference when we're using assembler, or locked functions, but leaving it off could be more efficient for the basic loads and stores. So add non-volatile overloads in C++ for them.
1 parent ebe48a2 commit 53b4074

File tree

2 files changed

+81
-13
lines changed

2 files changed

+81
-13
lines changed

platform/internal/mbed_atomic_impl.h

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -606,30 +606,30 @@ MBED_FORCEINLINE bool core_util_atomic_flag_test_and_set_explicit(volatile core_
606606

607607
/* Lock-free loads and stores don't need assembler - just aligned accesses */
608608
/* Silly ordering of `T volatile` is because T can be `void *` */
609-
#define DO_MBED_LOCKFREE_LOADSTORE(T, fn_suffix) \
610-
MBED_FORCEINLINE T core_util_atomic_load_##fn_suffix(T const volatile *valuePtr) \
609+
#define DO_MBED_LOCKFREE_LOADSTORE(T, V, fn_suffix) \
610+
MBED_FORCEINLINE T core_util_atomic_load_##fn_suffix(T const V *valuePtr) \
611611
{ \
612612
T value = *valuePtr; \
613613
MBED_BARRIER(); \
614614
return value; \
615615
} \
616616
\
617-
MBED_FORCEINLINE T core_util_atomic_load_explicit_##fn_suffix(T const volatile *valuePtr, mbed_memory_order order) \
617+
MBED_FORCEINLINE T core_util_atomic_load_explicit_##fn_suffix(T const V *valuePtr, mbed_memory_order order) \
618618
{ \
619619
MBED_CHECK_LOAD_ORDER(order); \
620620
T value = *valuePtr; \
621621
MBED_ACQUIRE_BARRIER(order); \
622622
return value; \
623623
} \
624624
\
625-
MBED_FORCEINLINE void core_util_atomic_store_##fn_suffix(T volatile *valuePtr, T value) \
625+
MBED_FORCEINLINE void core_util_atomic_store_##fn_suffix(T V *valuePtr, T value) \
626626
{ \
627627
MBED_BARRIER(); \
628628
*valuePtr = value; \
629629
MBED_BARRIER(); \
630630
} \
631631
\
632-
MBED_FORCEINLINE void core_util_atomic_store_explicit_##fn_suffix(T volatile *valuePtr, T value, mbed_memory_order order) \
632+
MBED_FORCEINLINE void core_util_atomic_store_explicit_##fn_suffix(T V *valuePtr, T value, mbed_memory_order order) \
633633
{ \
634634
MBED_CHECK_STORE_ORDER(order); \
635635
MBED_RELEASE_BARRIER(order); \
@@ -651,15 +651,51 @@ MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(volatile core_util_at
651651
flagPtr->_flag = false;
652652
MBED_SEQ_CST_BARRIER(order);
653653
}
654-
DO_MBED_LOCKFREE_LOADSTORE(uint8_t, u8)
655-
DO_MBED_LOCKFREE_LOADSTORE(uint16_t, u16)
656-
DO_MBED_LOCKFREE_LOADSTORE(uint32_t, u32)
657-
DO_MBED_LOCKFREE_LOADSTORE(int8_t, s8)
658-
DO_MBED_LOCKFREE_LOADSTORE(int16_t, s16)
659-
DO_MBED_LOCKFREE_LOADSTORE(int32_t, s32)
660-
DO_MBED_LOCKFREE_LOADSTORE(bool, bool)
661-
DO_MBED_LOCKFREE_LOADSTORE(void *, ptr)
662654

655+
#ifdef __cplusplus
656+
// Temporarily turn off extern "C", so we can provide non-volatile load/store
657+
// overloads for efficiency. All these functions are static inline, so this has
658+
// no linkage effect exactly, it just permits the overloads.
659+
} // extern "C"
660+
661+
// For efficiency it's worth having non-volatile overloads
662+
MBED_FORCEINLINE void core_util_atomic_flag_clear(core_util_atomic_flag *flagPtr)
663+
{
664+
MBED_BARRIER();
665+
flagPtr->_flag = false;
666+
MBED_BARRIER();
667+
}
668+
669+
MBED_FORCEINLINE void core_util_atomic_flag_clear_explicit(core_util_atomic_flag *flagPtr, mbed_memory_order order)
670+
{
671+
MBED_RELEASE_BARRIER(order);
672+
flagPtr->_flag = false;
673+
MBED_SEQ_CST_BARRIER(order);
674+
}
675+
676+
DO_MBED_LOCKFREE_LOADSTORE(uint8_t,, u8)
677+
DO_MBED_LOCKFREE_LOADSTORE(uint16_t,, u16)
678+
DO_MBED_LOCKFREE_LOADSTORE(uint32_t,, u32)
679+
DO_MBED_LOCKFREE_LOADSTORE(int8_t,, s8)
680+
DO_MBED_LOCKFREE_LOADSTORE(int16_t,, s16)
681+
DO_MBED_LOCKFREE_LOADSTORE(int32_t,, s32)
682+
DO_MBED_LOCKFREE_LOADSTORE(bool,, bool)
683+
DO_MBED_LOCKFREE_LOADSTORE(void *,, ptr)
684+
685+
#endif
686+
687+
DO_MBED_LOCKFREE_LOADSTORE(uint8_t, volatile, u8)
688+
DO_MBED_LOCKFREE_LOADSTORE(uint16_t, volatile, u16)
689+
DO_MBED_LOCKFREE_LOADSTORE(uint32_t, volatile, u32)
690+
DO_MBED_LOCKFREE_LOADSTORE(int8_t, volatile, s8)
691+
DO_MBED_LOCKFREE_LOADSTORE(int16_t, volatile, s16)
692+
DO_MBED_LOCKFREE_LOADSTORE(int32_t, volatile, s32)
693+
DO_MBED_LOCKFREE_LOADSTORE(bool, volatile, bool)
694+
DO_MBED_LOCKFREE_LOADSTORE(void *, volatile, ptr)
695+
696+
#ifdef __cplusplus
697+
extern "C" {
698+
#endif
663699

664700
/********************* GENERIC VARIANTS - SIGNED, BOOL, POINTERS ****************/
665701

@@ -901,6 +937,12 @@ DO_MBED_LOCKED_CAS_ORDERINGS(compare_exchange_weak)
901937
#define DO_MBED_ATOMIC_LOAD_TEMPLATE(T, fn_suffix) \
902938
template<> \
903939
inline T core_util_atomic_load(const volatile T *valuePtr) \
940+
{ \
941+
return core_util_atomic_load_##fn_suffix(valuePtr); \
942+
} \
943+
\
944+
template<> \
945+
inline T core_util_atomic_load(const T *valuePtr) \
904946
{ \
905947
return core_util_atomic_load_##fn_suffix(valuePtr); \
906948
}
@@ -911,6 +953,12 @@ inline T *core_util_atomic_load(T *const volatile *valuePtr)
911953
return (T *) core_util_atomic_load_ptr((void *const volatile *) valuePtr);
912954
}
913955

956+
template<typename T>
957+
inline T *core_util_atomic_load(T *const *valuePtr)
958+
{
959+
return (T *) core_util_atomic_load_ptr((void *const *) valuePtr);
960+
}
961+
914962
DO_MBED_ATOMIC_LOAD_TEMPLATE(uint8_t, u8)
915963
DO_MBED_ATOMIC_LOAD_TEMPLATE(uint16_t, u16)
916964
DO_MBED_ATOMIC_LOAD_TEMPLATE(uint32_t, u32)
@@ -924,6 +972,12 @@ DO_MBED_ATOMIC_LOAD_TEMPLATE(bool, bool)
924972
#define DO_MBED_ATOMIC_STORE_TEMPLATE(T, fn_suffix) \
925973
template<> \
926974
inline void core_util_atomic_store(volatile T *valuePtr, T val) \
975+
{ \
976+
core_util_atomic_store_##fn_suffix(valuePtr, val); \
977+
} \
978+
\
979+
template<> \
980+
inline void core_util_atomic_store(T *valuePtr, T val) \
927981
{ \
928982
core_util_atomic_store_##fn_suffix(valuePtr, val); \
929983
}
@@ -934,6 +988,12 @@ inline void core_util_atomic_store(T *volatile *valuePtr, T *val)
934988
core_util_atomic_store_ptr((void *volatile *) valuePtr, val);
935989
}
936990

991+
template<typename T>
992+
inline void core_util_atomic_store(T **valuePtr, T *val)
993+
{
994+
core_util_atomic_store_ptr((void **) valuePtr, val);
995+
}
996+
937997
DO_MBED_ATOMIC_STORE_TEMPLATE(uint8_t, u8)
938998
DO_MBED_ATOMIC_STORE_TEMPLATE(uint16_t, u16)
939999
DO_MBED_ATOMIC_STORE_TEMPLATE(uint32_t, u32)

platform/mbed_atomic.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,8 +888,12 @@ MBED_FORCEINLINE uint64_t core_util_atomic_fetch_xor_explicit_u64(volatile uint6
888888

889889
/** \copydoc core_util_atomic_load_u8 */
890890
template<typename T> T core_util_atomic_load(const volatile T *valuePtr);
891+
/** \copydoc core_util_atomic_load_u8 */
892+
template<typename T> T core_util_atomic_load(const T *valuePtr);
891893
/** \copydoc core_util_atomic_store_u8 */
892894
template<typename T> void core_util_atomic_store(volatile T *valuePtr, T desiredValue);
895+
/** \copydoc core_util_atomic_store_u8 */
896+
template<typename T> void core_util_atomic_store(T *valuePtr, T desiredValue);
893897
/** \copydoc core_util_atomic_exchange_u8 */
894898
template<typename T> T core_util_atomic_exchange(volatile T *ptr, T desiredValue);
895899
/** \copydoc core_util_atomic_cas_u8 */
@@ -930,8 +934,12 @@ template<typename T> T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr,
930934

931935
/** \copydoc core_util_atomic_load_ptr */
932936
template<typename T> inline T *core_util_atomic_load(T *const volatile *valuePtr);
937+
/** \copydoc core_util_atomic_load_ptr */
938+
template<typename T> inline T *core_util_atomic_load(T *const *valuePtr);
933939
/** \copydoc core_util_atomic_store_ptr */
934940
template<typename T> inline void core_util_atomic_store(T *volatile *valuePtr, T *desiredValue);
941+
/** \copydoc core_util_atomic_store_ptr */
942+
template<typename T> inline void core_util_atomic_store(T **valuePtr, T *desiredValue);
935943
/** \copydoc core_util_atomic_exchange_ptr */
936944
template<typename T> inline T *core_util_atomic_exchange(T *volatile *valuePtr, T *desiredValue);
937945
/** \copydoc core_util_atomic_cas_ptr */

0 commit comments

Comments
 (0)