diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h')
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h | 190 |
1 files changed, 110 insertions, 80 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h index 4626aec52..4db6fb0b4 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -24,33 +24,28 @@ #include <sys/param.h> #include <bits/pthreadtypes.h> #include <atomic.h> +#include <sysdep.h> #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 #define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define lll_futex_wait(futexp, val) \ - ({ \ - INTERNAL_SYSCALL_DECL (__err); \ - long int __ret; \ - \ - __ret = INTERNAL_SYSCALL (futex, __err, 4, \ - (futexp), FUTEX_WAIT, (val), 0); \ - __ret; \ - }) + lll_futex_timed_wait (futexp, val, NULL) #define lll_futex_timed_wait(futexp, val, timespec) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ - \ - __ret = INTERNAL_SYSCALL (futex, __err, 4, \ - (futexp), FUTEX_WAIT, (val), (timespec)); \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + FUTEX_WAIT, (val), (timespec)); \ __ret; \ }) @@ -58,9 +53,8 @@ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ - \ - __ret = INTERNAL_SYSCALL (futex, __err, 4, \ - (futexp), FUTEX_WAKE, (nr), 0); \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + FUTEX_WAKE, (nr), 0); \ __ret; \ }) @@ -69,70 +63,115 @@ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ - \ - __ret = INTERNAL_SYSCALL (futex, __err, 6, \ - (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ - (nr_move), (mutex), (val)); \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + FUTEX_CMP_REQUEUE, (nr_wake), (nr_move), (mutex), (val)); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) +#define lll_robust_dead(futexv) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ #ifdef __sparc32_atomic_do_lock -#error SPARC < v9 does not support compare and swap which is essential for futex based locking +/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs. */ +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) 1 +#else +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + FUTEX_WAKE_OP, \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) #endif static inline int __attribute__ ((always_inline)) -__lll_mutex_trylock (int *futex) +__lll_trylock (int *futex) { - return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; + return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0; } -#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) +#define lll_mutex_trylock(futex) __lll_trylock (&(futex)) static inline int __attribute__ ((always_inline)) -__lll_mutex_cond_trylock (int *futex) +__lll_cond_trylock (int *futex) { - return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; + return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0; } -#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) +#define lll_mutex_cond_trylock(futex) __lll_cond_trylock (&(futex)) +static inline int +__attribute__ ((always_inline)) +__lll_robust_trylock (int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(futex, id) \ + __lll_robust_trylock (&(futex), id) -extern void __lll_lock_wait (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex) attribute_hidden; static inline void __attribute__ ((always_inline)) -__lll_mutex_lock (int *futex) +__lll_lock (int *futex) { - int val = atomic_compare_and_exchange_val_acq (futex, 1, 0); + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); if (__builtin_expect (val != 0, 0)) - __lll_lock_wait (futex); + { + __lll_lock_wait (futex); + } } -#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) +#define lll_mutex_lock(futex) __lll_lock (&(futex)) +static inline int +__attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_lock_wait (futex); + return result; +} +#define lll_robust_lock(futex, id) \ + __lll_robust_lock (&(futex), id) static inline void __attribute__ ((always_inline)) -__lll_mutex_cond_lock (int *futex) +__lll_cond_lock (int *futex) { - int val = atomic_compare_and_exchange_val_acq (futex, 2, 0); + int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0); if (__builtin_expect (val != 0, 0)) __lll_lock_wait (futex); } -#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex)) +#define lll_mutex_cond_lock(futex) __lll_cond_lock (&(futex)) +#define lll_robust_cond_lock(futex, id) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS) -extern int __lll_timedlock_wait (int *futex, const struct timespec *) - attribute_hidden; +extern int __lll_timedlock_wait (int *futex, const struct timespec *) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) attribute_hidden; static inline int __attribute__ ((always_inline)) -__lll_mutex_timedlock (int *futex, const struct timespec *abstime) +__lll_timedlock (int *futex, const struct timespec *abstime) { - int val = atomic_compare_and_exchange_val_acq (futex, 1, 0); + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); int result = 0; if (__builtin_expect (val != 0, 0)) @@ -140,43 +179,56 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime) return result; } #define lll_mutex_timedlock(futex, abstime) \ - __lll_mutex_timedlock (&(futex), abstime) + __lll_timedlock (&(futex), abstime) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime); + return result; +} +#define lll_robust_timedlock(futex, abstime, id) \ + __lll_robust_timedlock (&(futex), abstime, id) #define lll_mutex_unlock(lock) \ ((void) ({ \ int *__futex = &(lock); \ - int __val = atomic_exchange_rel (__futex, 0); \ + int __val = atomic_exchange_24_rel (__futex, 0); \ if (__builtin_expect (__val > 1, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1); \ })) -#define lll_mutex_unlock_force(lock) \ +#define lll_robust_unlock(lock) \ ((void) ({ \ int *__futex = &(lock); \ - (void) atomic_exchange_rel (__futex, 0); \ - lll_futex_wake (__futex, 1); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1); \ })) #define lll_mutex_islocked(futex) \ (futex != 0) - /* We have a separate internal lock implementation which is not tied - to binary compatibility. We can use the lll_mutex_*. */ + to binary compatibility. */ /* Type for lock object. */ typedef int lll_lock_t; -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; - /* Initializers for lock. */ #define LLL_LOCK_INITIALIZER (0) #define LLL_LOCK_INITIALIZER_LOCKED (1) -#define lll_trylock(futex) lll_mutex_trylock (futex) -#define lll_lock(futex) lll_mutex_lock (futex) -#define lll_unlock(futex) lll_mutex_unlock (futex) -#define lll_islocked(futex) lll_mutex_islocked (futex) +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +#define lll_trylock(lock) lll_mutex_trylock (lock) +#define lll_lock(lock) lll_mutex_lock (lock) +#define lll_unlock(lock) lll_mutex_unlock (lock) +#define lll_islocked(lock) lll_mutex_islocked (lock) /* The kernel notifies a process with uses CLONE_CLEARTID via futex @@ -184,12 +236,12 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; thread ID while the clone is running and is reset to zero afterwards. */ #define lll_wait_tid(tid) \ - do \ - { \ - __typeof (tid) __tid; \ - while ((__tid = (tid)) != 0) \ - lll_futex_wait (&(tid), __tid); \ - } \ + do \ + { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid); \ + } \ while (0) extern int __lll_timedwait_tid (int *, const struct timespec *) @@ -203,26 +255,4 @@ extern int __lll_timedwait_tid (int *, const struct timespec *) __res; \ }) - -/* Conditional variable handling. */ - -extern void __lll_cond_wait (pthread_cond_t *cond) - attribute_hidden; -extern int __lll_cond_timedwait (pthread_cond_t *cond, - const struct timespec *abstime) - attribute_hidden; -extern void __lll_cond_wake (pthread_cond_t *cond) - attribute_hidden; -extern void __lll_cond_broadcast (pthread_cond_t *cond) - attribute_hidden; - -#define lll_cond_wait(cond) \ - __lll_cond_wait (cond) -#define lll_cond_timedwait(cond, abstime) \ - __lll_cond_timedwait (cond, abstime) -#define lll_cond_wake(cond) \ - __lll_cond_wake (cond) -#define lll_cond_broadcast(cond) \ - __lll_cond_broadcast (cond) - #endif /* lowlevellock.h */ |