[PATCH] atomic: Switch to builtin atomics

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Mon Sep 8 15:43:24 GMT 2025



On 08/09/25 09:56, Wilco Dijkstra wrote:
> 
> Switch to standard builtin atomics by removing the defines for !USE_ATOMIC_COMPILER_BUILTINS.
> Fix m68k to __HAVE_64B_ATOMICS set to 0.
> 
> Passes buildmanyglibc, OK for commit?

Currently !USE_ATOMIC_COMPILER_BUILTINS is used for alpha, m68k, m68k-coldfire,
hppa, microblaze, powerpc, and sh.

  * For alpha, microblaze, powerpc, and hs the current minimum gcc version now correctly 
    implements all __atomic* builtins so it should be ok to switch.

  * m68k the -m68000/-m68010 generates libcalls, but afaik we never supported such
    system anyway [1].  So it should be ok to make the switch and just remove all
    the old atomic definitions.

  * m68k-coldfire this will make sysdeps/unix/sysv/linux/m68k/coldfire/atomic-machine.h
    dead-code; since libgcc __sync routines will be used instead.  As for m68k,
    it is ok since for cases it route to the atomic_cmpxchg_32 syscall anyway
    so the extra function call should not matter (and it improves code size).

  * hppa the resulting libc.so how has the __sync_* symbol as for m68k-colfire,
    also making sysdeps/unix/sysv/linux/hppa/atomic-machine.h definitions unused.
    And the switch should also be ok, although I am not sure about performance
    implications (since HPPA uses a 'kernel atomic light weight syscalls' which
    guess is something akim a vsyscall/vdso.
  
I think it would be safer if we disable this per ABI basis, instead of a hard
switch for all of them; and remove the unused definitions along. The m68k fix
would be better in a different patch.

[1] http://www.linux-m68k.org/

> 
> ---
> 
> diff --git a/include/atomic.h b/include/atomic.h
> index 44a4ce8d711f3460194b15a1bf2c1bd8f33399a7..dbfaa3f156c3673c46865c36ed915212989e7a8e 100644
> --- a/include/atomic.h
> +++ b/include/atomic.h
> @@ -198,10 +198,6 @@
>     C11.  Usually, a function named atomic_OP_MO(args) is equivalent to C11's
>     atomic_OP_explicit(args, memory_order_MO); exceptions noted below.  */
>  
> -/* Each arch can request to use compiler built-ins for C11 atomics.  If it
> -   does, all atomics will be based on these.  */
> -#if USE_ATOMIC_COMPILER_BUILTINS
> -
>  /* We require 32b atomic operations; some archs also support 64b atomic
>     operations.  */
>  void __atomic_link_error (void);
> @@ -315,167 +311,6 @@ void __atomic_link_error (void);
>    ({ __atomic_check_size((mem));					      \
>    __atomic_fetch_xor ((mem), (operand), __ATOMIC_RELEASE); })
>  
> -#else /* !USE_ATOMIC_COMPILER_BUILTINS  */
> -
> -/* By default, we assume that read, write, and full barriers are equivalent
> -   to acquire, release, and seq_cst barriers.  Archs for which this does not
> -   hold have to provide custom definitions of the fences.  */
> -# ifndef atomic_thread_fence_acquire
> -#  define atomic_thread_fence_acquire() atomic_read_barrier ()
> -# endif
> -# ifndef atomic_thread_fence_release
> -#  define atomic_thread_fence_release() atomic_write_barrier ()
> -# endif
> -# ifndef atomic_thread_fence_seq_cst
> -#  define atomic_thread_fence_seq_cst() atomic_full_barrier ()
> -# endif
> -
> -# ifndef atomic_load_relaxed
> -#  define atomic_load_relaxed(mem) \
> -   ({ __typeof ((__typeof (*(mem))) *(mem)) __atg100_val;		      \
> -   __asm ("" : "=r" (__atg100_val) : "0" (*(mem)));			      \
> -   __atg100_val; })
> -# endif
> -# ifndef atomic_load_acquire
> -#  define atomic_load_acquire(mem) \
> -   ({ __typeof (*(mem)) __atg101_val = atomic_load_relaxed (mem);	      \
> -   atomic_thread_fence_acquire ();					      \
> -   __atg101_val; })
> -# endif
> -
> -# ifndef atomic_store_relaxed
> -/* XXX Use inline asm here?  */
> -#  define atomic_store_relaxed(mem, val) do { *(mem) = (val); } while (0)
> -# endif
> -# ifndef atomic_store_release
> -#  define atomic_store_release(mem, val) \
> -   do {									      \
> -     atomic_thread_fence_release ();					      \
> -     atomic_store_relaxed ((mem), (val));				      \
> -   } while (0)
> -# endif
> -
> -/* On failure, this CAS has memory_order_relaxed semantics.  */
> -/* XXX This potentially has one branch more than necessary, but archs
> -   currently do not define a CAS that returns both the previous value and
> -   the success flag.  */
> -# ifndef atomic_compare_exchange_weak_acquire
> -#  define atomic_compare_exchange_weak_acquire(mem, expected, desired) \
> -   ({ typeof (*(expected)) __atg102_expected = *(expected);		      \
> -   *(expected) =							      \
> -     atomic_compare_and_exchange_val_acq ((mem), (desired), *(expected));     \
> -   *(expected) == __atg102_expected; })
> -# endif
> -# ifndef atomic_compare_exchange_weak_relaxed
> -/* XXX Fall back to CAS with acquire MO because archs do not define a weaker
> -   CAS.  */
> -#  define atomic_compare_exchange_weak_relaxed(mem, expected, desired) \
> -   atomic_compare_exchange_weak_acquire ((mem), (expected), (desired))
> -# endif
> -# ifndef atomic_compare_exchange_weak_release
> -#  define atomic_compare_exchange_weak_release(mem, expected, desired) \
> -   ({ typeof (*(expected)) __atg103_expected = *(expected);		      \
> -   *(expected) =							      \
> -     atomic_compare_and_exchange_val_rel ((mem), (desired), *(expected));     \
> -   *(expected) == __atg103_expected; })
> -# endif
> -
> -/* XXX Fall back to acquire MO because archs do not define a weaker
> -   atomic_exchange.  */
> -# ifndef atomic_exchange_relaxed
> -#  define atomic_exchange_relaxed(mem, val) \
> -   atomic_exchange_acq ((mem), (val))
> -# endif
> -# ifndef atomic_exchange_acquire
> -#  define atomic_exchange_acquire(mem, val) \
> -   atomic_exchange_acq ((mem), (val))
> -# endif
> -# ifndef atomic_exchange_release
> -#  define atomic_exchange_release(mem, val) \
> -   atomic_exchange_rel ((mem), (val))
> -# endif
> -
> -# ifndef atomic_fetch_add_acquire
> -#  define atomic_fetch_add_acquire(mem, operand) \
> -   atomic_exchange_and_add_acq ((mem), (operand))
> -# endif
> -# ifndef atomic_fetch_add_relaxed
> -/* XXX Fall back to acquire MO because the MO semantics of
> -   atomic_exchange_and_add are not documented; the generic version falls back
> -   to atomic_exchange_and_add_acq if atomic_exchange_and_add is not defined,
> -   and vice versa.  */
> -#  define atomic_fetch_add_relaxed(mem, operand) \
> -   atomic_fetch_add_acquire ((mem), (operand))
> -# endif
> -# ifndef atomic_fetch_add_release
> -#  define atomic_fetch_add_release(mem, operand) \
> -   atomic_exchange_and_add_rel ((mem), (operand))
> -# endif
> -# ifndef atomic_fetch_add_acq_rel
> -#  define atomic_fetch_add_acq_rel(mem, operand) \
> -   ({ atomic_thread_fence_release ();					      \
> -   atomic_exchange_and_add_acq ((mem), (operand)); })
> -# endif
> -
> -/* XXX Fall back to acquire MO because archs do not define a weaker
> -   atomic_and_val.  */
> -# ifndef atomic_fetch_and_relaxed
> -#  define atomic_fetch_and_relaxed(mem, operand) \
> -   atomic_fetch_and_acquire ((mem), (operand))
> -# endif
> -/* XXX The default for atomic_and_val has acquire semantics, but this is not
> -   documented.  */
> -# ifndef atomic_fetch_and_acquire
> -#  define atomic_fetch_and_acquire(mem, operand) \
> -   atomic_and_val ((mem), (operand))
> -# endif
> -# ifndef atomic_fetch_and_release
> -/* XXX This unnecessarily has acquire MO.  */
> -#  define atomic_fetch_and_release(mem, operand) \
> -   ({ atomic_thread_fence_release ();					      \
> -   atomic_and_val ((mem), (operand)); })
> -# endif
> -
> -/* XXX The default for atomic_or_val has acquire semantics, but this is not
> -   documented.  */
> -# ifndef atomic_fetch_or_acquire
> -#  define atomic_fetch_or_acquire(mem, operand) \
> -   atomic_or_val ((mem), (operand))
> -# endif
> -/* XXX Fall back to acquire MO because archs do not define a weaker
> -   atomic_or_val.  */
> -# ifndef atomic_fetch_or_relaxed
> -#  define atomic_fetch_or_relaxed(mem, operand) \
> -   atomic_fetch_or_acquire ((mem), (operand))
> -# endif
> -/* XXX Contains an unnecessary acquire MO because archs do not define a weaker
> -   atomic_or_val.  */
> -# ifndef atomic_fetch_or_release
> -#  define atomic_fetch_or_release(mem, operand) \
> -   ({ atomic_thread_fence_release ();					      \
> -   atomic_fetch_or_acquire ((mem), (operand)); })
> -# endif
> -
> -# ifndef atomic_fetch_xor_release
> -/* Failing the atomic_compare_exchange_weak_release reloads the value in
> -   __atg104_expected, so we need only do the XOR again and retry.  */
> -# define atomic_fetch_xor_release(mem, operand) \
> -  ({ __typeof (mem) __atg104_memp = (mem);				      \
> -     __typeof (*(mem)) __atg104_expected = (*__atg104_memp);		      \
> -     __typeof (*(mem)) __atg104_desired;				      \
> -     __typeof (*(mem)) __atg104_op = (operand);				      \
> -									      \
> -     do									      \
> -       __atg104_desired = __atg104_expected ^ __atg104_op;		      \
> -     while (__glibc_unlikely						      \
> -	    (atomic_compare_exchange_weak_release (			      \
> -	       __atg104_memp, &__atg104_expected, __atg104_desired)	      \
> -	     == 0));							      \
> -     __atg104_expected; })
> -#endif
> -
> -#endif /* !USE_ATOMIC_COMPILER_BUILTINS  */
> -
>  /* This operation does not affect synchronization semantics but can be used
>     in the body of a spin loop to potentially improve its efficiency.  */
>  #ifndef atomic_spin_nop
> diff --git a/sysdeps/m68k/m680x0/m68020/atomic-machine.h b/sysdeps/m68k/m680x0/m68020/atomic-machine.h
> index 9d25fbc194182c9f2dc08fad33031a4de5b2c6bf..d586d06d89b85162aaaeb9ec2c5eadde433d6e2c 100644
> --- a/sysdeps/m68k/m680x0/m68020/atomic-machine.h
> +++ b/sysdeps/m68k/m680x0/m68020/atomic-machine.h
> @@ -15,7 +15,7 @@
>     License along with the GNU C Library.  If not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#define __HAVE_64B_ATOMICS 1
> +#define __HAVE_64B_ATOMICS 0
>  #define USE_ATOMIC_COMPILER_BUILTINS 0
>  
>  /* XXX Is this actually correct?  */
> 



More information about the Libc-alpha mailing list