Skip to content

Commit

Permalink
Remove intermediate struct for _Atomic for GCC C11
Browse files Browse the repository at this point in the history
Previously, stdatomic.h always used an intermediate struct
with GCC, to wrap atomic types, giving some protection against
non-atomic accesses.  This is unnecessary in C11. Previous commit
c25de3a moved a definition of "_Atomic"
into cdefs and changed the conditions such that it would not be defined
in C11, but the macros in stdatomic.h still expected the intermediate
struct and so dereferenced them by the "__val" member.

This change adds sets of macros when C11 is in use which access _Atomic
objects directly without the intermediate structs.

Change-Id: Ia2b0e7bc2a1dfb02ea8af64e9e5946cfed198701
  • Loading branch information
Colin McEwan committed Mar 22, 2024
1 parent f638ca9 commit 6b2a582
Showing 1 changed file with 42 additions and 4 deletions.
46 changes: 42 additions & 4 deletions newlib/libc/include/stdatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@

#include <sys/cdefs.h>
#include <sys/_types.h>
#include <stdint.h>
#include <stddef.h>

#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
#define __CLANG_ATOMICS
#elif __GNUC_PREREQ__(4, 7) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define __GNUC11_ATOMICS
#elif __GNUC_PREREQ__(4, 7)
#define __GNUC_ATOMICS
#elif defined(__GNUC__)
Expand Down Expand Up @@ -85,6 +89,9 @@
#if defined(__CLANG_ATOMICS)
#define ATOMIC_VAR_INIT(value) (value)
#define atomic_init(obj, value) __c11_atomic_init(obj, value)
#elif defined(__GNUC11_ATOMICS)
#define ATOMIC_VAR_INIT(value) (value)
#define atomic_init(obj, value) ((void)(*(obj) = (value)))
#else
#define ATOMIC_VAR_INIT(value) { .__val = (value) }
#define atomic_init(obj, value) ((void)((obj)->__val = (value)))
Expand Down Expand Up @@ -141,7 +148,7 @@ atomic_thread_fence(memory_order __order __unused)

#ifdef __CLANG_ATOMICS
__c11_atomic_thread_fence(__order);
#elif defined(__GNUC_ATOMICS)
#elif defined(__GNUC_ATOMICS) || defined(__GNUC11_ATOMICS)
__atomic_thread_fence(__order);
#else
__sync_synchronize();
Expand All @@ -154,7 +161,7 @@ atomic_signal_fence(memory_order __order __unused)

#ifdef __CLANG_ATOMICS
__c11_atomic_signal_fence(__order);
#elif defined(__GNUC_ATOMICS)
#elif defined(__GNUC_ATOMICS) || defined(__GNUC11_ATOMICS)
__atomic_signal_fence(__order);
#else
__asm volatile ("" ::: "memory");
Expand All @@ -169,9 +176,15 @@ atomic_signal_fence(memory_order __order __unused)
/* Atomics in kernelspace are always lock-free. */
#define atomic_is_lock_free(obj) \
((void)(obj), (_Bool)1)
#elif defined(__CLANG_ATOMICS) || defined(__GNUC_ATOMICS)
#elif defined(__CLANG_ATOMICS)
#define atomic_is_lock_free(obj) \
__atomic_is_lock_free(sizeof(*(obj)), obj)
#elif defined(__GNUC11_ATOMICS)
#define atomic_is_lock_free(obj) \
__atomic_is_lock_free(sizeof(*(obj)), (obj))
#elif defined(__GNUC_ATOMICS)
#define atomic_is_lock_free(obj) \
__atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
#else
#define atomic_is_lock_free(obj) \
((void)(obj), sizeof((obj)->__val) <= sizeof(void *))
Expand Down Expand Up @@ -254,7 +267,7 @@ typedef _Atomic(uintmax_t) atomic_uintmax_t;
__c11_atomic_load(object, order)
#define atomic_store_explicit(object, desired, order) \
__c11_atomic_store(object, desired, order)
#elif defined(__GNUC_ATOMICS)
#elif defined(__GNUC11_ATOMICS)
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(object, expected, \
Expand All @@ -279,6 +292,31 @@ typedef _Atomic(uintmax_t) atomic_uintmax_t;
__atomic_load_n(object, order)
#define atomic_store_explicit(object, desired, order) \
__atomic_store_n(object, desired, order)
#elif defined(__GNUC_ATOMICS)
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(&(object)->__val, expected, \
desired, 0, success, failure)
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(&(object)->__val, expected, \
desired, 1, success, failure)
#define atomic_exchange_explicit(object, desired, order) \
__atomic_exchange_n(&(object)->__val, desired, order)
#define atomic_fetch_add_explicit(object, operand, order) \
__atomic_fetch_add(&(object)->__val, operand, order)
#define atomic_fetch_and_explicit(object, operand, order) \
__atomic_fetch_and(&(object)->__val, operand, order)
#define atomic_fetch_or_explicit(object, operand, order) \
__atomic_fetch_or(&(object)->__val, operand, order)
#define atomic_fetch_sub_explicit(object, operand, order) \
__atomic_fetch_sub(&(object)->__val, operand, order)
#define atomic_fetch_xor_explicit(object, operand, order) \
__atomic_fetch_xor(&(object)->__val, operand, order)
#define atomic_load_explicit(object, order) \
__atomic_load_n(&(object)->__val, order)
#define atomic_store_explicit(object, desired, order) \
__atomic_store_n(&(object)->__val, desired, order)
#else
#define __atomic_apply_stride(object, operand) \
(((__typeof__((object)->__val))0) + (operand))
Expand Down

0 comments on commit 6b2a582

Please sign in to comment.