From 9e4a9f69dd74c47a7d84c1233164acfae7602a9f Mon Sep 17 00:00:00 2001
From: "David S. Miller" <davem@davemloft.net>
Date: Sun, 6 Nov 2016 19:01:31 -0800
Subject: [PATCH] sparc: On 32-bit, provide atomics via kernel assist.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
sysdeps/sparc/sparc32/atomic-machine.h | 313 ++-------------------
sysdeps/sparc/sparc32/pthread_barrier_wait.c | 1 -
sysdeps/sparc/sparc32/sem_post.c | 82 ------
sysdeps/sparc/sparc32/sem_waitcommon.c | 146 ----------
.../sparc/sparc32/sparcv9/pthread_barrier_wait.c | 1 -
sysdeps/sparc/sparc32/sparcv9/sem_post.c | 1 -
sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c | 1 -
.../unix/sysv/linux/sparc/sparc32/atomic-machine.h | 35 +++
.../linux/sparc/sparc32/sparcv9/atomic-machine.h | 1 +
9 files changed, 55 insertions(+), 526 deletions(-)
delete mode 100644 sysdeps/sparc/sparc32/pthread_barrier_wait.c
delete mode 100644 sysdeps/sparc/sparc32/sem_post.c
delete mode 100644 sysdeps/sparc/sparc32/sem_waitcommon.c
delete mode 100644 sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c
delete mode 100644 sysdeps/sparc/sparc32/sparcv9/sem_post.c
delete mode 100644 sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c
create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/atomic-machine.h
create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/atomic-machine.h
@@ -50,311 +50,36 @@ typedef uintmax_t uatomic_max_t;
#define __HAVE_64B_ATOMICS 0
#define USE_ATOMIC_COMPILER_BUILTINS 0
+#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
-/* We have no compare and swap, just test and set.
- The following implementation contends on 64 global locks
- per library and assumes no variable will be accessed using atomic.h
- macros from two different libraries. */
+#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
-__make_section_unallocated
- (".gnu.linkonce.b.__sparc32_atomic_locks, \"aw\", %nobits");
+# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+ __sparc_assisted_compare_and_exchange_val_32_acq ((mem), (newval), (oldval))
-volatile unsigned char __sparc32_atomic_locks[64]
- __attribute__ ((nocommon, section (".gnu.linkonce.b.__sparc32_atomic_locks"
- __sec_comment),
- visibility ("hidden")));
+#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
-#define __sparc32_atomic_do_lock(addr) \
- do \
- { \
- unsigned int __old_lock; \
- unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \
- & 63; \
- do \
- __asm __volatile ("ldstub %1, %0" \
- : "=r" (__old_lock), \
- "=m" (__sparc32_atomic_locks[__idx]) \
- : "m" (__sparc32_atomic_locks[__idx]) \
- : "memory"); \
- while (__old_lock); \
- } \
- while (0)
+#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
+ atomic_compare_and_exchange_val_acq (mem, newval, oldval)
-#define __sparc32_atomic_do_unlock(addr) \
- do \
- { \
- __sparc32_atomic_locks[(((long) addr >> 2) \
- ^ ((long) addr >> 12)) & 63] = 0; \
- __asm __volatile ("" ::: "memory"); \
- } \
- while (0)
-
-#define __sparc32_atomic_do_lock24(addr) \
- do \
- { \
- unsigned int __old_lock; \
- do \
- __asm __volatile ("ldstub %1, %0" \
- : "=r" (__old_lock), "=m" (*(addr)) \
- : "m" (*(addr)) \
- : "memory"); \
- while (__old_lock); \
- } \
- while (0)
-
-#define __sparc32_atomic_do_unlock24(addr) \
- do \
- { \
- __asm __volatile ("" ::: "memory"); \
- *(char *) (addr) = 0; \
- } \
- while (0)
-
-
-#ifndef SHARED
-# define __v9_compare_and_exchange_val_32_acq(mem, newval, oldval) \
-({union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) }; \
- union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) }; \
- register uint32_t __acev_tmp __asm ("%g6"); \
- register __typeof (mem) __acev_mem __asm ("%g1") = (mem); \
- register uint32_t __acev_oldval __asm ("%g5"); \
- __acev_tmp = newval_arg.v; \
- __acev_oldval = oldval_arg.v; \
- /* .word 0xcde05005 is cas [%g1], %g5, %g6. Can't use cas here though, \
- because as will then mark the object file as V8+ arch. */ \
- __asm __volatile (".word 0xcde05005" \
- : "+r" (__acev_tmp), "=m" (*__acev_mem) \
- : "r" (__acev_oldval), "m" (*__acev_mem), \
- "r" (__acev_mem) : "memory"); \
- (__typeof (oldval)) __acev_tmp; })
-#endif
-
-/* The only basic operation needed is compare and exchange. */
-#define __v7_compare_and_exchange_val_acq(mem, newval, oldval) \
- ({ __typeof (mem) __acev_memp = (mem); \
- __typeof (*mem) __acev_ret; \
- __typeof (*mem) __acev_newval = (newval); \
- \
- __sparc32_atomic_do_lock (__acev_memp); \
- __acev_ret = *__acev_memp; \
- if (__acev_ret == (oldval)) \
- *__acev_memp = __acev_newval; \
- __sparc32_atomic_do_unlock (__acev_memp); \
- __acev_ret; })
-
-#define __v7_compare_and_exchange_bool_acq(mem, newval, oldval) \
- ({ __typeof (mem) __aceb_memp = (mem); \
- int __aceb_ret; \
- __typeof (*mem) __aceb_newval = (newval); \
- \
- __sparc32_atomic_do_lock (__aceb_memp); \
- __aceb_ret = 0; \
- if (*__aceb_memp == (oldval)) \
- *__aceb_memp = __aceb_newval; \
- else \
- __aceb_ret = 1; \
- __sparc32_atomic_do_unlock (__aceb_memp); \
- __aceb_ret; })
-
-#define __v7_exchange_acq(mem, newval) \
- ({ __typeof (mem) __acev_memp = (mem); \
- __typeof (*mem) __acev_ret; \
- __typeof (*mem) __acev_newval = (newval); \
- \
- __sparc32_atomic_do_lock (__acev_memp); \
- __acev_ret = *__acev_memp; \
- *__acev_memp = __acev_newval; \
- __sparc32_atomic_do_unlock (__acev_memp); \
- __acev_ret; })
-
-#define __v7_exchange_and_add(mem, value) \
- ({ __typeof (mem) __acev_memp = (mem); \
- __typeof (*mem) __acev_ret; \
- \
- __sparc32_atomic_do_lock (__acev_memp); \
- __acev_ret = *__acev_memp; \
- *__acev_memp = __acev_ret + (value); \
- __sparc32_atomic_do_unlock (__acev_memp); \
- __acev_ret; })
-
-/* Special versions, which guarantee that top 8 bits of all values
- are cleared and use those bits as the ldstub lock. */
-#define __v7_compare_and_exchange_val_24_acq(mem, newval, oldval) \
- ({ __typeof (mem) __acev_memp = (mem); \
- __typeof (*mem) __acev_ret; \
- __typeof (*mem) __acev_newval = (newval); \
- \
- __sparc32_atomic_do_lock24 (__acev_memp); \
- __acev_ret = *__acev_memp & 0xffffff; \
- if (__acev_ret == (oldval)) \
- *__acev_memp = __acev_newval; \
- else \
- __sparc32_atomic_do_unlock24 (__acev_memp); \
- __asm __volatile ("" ::: "memory"); \
- __acev_ret; })
-
-#define __v7_exchange_24_rel(mem, newval) \
- ({ __typeof (mem) __acev_memp = (mem); \
- __typeof (*mem) __acev_ret; \
- __typeof (*mem) __acev_newval = (newval); \
- \
- __sparc32_atomic_do_lock24 (__acev_memp); \
- __acev_ret = *__acev_memp & 0xffffff; \
- *__acev_memp = __acev_newval; \
- __asm __volatile ("" ::: "memory"); \
- __acev_ret; })
-
-#ifdef SHARED
-
-/* When dynamically linked, we assume pre-v9 libraries are only ever
- used on pre-v9 CPU. */
-# define __atomic_is_v9 0
-
-# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
- __v7_compare_and_exchange_val_acq (mem, newval, oldval)
-
-# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
- __v7_compare_and_exchange_bool_acq (mem, newval, oldval)
-
-# define atomic_exchange_acq(mem, newval) \
- __v7_exchange_acq (mem, newval)
-
-# define atomic_exchange_and_add(mem, value) \
- __v7_exchange_and_add (mem, value)
-
-# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
- ({ \
- if (sizeof (*mem) != 4) \
- abort (); \
- __v7_compare_and_exchange_val_24_acq (mem, newval, oldval); })
-
-# define atomic_exchange_24_rel(mem, newval) \
- ({ \
- if (sizeof (*mem) != 4) \
- abort (); \
- __v7_exchange_24_rel (mem, newval); })
+#define atomic_exchange_24_rel(mem, newval) \
+ atomic_exchange_rel (mem, newval)
# define atomic_full_barrier() __asm ("" ::: "memory")
# define atomic_read_barrier() atomic_full_barrier ()
# define atomic_write_barrier() atomic_full_barrier ()
-#else
-
-/* In libc.a/libpthread.a etc. we don't know if we'll be run on
- pre-v9 or v9 CPU. To be interoperable with dynamically linked
- apps on v9 CPUs e.g. with process shared primitives, use cas insn
- on v9 CPUs and ldstub on pre-v9. */
-
-extern uint64_t _dl_hwcap __attribute__((weak));
-# define __atomic_is_v9 \
- (__builtin_expect (&_dl_hwcap != 0, 1) \
- && __builtin_expect (_dl_hwcap & HWCAP_SPARC_V9, HWCAP_SPARC_V9))
-
-# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
- ({ \
- __typeof (*mem) __acev_wret; \
- if (sizeof (*mem) != 4) \
- abort (); \
- if (__atomic_is_v9) \
- __acev_wret \
- = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
- else \
- __acev_wret \
- = __v7_compare_and_exchange_val_acq (mem, newval, oldval); \
- __acev_wret; })
-
-# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
- ({ \
- int __acev_wret; \
- if (sizeof (*mem) != 4) \
- abort (); \
- if (__atomic_is_v9) \
- { \
- __typeof (oldval) __acev_woldval = (oldval); \
- __acev_wret \
- = __v9_compare_and_exchange_val_32_acq (mem, newval, \
- __acev_woldval) \
- != __acev_woldval; \
- } \
- else \
- __acev_wret \
- = __v7_compare_and_exchange_bool_acq (mem, newval, oldval); \
- __acev_wret; })
-
-# define atomic_exchange_rel(mem, newval) \
- ({ \
- __typeof (*mem) __acev_wret; \
- if (sizeof (*mem) != 4) \
- abort (); \
- if (__atomic_is_v9) \
- { \
- __typeof (mem) __acev_wmemp = (mem); \
- __typeof (*(mem)) __acev_wval = (newval); \
- do \
- __acev_wret = *__acev_wmemp; \
- while (__builtin_expect \
- (__v9_compare_and_exchange_val_32_acq (__acev_wmemp,\
- __acev_wval, \
- __acev_wret) \
- != __acev_wret, 0)); \
- } \
- else \
- __acev_wret = __v7_exchange_acq (mem, newval); \
- __acev_wret; })
-
-# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
- ({ \
- __typeof (*mem) __acev_wret; \
- if (sizeof (*mem) != 4) \
- abort (); \
- if (__atomic_is_v9) \
- __acev_wret \
- = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
- else \
- __acev_wret \
- = __v7_compare_and_exchange_val_24_acq (mem, newval, oldval);\
- __acev_wret; })
-
-# define atomic_exchange_24_rel(mem, newval) \
- ({ \
- __typeof (*mem) __acev_w24ret; \
- if (sizeof (*mem) != 4) \
- abort (); \
- if (__atomic_is_v9) \
- __acev_w24ret = atomic_exchange_rel (mem, newval); \
- else \
- __acev_w24ret = __v7_exchange_24_rel (mem, newval); \
- __acev_w24ret; })
-
-#define atomic_full_barrier() \
- do { \
- if (__atomic_is_v9) \
- /* membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore */ \
- __asm __volatile (".word 0x8143e00f" : : : "memory"); \
- else \
- __asm __volatile ("" : : : "memory"); \
- } while (0)
-
-#define atomic_read_barrier() \
- do { \
- if (__atomic_is_v9) \
- /* membar #LoadLoad | #LoadStore */ \
- __asm __volatile (".word 0x8143e005" : : : "memory"); \
- else \
- __asm __volatile ("" : : : "memory"); \
- } while (0)
-
-#define atomic_write_barrier() \
- do { \
- if (__atomic_is_v9) \
- /* membar #LoadStore | #StoreStore */ \
- __asm __volatile (".word 0x8143e00c" : : : "memory"); \
- else \
- __asm __volatile ("" : : : "memory"); \
- } while (0)
+void __sparc_link_error (void);
+/* An OS-specific atomic-machine.h file will define this macro if
+ the OS can provide something. If not, we'll fail to build
+ with a compiler that doesn't supply the operation. */
+#ifndef __sparc_assisted_compare_and_exchange_val_32_acq
+# define __sparc_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+ ({ __sparc_link_error (); oldval; })
#endif
-#include <sysdep.h>
-
#endif /* atomic-machine.h */
deleted file mode 100644
@@ -1 +0,0 @@
-#error No support for pthread barriers on pre-v9 sparc.
deleted file mode 100644
@@ -1,82 +0,0 @@
-/* sem_post -- post to a POSIX semaphore. Generic futex-using version.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
-
- 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
- <http://www.gnu.org/licenses/>. */
-
-#include <atomic.h>
-#include <errno.h>
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <internaltypes.h>
-#include <semaphore.h>
-#include <futex-internal.h>
-
-#include <shlib-compat.h>
-
-
-/* See sem_wait for an explanation of the algorithm. */
-int
-__new_sem_post (sem_t *sem)
-{
- struct new_sem *isem = (struct new_sem *) sem;
- int private = isem->private;
- unsigned int v;
-
- __sparc32_atomic_do_lock24 (&isem->pad);
-
- v = isem->value;
- if ((v >> SEM_VALUE_SHIFT) == SEM_VALUE_MAX)
- {
- __sparc32_atomic_do_unlock24 (&isem->pad);
-
- __set_errno (EOVERFLOW);
- return -1;
- }
- isem->value = v + (1 << SEM_VALUE_SHIFT);
-
- __sparc32_atomic_do_unlock24 (&isem->pad);
-
- if ((v & SEM_NWAITERS_MASK) != 0)
- futex_wake (&isem->value, 1, private);
-
- return 0;
-}
-versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
-
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-int
-attribute_compat_text_section
-__old_sem_post (sem_t *sem)
-{
- int *futex = (int *) sem;
-
- /* We must need to synchronize with consumers of this token, so the atomic
- increment must have release MO semantics. */
- atomic_write_barrier ();
- (void) atomic_increment_val (futex);
- /* We always have to assume it is a shared semaphore. */
- int err = lll_futex_wake (futex, 1, LLL_SHARED);
- if (__builtin_expect (err, 0) < 0)
- {
- __set_errno (-err);
- return -1;
- }
- return 0;
-}
-compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
-#endif
deleted file mode 100644
@@ -1,146 +0,0 @@
-/* sem_waitcommon -- wait on a semaphore, shared code.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
-
- 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
- <http://www.gnu.org/licenses/>. */
-
-#include <errno.h>
-#include <sysdep.h>
-#include <futex-internal.h>
-#include <internaltypes.h>
-#include <semaphore.h>
-#include <sys/time.h>
-
-#include <pthreadP.h>
-#include <shlib-compat.h>
-#include <atomic.h>
-
-
-static void
-__sem_wait_32_finish (struct new_sem *sem);
-
-static void
-__sem_wait_cleanup (void *arg)
-{
- struct new_sem *sem = (struct new_sem *) arg;
-
- __sem_wait_32_finish (sem);
-}
-
-/* Wait until at least one token is available, possibly with a timeout.
- This is in a separate function in order to make sure gcc
- puts the call site into an exception region, and thus the
- cleanups get properly run. TODO still necessary? Other futex_wait
- users don't seem to need it. */
-static int
-__attribute__ ((noinline))
-do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
-{
- int err;
-
- err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
- abstime, sem->private);
-
- return err;
-}
-
-/* Fast path: Try to grab a token without blocking. */
-static int
-__new_sem_wait_fast (struct new_sem *sem, int definitive_result)
-{
- unsigned int v;
- int ret = 0;
-
- __sparc32_atomic_do_lock24(&sem->pad);
-
- v = sem->value;
- if ((v >> SEM_VALUE_SHIFT) == 0)
- ret = -1;
- else
- sem->value = v - (1 << SEM_VALUE_SHIFT);
-
- __sparc32_atomic_do_unlock24(&sem->pad);
-
- return ret;
-}
-
-/* Slow path that blocks. */
-static int
-__attribute__ ((noinline))
-__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
-{
- unsigned int v;
- int err = 0;
-
- __sparc32_atomic_do_lock24(&sem->pad);
-
- sem->nwaiters++;
-
- pthread_cleanup_push (__sem_wait_cleanup, sem);
-
- /* Wait for a token to be available. Retry until we can grab one. */
- v = sem->value;
- do
- {
- if (!(v & SEM_NWAITERS_MASK))
- sem->value = v | SEM_NWAITERS_MASK;
-
- /* If there is no token, wait. */
- if ((v >> SEM_VALUE_SHIFT) == 0)
- {
- __sparc32_atomic_do_unlock24(&sem->pad);
-
- err = do_futex_wait(sem, abstime);
- if (err == ETIMEDOUT || err == EINTR)
- {
- __set_errno (err);
- err = -1;
- goto error;
- }
- err = 0;
-
- __sparc32_atomic_do_lock24(&sem->pad);
-
- /* We blocked, so there might be a token now. */
- v = sem->value;
- }
- }
- /* If there is no token, we must not try to grab one. */
- while ((v >> SEM_VALUE_SHIFT) == 0);
-
- sem->value = v - (1 << SEM_VALUE_SHIFT);
-
- __sparc32_atomic_do_unlock24(&sem->pad);
-
-error:
- pthread_cleanup_pop (0);
-
- __sem_wait_32_finish (sem);
-
- return err;
-}
-
-/* Stop being a registered waiter (non-64b-atomics code only). */
-static void
-__sem_wait_32_finish (struct new_sem *sem)
-{
- __sparc32_atomic_do_lock24(&sem->pad);
-
- if (--sem->nwaiters == 0)
- sem->value &= ~SEM_NWAITERS_MASK;
-
- __sparc32_atomic_do_unlock24(&sem->pad);
-}
deleted file mode 100644
@@ -1 +0,0 @@
-#include <nptl/pthread_barrier_wait.c>
deleted file mode 100644
@@ -1 +0,0 @@
-#include <nptl/sem_post.c>
deleted file mode 100644
@@ -1 +0,0 @@
-#include <nptl/sem_waitcommon.c>
new file mode 100644
@@ -0,0 +1,35 @@
+/* Atomic operations. SPARC/Linux version.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+
+#define __sparc_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval)\
+({union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) }; \
+ union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) }; \
+ register uint32_t __acev_tmp __asm ("%o2"); \
+ register __typeof (mem) __acev_mem __asm ("%o0") = (mem); \
+ register uint32_t __acev_oldval __asm ("%o1"); \
+ __acev_tmp = newval_arg.v; \
+ __acev_oldval = oldval_arg.v; \
+ __asm __volatile ("ta 0x23" \
+ : "+r" (__acev_tmp), "=m" (*__acev_mem) \
+ : "r" (__acev_oldval), "m" (*__acev_mem), \
+ "r" (__acev_mem) : "memory"); \
+ (__typeof (oldval)) __acev_tmp; })
+
+#include <sysdeps/sparc/sparc32/atomic-machine.h>
new file mode 100644
@@ -0,0 +1 @@
+#include <sysdeps/sparc/sparc32/sparcv9/atomic-machine.h>
--
2.1.2.532.g19b5d50