Message ID | 20211231064455.1030051-8-caiyinyu@loongson.cn |
---|---|
State | New |
Headers | show |
Series | GLIBC LoongArch PATCHES | expand |
On 31/12/2021 03:44, caiyinyu wrote: > This patch implements various atomic and locking routines on LoongArch. > --- > .../loongarch/nptl/bits/pthreadtypes-arch.h | 41 ++++ > sysdeps/loongarch/nptl/bits/semaphore.h | 32 +++ > sysdeps/loongarch/nptl/libc-lowlevellock.c | 8 + > .../sysv/linux/loongarch/atomic-machine.h | 196 ++++++++++++++++++ > 4 files changed, 277 insertions(+) > create mode 100644 sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h > create mode 100644 sysdeps/loongarch/nptl/bits/semaphore.h > create mode 100644 sysdeps/loongarch/nptl/libc-lowlevellock.c > create mode 100644 sysdeps/unix/sysv/linux/loongarch/atomic-machine.h > > diff --git a/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h > new file mode 100644 > index 0000000000..e57f122a98 > --- /dev/null > +++ b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h > @@ -0,0 +1,41 @@ > +/* Machine-specific pthread type layouts. > + Copyright (C) 2021 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 _BITS_PTHREADTYPES_ARCH_H > +#define _BITS_PTHREADTYPES_ARCH_H 1 > + > +#include <bits/endian.h> > + > +#ifdef __loongarch_lp64 > +#define __SIZEOF_PTHREAD_ATTR_T 56 > +#define __SIZEOF_PTHREAD_MUTEX_T 40 > +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 > +#define __SIZEOF_PTHREAD_COND_T 48 > +#define __SIZEOF_PTHREAD_CONDATTR_T 4 > +#define __SIZEOF_PTHREAD_RWLOCK_T 56 > +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 > +#define __SIZEOF_PTHREAD_BARRIER_T 32 > +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 > +#else > +#error "32bit LoongArch systems are not supported" > +#endif > + > +#define __LOCK_ALIGNMENT > +#define __ONCE_ALIGNMENT > + > +#endif /* bits/pthreadtypes.h */ Why can't you use the generic definition? Also, I think all the __loongarch_lp64 tests to avoid 32-bit build should be moved to a configure test instead. > diff --git a/sysdeps/loongarch/nptl/bits/semaphore.h b/sysdeps/loongarch/nptl/bits/semaphore.h > new file mode 100644 > index 0000000000..510f3b0e9a > --- /dev/null > +++ b/sysdeps/loongarch/nptl/bits/semaphore.h > @@ -0,0 +1,32 @@ > +/* POSIX semaphore type layout > + Copyright (C) 2021 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 _SEMAPHORE_H > +#error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." > +#endif > + > +#define __SIZEOF_SEM_T (4 * __SIZEOF_POINTER__) > + > +/* Value returned if `sem_open' failed. */ > +#define SEM_FAILED ((sem_t *) 0) > + > +typedef union > +{ > + char __size[__SIZEOF_SEM_T]; > + long int __align; > +} sem_t; Why can't you use the generic linux header interface? > diff --git a/sysdeps/loongarch/nptl/libc-lowlevellock.c b/sysdeps/loongarch/nptl/libc-lowlevellock.c > new file mode 100644 > index 0000000000..f4b8b5c193 > --- /dev/null > +++ b/sysdeps/loongarch/nptl/libc-lowlevellock.c > @@ -0,0 +1,8 @@ > +/* This kludge works around a libpthread static linking problem: > + https://sourceware.org/bugzilla/show_bug.cgi?id=15648. */ > + > +#ifndef SHARED > +#define __lll_lock_wait_private weak_function __lll_lock_wait_private > +#endif > + > +#include <lowlevellock.c> Why this file is required? > diff --git a/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h > new file mode 100644 > index 0000000000..dbae608ee5 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h > @@ -0,0 +1,196 @@ > +/* Atomic operations. > + Copyright (C) 2021 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 > + > +#include <stdint.h> > + > +typedef int32_t atomic32_t; > +typedef uint32_t uatomic32_t; > + > +typedef int64_t atomic64_t; > +typedef uint64_t uatomic64_t; > + > +typedef intptr_t atomicptr_t; > +typedef uintptr_t uatomicptr_t; > +typedef intmax_t atomic_max_t; > +typedef uintmax_t uatomic_max_t; These definition are not required any longer. > + > +#define atomic_full_barrier() __sync_synchronize () > + > +#ifdef __LP64__ > +#define __HAVE_64B_ATOMICS 1 > +#endif I think there is no need to guard it for __LP64__.
在 2022/1/4 下午10:09, Adhemerval Zanella 写道: > On 31/12/2021 03:44, caiyinyu wrote: >> This patch implements various atomic and locking routines on LoongArch. >> --- >> .../loongarch/nptl/bits/pthreadtypes-arch.h | 41 ++++ >> sysdeps/loongarch/nptl/bits/semaphore.h | 32 +++ >> sysdeps/loongarch/nptl/libc-lowlevellock.c | 8 + >> .../sysv/linux/loongarch/atomic-machine.h | 196 ++++++++++++++++++ >> 4 files changed, 277 insertions(+) >> create mode 100644 sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h >> create mode 100644 sysdeps/loongarch/nptl/bits/semaphore.h >> create mode 100644 sysdeps/loongarch/nptl/libc-lowlevellock.c >> create mode 100644 sysdeps/unix/sysv/linux/loongarch/atomic-machine.h >> >> diff --git a/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h >> new file mode 100644 >> index 0000000000..e57f122a98 >> --- /dev/null >> +++ b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h >> @@ -0,0 +1,41 @@ >> +/* Machine-specific pthread type layouts. >> + Copyright (C) 2021 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 _BITS_PTHREADTYPES_ARCH_H >> +#define _BITS_PTHREADTYPES_ARCH_H 1 >> + >> +#include <bits/endian.h> >> + >> +#ifdef __loongarch_lp64 >> +#define __SIZEOF_PTHREAD_ATTR_T 56 >> +#define __SIZEOF_PTHREAD_MUTEX_T 40 >> +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 >> +#define __SIZEOF_PTHREAD_COND_T 48 >> +#define __SIZEOF_PTHREAD_CONDATTR_T 4 >> +#define __SIZEOF_PTHREAD_RWLOCK_T 56 >> +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 >> +#define __SIZEOF_PTHREAD_BARRIER_T 32 >> +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 >> +#else >> +#error "32bit LoongArch systems are not supported" >> +#endif >> + >> +#define __LOCK_ALIGNMENT >> +#define __ONCE_ALIGNMENT >> + >> +#endif /* bits/pthreadtypes.h */ > Why can't you use the generic definition? Also, I think all the __loongarch_lp64 > tests to avoid 32-bit build should be moved to a configure test instead. Fixed by using generic definition and __loongarch_lp64 tests have been moved to configure test. >> diff --git a/sysdeps/loongarch/nptl/bits/semaphore.h b/sysdeps/loongarch/nptl/bits/semaphore.h >> new file mode 100644 >> index 0000000000..510f3b0e9a >> --- /dev/null >> +++ b/sysdeps/loongarch/nptl/bits/semaphore.h >> @@ -0,0 +1,32 @@ >> +/* POSIX semaphore type layout >> + Copyright (C) 2021 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 _SEMAPHORE_H >> +#error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." >> +#endif >> + >> +#define __SIZEOF_SEM_T (4 * __SIZEOF_POINTER__) >> + >> +/* Value returned if `sem_open' failed. */ >> +#define SEM_FAILED ((sem_t *) 0) >> + >> +typedef union >> +{ >> + char __size[__SIZEOF_SEM_T]; >> + long int __align; >> +} sem_t; > Why can't you use the generic linux header interface? Fixed by using generic linux header interface. >> diff --git a/sysdeps/loongarch/nptl/libc-lowlevellock.c b/sysdeps/loongarch/nptl/libc-lowlevellock.c >> new file mode 100644 >> index 0000000000..f4b8b5c193 >> --- /dev/null >> +++ b/sysdeps/loongarch/nptl/libc-lowlevellock.c >> @@ -0,0 +1,8 @@ >> +/* This kludge works around a libpthread static linking problem: >> +https://sourceware.org/bugzilla/show_bug.cgi?id=15648. */ >> + >> +#ifndef SHARED >> +#define __lll_lock_wait_private weak_function __lll_lock_wait_private >> +#endif >> + >> +#include <lowlevellock.c> > Why this file is required? Fixed by removing libc-lowlevellock.c >> diff --git a/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h >> new file mode 100644 >> index 0000000000..dbae608ee5 >> --- /dev/null >> +++ b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h >> @@ -0,0 +1,196 @@ >> +/* Atomic operations. >> + Copyright (C) 2021 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 >> + >> +#include <stdint.h> >> + >> +typedef int32_t atomic32_t; >> +typedef uint32_t uatomic32_t; >> + >> +typedef int64_t atomic64_t; >> +typedef uint64_t uatomic64_t; >> + >> +typedef intptr_t atomicptr_t; >> +typedef uintptr_t uatomicptr_t; >> +typedef intmax_t atomic_max_t; >> +typedef uintmax_t uatomic_max_t; > These definition are not required any longer. Fixed. >> + >> +#define atomic_full_barrier() __sync_synchronize () >> + >> +#ifdef __LP64__ >> +#define __HAVE_64B_ATOMICS 1 >> +#endif > I think there is no need to guard it for __LP64__. Fixed.
diff --git a/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h new file mode 100644 index 0000000000..e57f122a98 --- /dev/null +++ b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h @@ -0,0 +1,41 @@ +/* Machine-specific pthread type layouts. + Copyright (C) 2021 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 _BITS_PTHREADTYPES_ARCH_H +#define _BITS_PTHREADTYPES_ARCH_H 1 + +#include <bits/endian.h> + +#ifdef __loongarch_lp64 +#define __SIZEOF_PTHREAD_ATTR_T 56 +#define __SIZEOF_PTHREAD_MUTEX_T 40 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 56 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 32 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +#error "32bit LoongArch systems are not supported" +#endif + +#define __LOCK_ALIGNMENT +#define __ONCE_ALIGNMENT + +#endif /* bits/pthreadtypes.h */ diff --git a/sysdeps/loongarch/nptl/bits/semaphore.h b/sysdeps/loongarch/nptl/bits/semaphore.h new file mode 100644 index 0000000000..510f3b0e9a --- /dev/null +++ b/sysdeps/loongarch/nptl/bits/semaphore.h @@ -0,0 +1,32 @@ +/* POSIX semaphore type layout + Copyright (C) 2021 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 _SEMAPHORE_H +#error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#define __SIZEOF_SEM_T (4 * __SIZEOF_POINTER__) + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/sysdeps/loongarch/nptl/libc-lowlevellock.c b/sysdeps/loongarch/nptl/libc-lowlevellock.c new file mode 100644 index 0000000000..f4b8b5c193 --- /dev/null +++ b/sysdeps/loongarch/nptl/libc-lowlevellock.c @@ -0,0 +1,8 @@ +/* This kludge works around a libpthread static linking problem: + https://sourceware.org/bugzilla/show_bug.cgi?id=15648. */ + +#ifndef SHARED +#define __lll_lock_wait_private weak_function __lll_lock_wait_private +#endif + +#include <lowlevellock.c> diff --git a/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h new file mode 100644 index 0000000000..dbae608ee5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h @@ -0,0 +1,196 @@ +/* Atomic operations. + Copyright (C) 2021 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 + +#include <stdint.h> + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +#define atomic_full_barrier() __sync_synchronize () + +#ifdef __LP64__ +#define __HAVE_64B_ATOMICS 1 +#endif +#define USE_ATOMIC_COMPILER_BUILTINS 1 +#define ATOMIC_EXCHANGE_USES_CAS 0 + +/* Compare and exchange. + For all "bool" routines, we return FALSE if exchange succesful. */ + +#define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + }) + +#define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + }) + +#define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + }) + +#define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + }) + +#define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + __oldval; \ + }) + +#define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + __oldval; \ + }) + +#define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + __oldval; \ + }) + +#define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \ + ({ \ + typeof (*mem) __oldval = (oldval); \ + __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \ + __ATOMIC_RELAXED); \ + __oldval; \ + }) + +/* Atomic compare and exchange. */ + +#define atomic_compare_and_exchange_bool_acq(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, mem, new, old, \ + __ATOMIC_ACQUIRE) + +#define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, mem, new, old, \ + __ATOMIC_ACQUIRE) + +#define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, mem, new, old, \ + __ATOMIC_RELEASE) + +/* Atomic exchange (without compare). */ + +#define __arch_exchange_8_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +#define __arch_exchange_16_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +#define __arch_exchange_32_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +#define __arch_exchange_64_int(mem, newval, model) \ + __atomic_exchange_n (mem, newval, model) + +#define atomic_exchange_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE) + +#define atomic_exchange_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE) + +/* Atomically add value and return the previous (unincremented) value. */ + +#define __arch_exchange_and_add_8_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +#define __arch_exchange_and_add_16_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +#define __arch_exchange_and_add_32_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +#define __arch_exchange_and_add_64_int(mem, value, model) \ + __atomic_fetch_add (mem, value, model) + +#define atomic_exchange_and_add_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ + __ATOMIC_ACQUIRE) + +#define atomic_exchange_and_add_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ + __ATOMIC_RELEASE) + +/* Miscellaneous. */ + +#define asm_amo(which, mem, value) \ + ({ \ + __atomic_check_size (mem); \ + typeof (*mem) __tmp; \ + if (sizeof (__tmp) == 4) \ + asm volatile(which ".w" \ + "\t%0, %z2, %1" \ + : "=&r"(__tmp), "+ZB"(*(mem)) \ + : "rJ"(value)); \ + else if (sizeof (__tmp) == 8) \ + asm volatile(which ".d" \ + "\t%0, %z2, %1" \ + : "=&r"(__tmp), "+ZB"(*(mem)) \ + : "rJ"(value)); \ + else \ + abort (); \ + __tmp; \ + }) + +#define atomic_max(mem, value) asm_amo ("ammax_db", mem, value) +#define atomic_min(mem, value) asm_amo ("ammin_db", mem, value) + +#define atomic_bit_test_set(mem, bit) \ + ({ \ + typeof (*mem) __mask = (typeof (*mem)) 1 << (bit); \ + asm_amo ("amor_db", mem, __mask) & __mask; \ + }) + +#define catomic_exchange_and_add(mem, value) \ + atomic_exchange_and_add (mem, value) +#define catomic_max(mem, value) atomic_max (mem, value) + +#endif /* bits/atomic.h */