aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/sparc/sparc32/bits/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/sparc/sparc32/bits/atomic.h')
-rw-r--r--sysdeps/sparc/sparc32/bits/atomic.h30
1 files changed, 18 insertions, 12 deletions
diff --git a/sysdeps/sparc/sparc32/bits/atomic.h b/sysdeps/sparc/sparc32/bits/atomic.h
index c4e0abfe06..00d799392b 100644
--- a/sysdeps/sparc/sparc32/bits/atomic.h
+++ b/sysdeps/sparc/sparc32/bits/atomic.h
@@ -22,28 +22,34 @@
#define _BITS_ATOMIC_H 1
/* We have no compare and swap, just test and set.
- The following implementation contends on one single global lock
+ 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. */
-volatile unsigned char __sparc32_atomic_lock
- __attribute__ ((nocommon, section (".gnu.linkonce.b.__sparc32_atomic_lock"),
+volatile unsigned char __sparc32_atomic_locks[64]
+ __attribute__ ((nocommon, section (".gnu.linkonce.b.__sparc32_atomic_locks"),
visibility ("hidden")));
-#define __sparc32_atomic_do_lock() \
+#define __sparc32_atomic_do_lock(addr) \
do \
{ \
unsigned int __old_lock; \
+ unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \
+ & 63; \
do \
__asm ("ldstub %1, %0" \
- : "=r" (__old_lock), "=m" (__sparc32_atomic_lock) \
- : "m" (__sparc32_atomic_lock)); \
+ : "=r" (__old_lock), \
+ "=m" (__sparc32_atomic_locks[__idx]) \
+ : "m" (__sparc32_atomic_locks[__idx])); \
while (__old_lock); \
} \
while (0)
-#define __sparc32_atomic_do_unlock() \
- do __sparc32_atomic_lock = 0; while (0)
+#define __sparc32_atomic_do_unlock(addr) \
+ do \
+ __sparc32_atomic_locks[(((long) addr >> 2) \
+ ^ ((long) addr >> 12)) & 63] = 0; \
+ while (0)
/* The only basic operation needed is compare and exchange. */
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
@@ -51,11 +57,11 @@ volatile unsigned char __sparc32_atomic_lock
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
- __sparc32_atomic_do_lock (); \
+ __sparc32_atomic_do_lock (__acev_memp); \
__acev_ret = *__acev_memp; \
if (__acev_ret == (oldval)) \
*__acev_memp = __acev_newval; \
- __sparc32_atomic_do_unlock (); \
+ __sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
@@ -63,13 +69,13 @@ volatile unsigned char __sparc32_atomic_lock
int __aceb_ret; \
__typeof (*mem) __aceb_newval = (newval); \
\
- __sparc32_atomic_do_lock (); \
+ __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 (); \
+ __sparc32_atomic_do_unlock (__aceb_memp); \
__aceb_ret; })
#endif /* bits/atomic.h */