nptl: Remove ATOMIC_EXCHANGE_USES_CAS usage

The only usage was for pthread_spin_lock, introduced by 12d2dd7060,
as a way to optimize the code for certain architectures. Now that atomic
builtins are used by default, let the compiler use the best code sequence
for the atomic exchange.

Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
This commit is contained in:
Wilco Dijkstra 2025-09-11 10:49:48 -03:00 committed by Adhemerval Zanella
parent 53807741fb
commit 324c088a18
23 changed files with 32 additions and 427 deletions

View File

@ -258,12 +258,4 @@ void __atomic_link_error (void);
# define atomic_spin_nop() do { /* nothing */ } while (0)
#endif
/* ATOMIC_EXCHANGE_USES_CAS is non-zero if atomic_exchange operations
are implemented based on a CAS loop; otherwise, this is zero and we assume
that the atomic_exchange operations could provide better performance
than a CAS loop. */
#ifndef ATOMIC_EXCHANGE_USES_CAS
# error ATOMIC_EXCHANGE_USES_CAS has to be defined.
#endif
#endif /* atomic.h */

View File

@ -26,29 +26,12 @@ __pthread_spin_lock (pthread_spinlock_t *lock)
int val = 0;
/* We assume that the first try mostly will be successful, thus we use
atomic_exchange if it is not implemented by a CAS loop (we also assume
that atomic_exchange can be faster if it succeeds, see
ATOMIC_EXCHANGE_USES_CAS). Otherwise, we use a weak CAS and not an
exchange so we bail out after the first failed attempt to change the
state. For the subsequent attempts we use atomic_compare_and_exchange
after we observe that the lock is not acquired.
See also comment in pthread_spin_trylock.
atomic_exchange.
We use acquire MO to synchronize-with the release MO store in
pthread_spin_unlock, and thus ensure that prior critical sections
happen-before this critical section. */
#if ! ATOMIC_EXCHANGE_USES_CAS
/* Try to acquire the lock with an exchange instruction as this architecture
has such an instruction and we assume it is faster than a CAS.
The acquisition succeeds if the lock is not in an acquired state. */
if (__glibc_likely (atomic_exchange_acquire (lock, 1) == 0))
return 0;
#else
/* Try to acquire the lock with a CAS instruction as this architecture
has no exchange instruction. The acquisition succeeds if the lock is not
acquired. */
if (__glibc_likely (atomic_compare_exchange_weak_acquire (lock, &val, 1)))
return 0;
#endif
do
{

View File

@ -24,57 +24,8 @@
int
__pthread_spin_trylock (pthread_spinlock_t *lock)
{
/* For the spin try lock, we have the following possibilities:
1) If we assume that trylock will most likely succeed in practice:
* We just do an exchange.
2) If we want to bias towards cases where trylock succeeds, but don't
rule out contention:
* If exchange is not implemented by a CAS loop, and exchange is faster
than CAS, do an exchange.
* If exchange is implemented by a CAS loop, use a weak CAS and not an
exchange so we bail out after the first failed attempt to change the state.
3) If we expect contention to be likely:
* If CAS always brings the cache line into an exclusive state even if the
spinlock is already acquired, then load the value first with
atomic_load_relaxed and test if lock is not acquired. Then do 2).
We assume that 2) is the common case, and that this won't be slower than
1) in the common case.
We use acquire MO to synchronize-with the release MO store in
pthread_spin_unlock, and thus ensure that prior critical sections
happen-before this critical section. */
#if ! ATOMIC_EXCHANGE_USES_CAS
/* Try to acquire the lock with an exchange instruction as this architecture
has such an instruction and we assume it is faster than a CAS.
The acquisition succeeds if the lock is not in an acquired state. */
if (atomic_exchange_acquire (lock, 1) == 0)
return 0;
#else
/* Try to acquire the lock with a CAS instruction as this architecture
has no exchange instruction. The acquisition succeeds if the lock is not
acquired. */
do
{
int val = 0;
if (atomic_compare_exchange_weak_acquire (lock, &val, 1))
return 0;
}
/* atomic_compare_exchange_weak_acquire can fail spuriously. Whereas
C++11 and C11 make it clear that trylock operations can fail spuriously,
POSIX does not explicitly specify this; it only specifies that failing
synchronization operations do not need to have synchronization effects
themselves, but a spurious failure is something that could contradict a
happens-before established earlier (e.g., that we need to observe that
the lock is acquired). Therefore, we emulate a strong CAS by simply
checking with a relaxed MO load that the lock is really acquired before
returning EBUSY; the additional overhead this may cause is on the slow
path. */
while (atomic_load_relaxed (lock) == 0);
#endif
return EBUSY;
}

View File

@ -1,24 +0,0 @@
/* Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _AARCH64_ATOMIC_MACHINE_H
#define _AARCH64_ATOMIC_MACHINE_H 1
#define ATOMIC_EXCHANGE_USES_CAS 0
#endif

View File

@ -17,7 +17,4 @@
#include <stdint.h>
/* XXX Is this actually correct? */
#define ATOMIC_EXCHANGE_USES_CAS 1
#define atomic_write_barrier() __asm ("wmb" : : : "memory");

View File

@ -1,26 +0,0 @@
/* Low-level functions for atomic operations. ARC version.
Copyright (C) 2020-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _ARC_BITS_ATOMIC_H
#define _ARC_BITS_ATOMIC_H 1
/* ARC does have legacy atomic EX reg, [mem] instruction but the micro-arch
is not as optimal as LLOCK/SCOND specially for SMP. */
#define ATOMIC_EXCHANGE_USES_CAS 1
#endif /* _ARC_BITS_ATOMIC_H */

View File

@ -1,19 +0,0 @@
/* Atomic operations. Pure ARM version.
Copyright (C) 2002-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#define ATOMIC_EXCHANGE_USES_CAS 1

View File

@ -1,24 +0,0 @@
/* Atomic operations. C-SKY version.
Copyright (C) 2018-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef __CSKY_ATOMIC_H_
#define __CSKY_ATOMIC_H_
#define ATOMIC_EXCHANGE_USES_CAS 1
#endif /* atomic-machine.h */

View File

@ -18,24 +18,20 @@
#ifndef _ATOMIC_MACHINE_H
#define _ATOMIC_MACHINE_H 1
/* We have by default no support for atomic operations. So define
them non-atomic. If this is a problem somebody will have to come
up with real definitions. */
/* Some macros can be overridden if the architecture requires some specific
atomic operations or provides extra optimizations.
/* The only basic operation needed is compare and exchange. */
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
({ __typeof (mem) __gmemp = (mem); \
__typeof (*mem) __gret = *__gmemp; \
__typeof (*mem) __gnewval = (newval); \
\
if (__gret == (oldval)) \
*__gmemp = __gnewval; \
__gret; })
* atomic_max (mem, value): atomically set the maximum value of *mem
and value to *mem. Used on malloc statistics collection.
#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
({ __typeof (mem) __gmemp = (mem); \
__typeof (*mem) __gnewval = (newval); \
\
*__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; })
* atomic_full_barrier: defaults to __atomic_thread_fence (__ATOMIC_SEQ_CST)
* atomic_read_barrier: defaults to __atomic_thread_fence (__ATOMIC_ACQUIRE)
* atomic_write_barrier: defaults to __atomic_thread_fence (__ATOMIC_RELEASE)
* atomic_spin_nop: arch-specific instruction used on pthread spin lock
and adaptive mutexes to optimize spin-wait loops.
*/
#endif /* atomic-machine.h */

View File

@ -1,24 +0,0 @@
/* Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _ATOMIC_MACHINE_H
#define _ATOMIC_MACHINE_H 1
/* XXX Is this actually correct? */
#define ATOMIC_EXCHANGE_USES_CAS 1
#endif

View File

@ -1,24 +0,0 @@
/* Atomic operations.
Copyright (C) 2022-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _LINUX_LOONGARCH_BITS_ATOMIC_H
#define _LINUX_LOONGARCH_BITS_ATOMIC_H 1
#define ATOMIC_EXCHANGE_USES_CAS 0
#endif /* bits/atomic.h */

View File

@ -1,28 +0,0 @@
/* Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _M68K_ATOMIC_MACHINE_H
#define _M68K_ATOMIC_MACHINE_H 1
#if defined __mc68020__ || defined __mcoldfire__
/* XXX Is this actually correct? */
# define ATOMIC_EXCHANGE_USES_CAS 1
#else
# error "ISAs does not support atomic operations"
#endif
#endif

View File

@ -1,22 +0,0 @@
/* Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/* XXX Is this actually correct? */
#define ATOMIC_EXCHANGE_USES_CAS 1

View File

@ -1,38 +0,0 @@
/* Low-level functions for atomic operations. Mips version.
Copyright (C) 2005-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _MIPS_ATOMIC_MACHINE_H
#define _MIPS_ATOMIC_MACHINE_H 1
#include <sgidefs.h>
#if _MIPS_SIM == _ABIO32 && __mips < 2
#define MIPS_PUSH_MIPS2 ".set mips2\n\t"
#else
#define MIPS_PUSH_MIPS2
#endif
/* MIPS is an LL/SC machine. However, XLP has a direct atomic exchange
instruction which will be used by __atomic_exchange_n. */
#ifdef _MIPS_ARCH_XLP
# define ATOMIC_EXCHANGE_USES_CAS 0
#else
# define ATOMIC_EXCHANGE_USES_CAS 1
#endif
#endif /* atomic-machine.h */

View File

@ -1,24 +0,0 @@
/* Atomic operations. OpenRISC version.
Copyright (C) 2022-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef __OR1K_ATOMIC_H_
#define __OR1K_ATOMIC_H_
#define ATOMIC_EXCHANGE_USES_CAS 1
#endif /* atomic-machine.h */

View File

@ -1,34 +0,0 @@
/* Atomic operations. PowerPC Common version.
Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _POWERPC_ATOMIC_MACHINE_H
#define _POWERPC_ATOMIC_MACHINE_H 1
#define ATOMIC_EXCHANGE_USES_CAS 1
/* Used on pthread_spin_{try}lock. */
#define __ARCH_ACQ_INSTR "isync"
#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
# define MUTEX_HINT_ACQ ",1"
# define MUTEX_HINT_REL ",0"
#else
# define MUTEX_HINT_ACQ
# define MUTEX_HINT_REL
#endif
#endif

View File

@ -18,6 +18,15 @@
#include "pthreadP.h"
#include <shlib-compat.h>
#define __ARCH_ACQ_INSTR "isync"
#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
# define MUTEX_HINT_ACQ ",1"
# define MUTEX_HINT_REL ",0"
#else
# define MUTEX_HINT_ACQ
# define MUTEX_HINT_REL
#endif
int
__pthread_spin_lock (pthread_spinlock_t *lock)
{

View File

@ -19,6 +19,15 @@
#include "pthreadP.h"
#include <shlib-compat.h>
#define __ARCH_ACQ_INSTR "isync"
#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
# define MUTEX_HINT_ACQ ",1"
# define MUTEX_HINT_REL ",0"
#else
# define MUTEX_HINT_ACQ
# define MUTEX_HINT_REL
#endif
int
__pthread_spin_trylock (pthread_spinlock_t *lock)
{

View File

@ -21,8 +21,6 @@
#ifdef __riscv_atomic
# define ATOMIC_EXCHANGE_USES_CAS 0
/* Miscellaneous. */
# define asm_amo(which, ordering, mem, value) ({ \

View File

@ -1,18 +0,0 @@
/* Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define ATOMIC_EXCHANGE_USES_CAS 1

View File

@ -1,20 +0,0 @@
/* Atomic operations used inside libc. Linux/SH version.
Copyright (C) 2003-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* XXX Is this actually correct? */
#define ATOMIC_EXCHANGE_USES_CAS 1

View File

@ -19,9 +19,6 @@
#ifndef _ATOMIC_MACHINE_H
#define _ATOMIC_MACHINE_H 1
/* XXX Is this actually correct? */
#define ATOMIC_EXCHANGE_USES_CAS __HAVE_64B_ATOMICS
#ifdef __sparc_v9__
# define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \

View File

@ -19,8 +19,6 @@
#ifndef _X86_ATOMIC_MACHINE_H
#define _X86_ATOMIC_MACHINE_H 1
#define ATOMIC_EXCHANGE_USES_CAS 0
#define atomic_spin_nop() __asm ("pause")
#endif /* atomic-machine.h */