summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h28
-rw-r--r--nptl/sysdeps/unix/sysv/linux/lowlevellock.c2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h60
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S54
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S96
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S76
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S113
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S8
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h16
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c (renamed from nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c)60
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c69
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c112
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c117
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c9
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c51
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c100
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c16
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c127
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c2
27 files changed, 958 insertions, 183 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
index 4f6796449a..4487607bb3 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
@@ -226,23 +226,23 @@ __lll_robust_timedlock (int *futex, const struct timespec *abstime,
__lll_robust_timedlock (&(futex), abstime, id, private)
-static inline void __attribute__ ((always_inline))
-__lll_unlock (int *futex, int private)
-{
- int val = atomic_exchange_rel (futex, 0);
- if (__builtin_expect (val > 1, 0))
- lll_futex_wake (futex, 1, private);
-}
+#define __lll_unlock(futex, private) \
+ (void) \
+ ({ int *__futex = (futex); \
+ ({ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__builtin_expect (__oldval > 1, 0)) \
+ lll_futex_wake (__futex, 1, private); \
+ })
#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
-static inline void __attribute__ ((always_inline))
-__lll_robust_unlock (int *futex, int private)
-{
- int val = atomic_exchange_rel (futex, 0);
- if (__builtin_expect (val & FUTEX_WAITERS, 0))
- lll_futex_wake (futex, 1, private);
-}
+#define __lll_robust_unlock(futex, private) \
+ (void) \
+ ({ int *__futex = (futex); \
+ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \
+ lll_futex_wake (__futex, 1, private); \
+ })
#define lll_robust_unlock(futex, private) \
__lll_robust_unlock(&(futex), private)
diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
index 1187800148..f0e42957c2 100644
--- a/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
+++ b/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
@@ -37,7 +37,7 @@ __lll_lock_wait_private (int *futex)
}
-/* These functions doesn't get included in libc.so */
+/* These functions don't get included in libc.so */
#ifdef IS_IN_libpthread
void
__lll_lock_wait (int *futex, int private)
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
index 7fee435f12..c9347e98b2 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
@@ -291,31 +291,29 @@ __lll_robust_timedlock (int *futex, const struct timespec *abstime,
__lll_robust_timedlock (&(futex), abstime, id, private)
-static inline void
-__attribute__ ((always_inline))
-__lll_unlock (int *futex, int private)
-{
- int oldval;
- int newval = 0;
-
- lll_compare_and_swap (futex, oldval, newval, "slr %2,%2");
- if (__builtin_expect (oldval > 1, 0))
- lll_futex_wake (futex, 1, private);
-}
+#define __lll_unlock(futex, private) \
+ (void) \
+ ({ int __oldval; \
+ int __newval = 0; \
+ int *__futexp = (futex); \
+ \
+ lll_compare_and_swap (__futexp, __oldval, __newval, "slr %2,%2"); \
+ if (__builtin_expect (__oldval > 1, 0)) \
+ lll_futex_wake (__futexp, 1, private); \
+ })
#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
-static inline void
-__attribute__ ((always_inline))
-__lll_robust_unlock (int *futex, int private)
-{
- int oldval;
- int newval = 0;
-
- lll_compare_and_swap (futex, oldval, newval, "slr %2,%2");
- if (__builtin_expect (oldval & FUTEX_WAITERS, 0))
- lll_futex_wake (futex, 1, private);
-}
+#define __lll_robust_unlock(futex, private) \
+ (void) \
+ ({ int __oldval; \
+ int __newval = 0; \
+ int *__futexp = (futex); \
+ \
+ lll_compare_and_swap (__futexp, __oldval, __newval, "slr %2,%2"); \
+ if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \
+ lll_futex_wake (__futexp, 1, private); \
+ })
#define lll_robust_unlock(futex, private) \
__lll_robust_unlock(&(futex), private)
@@ -331,15 +329,15 @@ __lll_robust_unlock (int *futex, int private)
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
-static inline void
-__attribute__ ((always_inline))
-__lll_wait_tid (int *ptid)
-{
- int tid;
-
- while ((tid = *ptid) != 0)
- lll_futex_wait (ptid, tid, LLL_SHARED);
-}
+#define __lll_wait_tid(ptid) \
+ do \
+ { \
+ int __tid; \
+ \
+ while ((__tid = *ptid) != 0) \
+ lll_futex_wait (ptid, __tid, LLL_SHARED); \
+ } \
+ while (0)
#define lll_wait_tid(tid) __lll_wait_tid(&(tid))
extern int __lll_timedwait_tid (int *, const struct timespec *)
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
index b173f2d8bf..7dff15ac52 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
@@ -93,13 +93,24 @@ __pthread_cond_broadcast:
bt/s 9f
add #cond_futex, r4
- /* XXX: The kernel so far doesn't support requeue to PI futex. */
+ /* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same
+ type of futex (private resp. shared). */
mov.l @(MUTEX_KIND,r9), r0
- tst #PI_BIT, r0
+ tst #(PI_BIT|PS_BIT), r0
bf 9f
/* Wake up all threads. */
- mov #FUTEX_CMP_REQUEUE, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_CMP_REQUEUE, r0
+ or r0, r5
+#endif
mov #1, r6
mov #-1, r7
shlr r7 /* r7 = 0x7fffffff */
@@ -156,7 +167,12 @@ __pthread_cond_broadcast:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait5, r1
bsrf r1
@@ -171,7 +187,12 @@ __pthread_cond_broadcast:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lwake5, r1
bsrf r1
extu.b r5, r5
@@ -185,7 +206,12 @@ __pthread_cond_broadcast:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov #-1, r0
+ cmp/eq r0, r9
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lwake6, r1
bsrf r1
extu.b r5, r5
@@ -194,7 +220,22 @@ __pthread_cond_broadcast:
nop
9:
- mov #FUTEX_WAKE, r5
+ mov #-1, r0
+ cmp/eq r0, r9
+ bt/s 99f
+ mov #FUTEX_WAKE, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAKE, r0
+ or r0, r5
+#endif
+99:
mov #-1, r6
shlr r6 /* r6 = 0x7fffffff */
mov #0, r7
@@ -205,6 +246,11 @@ __pthread_cond_broadcast:
bra 10b
nop
+#ifndef __ASSUME_PRIVATE_FUTEX
+.Lpfoff:
+ .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
+#endif
+
.align 2
.Lwait5:
.long __lll_lock_wait-.Lwait5b
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
index 3ef2d6ee14..9cb73a233c 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
@@ -74,14 +74,63 @@ __pthread_cond_signal:
/* Wake up one thread. */
mov r8, r4
add #cond_futex, r4
- mov #FUTEX_WAKE, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAKE_OP, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAKE_OP, r0
+ or r0, r5
+#endif
+99:
mov #1, r6
mov #0, r7
+ mov r8, r0
+ add #cond_lock, r0
+ mov.l .Lfutexop, r1
mov #SYS_futex, r3
extu.b r3, r3
trapa #0x14
SYSCALL_INST_PAD
+ /* For any kind of error, we try again with WAKE.
+ The general test also covers running on old kernels. */
+ mov r0, r1
+ mov #-12, r2
+ shad r2, r1
+ not r1, r1
+ tst r1, r1
+ bt 7f
+
+6:
+ mov #0, r0
+ lds.l @r15+, pr
+ rts
+ mov.l @r15+, r8
+
+#ifndef __ASSUME_PRIVATE_FUTEX
+.Lpfoff:
+ .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
+#endif
+ .align 2
+.Lfutexop:
+ .long FUTEX_OP_CLEAR_WAKE_IF_GT_ONE
+
+7:
+ /* r5 should be either FUTEX_WAKE_OP or
+ FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */
+ mov #(FUTEX_WAKE ^ FUTEX_WAKE_OP), r0
+ xor r0, r5
+ trapa #0x14
+ SYSCALL_INST_PAD
+
4:
/* Unlock. */
#if cond_lock != 0
@@ -90,12 +139,26 @@ __pthread_cond_signal:
DEC (@r8, r2)
#endif
tst r2, r2
- bf 5f
-6:
- mov #0, r0
- lds.l @r15+, pr
- rts
- mov.l @r15+, r8
+ bt 6b
+
+5:
+ /* Unlock in loop requires wakeup. */
+ mov r8, r4
+#if cond_lock != 0
+ add #cond_lock, r4
+#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
+ mov #LLL_SHARED, r5
+99:
+ mov.l .Lwake4, r1
+ bsrf r1
+ extu.b r5, r5
+.Lwake4b:
+ bra 6b
+ nop
1:
/* Initial locking failed. */
@@ -103,7 +166,12 @@ __pthread_cond_signal:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait4, r1
bsrf r1
@@ -112,20 +180,6 @@ __pthread_cond_signal:
bra 2b
nop
-5:
- /* Unlock in loop requires wakeup. */
- mov r8, r4
-#if cond_lock != 0
- add #cond_lock, r4
-#endif
- mov #LLL_SHARED, r5
- mov.l .Lwake4, r1
- bsrf r1
- extu.b r5, r5
-.Lwake4b:
- bra 6b
- nop
-
.align 2
.Lwait4:
.long __lll_lock_wait-.Lwait4b
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
index fde4f57b2a..4cf0ac45c5 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
@@ -21,8 +21,9 @@
#include <lowlevellock.h>
#include <lowlevelcond.h>
#include <pthread-errnos.h>
-#include "lowlevel-atomic.h"
#include <kernel-features.h>
+#include <tcb-offsets.h>
+#include "lowlevel-atomic.h"
.text
@@ -230,7 +231,22 @@ __pthread_cond_timedwait:
mov r15, r7
add #16, r7
- mov #FUTEX_WAIT, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAIT, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAIT, r0
+ or r0, r5
+#endif
+99:
mov.l @(8,r15), r6
mov r8, r4
add #cond_futex, r4
@@ -339,7 +355,22 @@ __pthread_cond_timedwait:
mov r8, r4
add #cond_nwaiters, r4
- mov #FUTEX_WAKE, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAKE, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAKE, r0
+ or r0, r5
+#endif
+99:
mov #1, r6
mov #0, r7
mov #SYS_futex, r3
@@ -379,6 +410,10 @@ __pthread_cond_timedwait:
rts
mov.l @r15+, r8
+#ifndef __ASSUME_PRIVATE_FUTEX
+.Lpfoff:
+ .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
+#endif
.L1k:
.word 1000
.align 2
@@ -399,7 +434,12 @@ __pthread_cond_timedwait:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait2, r1
bsrf r1
@@ -414,7 +454,12 @@ __pthread_cond_timedwait:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lmwait2, r1
bsrf r1
extu.b r5, r5
@@ -428,7 +473,12 @@ __pthread_cond_timedwait:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait3, r1
bsrf r1
@@ -443,7 +493,12 @@ __pthread_cond_timedwait:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lmwait3, r1
bsrf r1
extu.b r5, r5
@@ -466,7 +521,12 @@ __pthread_cond_timedwait:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lmwait4, r1
bsrf r1
extu.b r5, r5
@@ -510,7 +570,12 @@ __condvar_tw_cleanup:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait5, r1
bsrf r1
@@ -605,7 +670,12 @@ __condvar_tw_cleanup:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lmwait5, r1
bsrf r1
extu.b r5, r5
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
index 9ca4c35edc..eddf4c95a7 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
@@ -20,6 +20,8 @@
#include <shlib-compat.h>
#include <lowlevellock.h>
#include <lowlevelcond.h>
+#include <tcb-offsets.h>
+#include <kernel-features.h>
#include "lowlevel-atomic.h"
.text
@@ -135,7 +137,22 @@ __pthread_cond_wait:
mov.l r0, @r15
mov #0, r7
- mov #FUTEX_WAIT, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAIT, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff0, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAIT, r0
+ or r0, r5
+#endif
+99:
mov.l @(8,r15), r6
mov r8, r4
add #cond_futex, r4
@@ -213,7 +230,22 @@ __pthread_cond_wait:
mov r8, r4
add #cond_nwaiters, r4
- mov #FUTEX_WAKE, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAKE, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff0, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAKE, r0
+ or r0, r5
+#endif
+99:
mov #1, r6
mov #0, r7
mov #SYS_futex, r3
@@ -247,6 +279,10 @@ __pthread_cond_wait:
rts
mov.l @r15+, r8
+#ifndef __ASSUME_PRIVATE_FUTEX
+.Lpfoff0:
+ .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
+#endif
.align 2
.Lmunlock0:
.long __pthread_mutex_unlock_usercnt-.Lmunlock0b
@@ -263,7 +299,12 @@ __pthread_cond_wait:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait0, r1
bsrf r1
@@ -277,7 +318,12 @@ __pthread_cond_wait:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lwake0, r1
bsrf r1
extu.b r5, r5
@@ -291,7 +337,12 @@ __pthread_cond_wait:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait1, r1
bsrf r1
@@ -306,7 +357,12 @@ __pthread_cond_wait:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lwake1, r1
bsrf r1
extu.b r5, r5
@@ -329,7 +385,12 @@ __pthread_cond_wait:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lwake2, r1
bsrf r1
extu.b r5, r5
@@ -374,7 +435,12 @@ __condvar_w_cleanup:
#if cond_lock != 0
add #cond_lock, r5
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r6
mov #LLL_SHARED, r6
+99:
extu.b r6, r6
mov.l .Lwait3, r1
bsrf r1
@@ -447,7 +513,22 @@ __condvar_w_cleanup:
mov r8, r4
add #cond_nwaiters, r4
- mov #FUTEX_WAKE, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAKE, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff1, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAKE, r0
+ or r0, r5
+#endif
+99:
mov #1, r6
mov #0, r7
mov #SYS_futex, r3
@@ -469,7 +550,12 @@ __condvar_w_cleanup:
#if cond_lock != 0
add #cond_lock, r4
#endif
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bf/s 99f
+ mov #LLL_PRIVATE, r5
mov #LLL_SHARED, r5
+99:
mov.l .Lwake3, r1
bsrf r1
extu.b r5, r5
@@ -481,7 +567,22 @@ __condvar_w_cleanup:
bf/s 5f
mov r8, r4
add #cond_futex, r4
- mov #FUTEX_WAKE, r5
+ mov.l @(dep_mutex,r8), r0
+ cmp/eq #-1, r0
+ bt/s 99f
+ mov #FUTEX_WAKE, r5
+#ifdef __ASSUME_PRIVATE_FUTEX
+ mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
+ extu.b r5, r5
+#else
+ stc gbr, r1
+ mov.w .Lpfoff1, r2
+ add r2, r1
+ mov.l @r1, r5
+ mov #FUTEX_WAKE, r0
+ or r0, r5
+#endif
+99:
mov #-1, r6
shlr r6 /* r6 = 0x7fffffff */
mov #0, r7
@@ -505,6 +606,10 @@ __condvar_w_cleanup:
mov r11, r4
sleep
+#ifndef __ASSUME_PRIVATE_FUTEX
+.Lpfoff1:
+ .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
+#endif
.align 2
.Lwait3:
.long __lll_lock_wait-.Lwait3b
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S
index 439907502a..0830cab246 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S
@@ -94,7 +94,7 @@ __pthread_once:
bf 3f /* Different for generation -> run initializer. */
/* Somebody else got here first. Wait. */
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5
extu.b r5, r5
#else
@@ -168,7 +168,7 @@ __pthread_once:
INC (@r9, r2)
/* Wake up all other threads. */
mov r9, r4
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
extu.b r5, r5
#else
@@ -213,7 +213,7 @@ __pthread_once:
mov #0, r7
mov.l r7, @r9
mov r9, r4
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
#else
stc gbr, r1
@@ -239,7 +239,7 @@ __pthread_once:
sleep
cfi_endproc
-#if !__ASSUME_PRIVATE_FUTEX
+#ifndef __ASSUME_PRIVATE_FUTEX
.Lpfoff:
.word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S
index 9e4ba959b5..b71be1d974 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S
@@ -74,7 +74,7 @@ __pthread_rwlock_rdlock:
tst r2, r2
bf 10f
11:
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #PSHARED, r0
mov.b @(r0,r8), r5
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0
@@ -142,7 +142,7 @@ __pthread_rwlock_rdlock:
rts
mov r3, r0
-#if !__ASSUME_PRIVATE_FUTEX
+#ifndef __ASSUME_PRIVATE_FUTEX
.Lpfoff:
.word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S
index b06fd960cf..e40771de0f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S
@@ -115,7 +115,7 @@ pthread_rwlock_timedrdlock:
/* Futex call. */
mov r15, r7
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #PSHARED, r0
mov.b @(r0,r8), r5
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0
@@ -193,7 +193,7 @@ pthread_rwlock_timedrdlock:
rts
mov r3, r0
-#if !__ASSUME_PRIVATE_FUTEX
+#ifndef __ASSUME_PRIVATE_FUTEX
.Lpfoff:
.word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S
index 4591309ecc..dfe137973c 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S
@@ -111,7 +111,7 @@ pthread_rwlock_timedwrlock:
/* Futex call. */
mov r15, r7
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #PSHARED, r0
mov.b @(r0,r8), r5
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0
@@ -191,7 +191,7 @@ pthread_rwlock_timedwrlock:
rts
mov r3, r0
-#if !__ASSUME_PRIVATE_FUTEX
+#ifndef __ASSUME_PRIVATE_FUTEX
.Lpfoff:
.word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S
index 1504c1aed1..045b8b3b33 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S
@@ -85,7 +85,7 @@ __pthread_rwlock_unlock:
bf 7f
8:
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #PSHARED, r0
mov.b @(r0,r8), r5
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r0
@@ -177,7 +177,7 @@ __pthread_rwlock_unlock:
bra 8b
mov.l @r15+, r4
-#if !__ASSUME_PRIVATE_FUTEX
+#ifndef __ASSUME_PRIVATE_FUTEX
.Lpfoff:
.word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S
index 25dffe4bf9..6de65cc640 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S
@@ -72,7 +72,7 @@ __pthread_rwlock_wrlock:
11:
mov r8, r4
add #WRITERS_WAKEUP, r4
-#if __ASSUME_PRIVATE_FUTEX
+#ifdef __ASSUME_PRIVATE_FUTEX
mov #PSHARED, r0
mov.b @(r0,r8), r5
mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0
@@ -174,7 +174,7 @@ __pthread_rwlock_wrlock:
bra 7b
mov #0, r3
-#if !__ASSUME_PRIVATE_FUTEX
+#ifndef __ASSUME_PRIVATE_FUTEX
.Lpfoff:
.word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h
index 4d0ea51723..4f400a3fe3 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h
@@ -15,4 +15,20 @@ union sparc_pthread_barrier
} s;
};
+struct sparc_new_sem
+{
+ unsigned int value;
+ unsigned char lock;
+ unsigned char private;
+ unsigned char pad[2];
+ unsigned long int nwaiters;
+};
+
+struct sparc_old_sem
+{
+ unsigned int value;
+ unsigned char lock;
+ unsigned char private;
+};
+
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c
index dffd8c7efa..840032a08c 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -18,20 +18,50 @@
02111-1307 USA. */
#include <errno.h>
+#include <string.h>
#include <semaphore.h>
#include <lowlevellock.h>
#include <shlib-compat.h>
#include "semaphoreP.h"
+#include <kernel-features.h>
-struct sparc_sem
+
+int
+__new_sem_init (sem, pshared, value)
+ sem_t *sem;
+ int pshared;
+ unsigned int value;
{
- struct sem s;
- unsigned char lock;
-};
+ /* Parameter sanity check. */
+ if (__builtin_expect (value > SEM_VALUE_MAX, 0))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+ /* Map to the internal type. */
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
+ /* Use the values the user provided. */
+ memset (isem, '\0', sizeof (*isem));
+ isem->value = value;
+#ifdef __ASSUME_PRIVATE_FUTEX
+ isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG;
+#else
+ isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF,
+ header.private_futex);
+#endif
+
+ return 0;
+}
+versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
+
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
int
-__new_sem_init (sem, pshared, value)
+attribute_compat_text_section
+__old_sem_init (sem, pshared, value)
sem_t *sem;
int pshared;
unsigned int value;
@@ -44,20 +74,20 @@ __new_sem_init (sem, pshared, value)
}
/* Map to the internal type. */
- struct sparc_sem *isem = (struct sparc_sem *) sem;
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
/* Use the value the user provided. */
- isem->s.count = value;
-
- isem->lock = 0;
+ memset (isem, '\0', sizeof (*isem));
+ isem->value = value;
- /* We can completely ignore the PSHARED parameter since inter-process
- use needs no special preparation. */
+#ifdef __ASSUME_PRIVATE_FUTEX
+ isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG;
+#else
+ isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF,
+ header.private_futex);
+#endif
return 0;
}
-versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_init, __old_sem_init)
compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c
new file mode 100644
index 0000000000..95964d0744
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c
@@ -0,0 +1,69 @@
+/* sem_post -- post to a POSIX semaphore. SPARC version.
+ Copyright (C) 2003, 2004, 2007 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <shlib-compat.h>
+
+int
+__new_sem_post (sem_t *sem)
+{
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
+
+ int nr = atomic_increment_val (&isem->value);
+ atomic_full_barrier ();
+ if (isem->nwaiters > 0)
+ {
+ int err = lll_futex_wake (&isem->value, 1,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+ if (__builtin_expect (err, 0) < 0)
+ {
+ __set_errno (-err);
+ return -1;
+ }
+ }
+ 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)
+{
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
+
+ int nr = atomic_increment_val (&isem->value);
+ int err = lll_futex_wake (&isem->value, 1,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+ 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
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c
new file mode 100644
index 0000000000..01952f3f9a
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c
@@ -0,0 +1,112 @@
+/* sem_timedwait -- wait on a semaphore. Generic futex-using version.
+ Copyright (C) 2003, 2007 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <pthreadP.h>
+#include <shlib-compat.h>
+
+
+extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+
+
+int
+sem_timedwait (sem_t *sem, const struct timespec *abstime)
+{
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
+ int err;
+
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ return 0;
+
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ atomic_increment (&isem->nwaiters);
+
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
+
+ while (1)
+ {
+ struct timeval tv;
+ struct timespec rt;
+ int sec, nsec;
+
+ /* Get the current time. */
+ __gettimeofday (&tv, NULL);
+
+ /* Compute relative timeout. */
+ sec = abstime->tv_sec - tv.tv_sec;
+ nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+ if (nsec < 0)
+ {
+ nsec += 1000000000;
+ --sec;
+ }
+
+ /* Already timed out? */
+ err = -ETIMEDOUT;
+ if (sec < 0)
+ {
+ __set_errno (ETIMEDOUT);
+ err = -1;
+ break;
+ }
+
+ /* Do wait. */
+ rt.tv_sec = sec;
+ rt.tv_nsec = nsec;
+
+ /* Enable asynchronous cancellation. Required by the standard. */
+ int oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_timed_wait (&isem->value, 0, &rt,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (oldtype);
+
+ if (err != 0 && err != -EWOULDBLOCK)
+ {
+ __set_errno (-err);
+ err = -1;
+ break;
+ }
+
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ {
+ err = 0;
+ break;
+ }
+ }
+
+ pthread_cleanup_pop (0);
+
+ atomic_decrement (&isem->nwaiters);
+
+ return err;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c
new file mode 100644
index 0000000000..a846f20601
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c
@@ -0,0 +1,117 @@
+/* sem_wait -- wait on a semaphore. Generic futex-using version.
+ Copyright (C) 2003, 2007 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <pthreadP.h>
+#include <shlib-compat.h>
+
+
+void
+attribute_hidden
+__sem_wait_cleanup (void *arg)
+{
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) arg;
+
+ atomic_decrement (&isem->nwaiters);
+}
+
+
+int
+__new_sem_wait (sem_t *sem)
+{
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
+ int err;
+
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ return 0;
+
+ atomic_increment (&isem->nwaiters);
+
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
+
+ while (1)
+ {
+ /* Enable asynchronous cancellation. Required by the standard. */
+ int oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_wait (&isem->value, 0,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (oldtype);
+
+ if (err != 0 && err != -EWOULDBLOCK)
+ {
+ __set_errno (-err);
+ err = -1;
+ break;
+ }
+
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ {
+ err = 0;
+ break;
+ }
+ }
+
+ pthread_cleanup_pop (0);
+
+ atomic_decrement (&isem->nwaiters);
+
+ return err;
+}
+versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
+
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+attribute_compat_text_section
+__old_sem_wait (sem_t *sem)
+{
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
+ int err;
+
+ do
+ {
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ return 0;
+
+ /* Enable asynchronous cancellation. Required by the standard. */
+ int oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_wait (&isem->value, 0,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (oldtype);
+ }
+ while (err == 0 || err == -EWOULDBLOCK);
+
+ __set_errno (-err);
+ return -1;
+}
+
+compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
index 1ee9b4737b..682307eef1 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
@@ -36,9 +36,9 @@ __lll_lock_wait_private (int *futex)
while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
}
-#ifdef IS_IN_libpthread
-/* These functions don't get included in libc.so */
+/* These functions don't get included in libc.so */
+#ifdef IS_IN_libpthread
void
__lll_lock_wait (int *futex, int private)
{
@@ -121,8 +121,9 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
if (rt.tv_sec < 0)
return ETIMEDOUT;
- /* Wait until thread terminates. */
- if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT)
+ /* Wait until thread terminates. The kernel so far does not use
+ the private futex operations for this. */
+ if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
return ETIMEDOUT;
}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
index 527aedfdc7..dbd34f2210 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
@@ -29,19 +29,51 @@
int
__new_sem_post (sem_t *sem)
{
- int *futex = (int *) sem, nr;
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
+ int nr;
if (__atomic_is_v9)
- nr = atomic_increment_val (futex);
+ nr = atomic_increment_val (&isem->value);
else
{
- __sparc32_atomic_do_lock24 (futex + 1);
- nr = ++*futex;
- __sparc32_atomic_do_unlock24 (futex + 1);
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ nr = ++(isem->value);
+ __sparc32_atomic_do_unlock24 (&isem->lock);
}
- int err = lll_futex_wake (futex, nr,
- // XYZ check mutex flag
- LLL_SHARED);
+ atomic_full_barrier ();
+ if (isem->nwaiters > 0)
+ {
+ int err = lll_futex_wake (&isem->value, 1,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+ if (__builtin_expect (err, 0) < 0)
+ {
+ __set_errno (-err);
+ return -1;
+ }
+ }
+ 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)
+{
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
+ int nr;
+
+ if (__atomic_is_v9)
+ nr = atomic_increment_val (&isem->value);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ nr = ++(isem->value);
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+ int err = lll_futex_wake (&isem->value, 1,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
if (__builtin_expect (err, 0) < 0)
{
__set_errno (-err);
@@ -49,8 +81,5 @@ __new_sem_post (sem_t *sem)
}
return 0;
}
-versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_post, __old_sem_post)
compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
index efcc9e9aa8..55f3e2e075 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
@@ -1,5 +1,5 @@
/* sem_timedwait -- wait on a semaphore. SPARC version.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
@@ -28,37 +28,48 @@
#include <shlib-compat.h>
+extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+
+
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
- /* First check for cancellation. */
- CANCELLATION_P (THREAD_SELF);
-
- int *futex = (int *) sem;
- int val;
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
int err;
+ int val;
- if (*futex > 0)
+ if (__atomic_is_v9)
+ val = atomic_decrement_if_positive (&isem->value);
+ else
{
- if (__atomic_is_v9)
- val = atomic_decrement_if_positive (futex);
- else
- {
- __sparc32_atomic_do_lock24 (futex + 1);
- val = *futex;
- if (val > 0)
- *futex = val - 1;
- __sparc32_atomic_do_unlock24 (futex + 1);
- }
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
if (val > 0)
- return 0;
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
}
- err = -EINVAL;
+ if (val > 0)
+ return 0;
+
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
- goto error_return;
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (__atomic_is_v9)
+ atomic_increment (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters++;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
- do
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
+
+ while (1)
{
struct timeval tv;
struct timespec rt;
@@ -79,7 +90,11 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Already timed out? */
err = -ETIMEDOUT;
if (sec < 0)
- goto error_return;
+ {
+ __set_errno (ETIMEDOUT);
+ err = -1;
+ break;
+ }
/* Do wait. */
rt.tv_sec = sec;
@@ -88,30 +103,47 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
- err = lll_futex_timed_wait (futex, 0, &rt);
+ err = lll_futex_timed_wait (&isem->value, 0, &rt,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
- goto error_return;
+ {
+ __set_errno (-err);
+ err = -1;
+ break;
+ }
if (__atomic_is_v9)
- val = atomic_decrement_if_positive (futex);
+ val = atomic_decrement_if_positive (&isem->value);
else
{
- __sparc32_atomic_do_lock24 (futex + 1);
- val = *futex;
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
if (val > 0)
- *futex = val - 1;
- __sparc32_atomic_do_unlock24 (futex + 1);
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+
+ if (val > 0)
+ {
+ err = 0;
+ break;
}
}
- while (val <= 0);
- return 0;
+ pthread_cleanup_pop (0);
+
+ if (__atomic_is_v9)
+ atomic_decrement (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters--;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
- error_return:
- __set_errno (-err);
- return -1;
+ return err;
}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
index 429494e257..4db89727a7 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
@@ -1,5 +1,5 @@
/* sem_trywait -- wait on a semaphore. SPARC version.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
@@ -30,20 +30,20 @@
int
__new_sem_trywait (sem_t *sem)
{
- int *futex = (int *) sem;
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
int val;
- if (*futex > 0)
+ if (isem->value > 0)
{
if (__atomic_is_v9)
- val = atomic_decrement_if_positive (futex);
+ val = atomic_decrement_if_positive (&isem->value);
else
{
- __sparc32_atomic_do_lock24 (futex + 1);
- val = *futex;
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
if (val > 0)
- *futex = val - 1;
- __sparc32_atomic_do_unlock24 (futex + 1);
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
}
if (val > 0)
return 0;
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
index d9fcdcd4ee..3c71c969b8 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
@@ -1,5 +1,5 @@
-/* sem_wait -- wait on a semaphore. SPARC version.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+/* sem_wait -- wait on a semaphore. Generic futex-using version.
+ Copyright (C) 2003, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
@@ -28,35 +28,135 @@
#include <shlib-compat.h>
+void
+attribute_hidden
+__sem_wait_cleanup (void *arg)
+{
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) arg;
+
+ if (__atomic_is_v9)
+ atomic_decrement (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters--;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+}
+
+
int
__new_sem_wait (sem_t *sem)
{
- /* First check for cancellation. */
- CANCELLATION_P (THREAD_SELF);
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
+ int err;
+ int val;
+
+ if (__atomic_is_v9)
+ val = atomic_decrement_if_positive (&isem->value);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
+ if (val > 0)
+ isem->value = val - 1;
+ else
+ isem->nwaiters++;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+
+ if (val > 0)
+ return 0;
+
+ if (__atomic_is_v9)
+ atomic_increment (&isem->nwaiters);
+ else
+ /* Already done above while still holding isem->lock. */;
+
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
+
+ while (1)
+ {
+ /* Enable asynchronous cancellation. Required by the standard. */
+ int oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_wait (&isem->value, 0,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (oldtype);
+
+ if (err != 0 && err != -EWOULDBLOCK)
+ {
+ __set_errno (-err);
+ err = -1;
+ break;
+ }
+
+ if (__atomic_is_v9)
+ val = atomic_decrement_if_positive (&isem->value);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
+ if (val > 0)
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+
+ if (val > 0)
+ {
+ err = 0;
+ break;
+ }
+ }
+
+ pthread_cleanup_pop (0);
- int *futex = (int *) sem;
+ if (__atomic_is_v9)
+ atomic_decrement (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters--;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+
+ return err;
+}
+versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
+
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+attribute_compat_text_section
+__old_sem_wait (sem_t *sem)
+{
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
int err;
+ int val;
do
{
- int val;
if (__atomic_is_v9)
- val = atomic_decrement_if_positive (futex);
+ val = atomic_decrement_if_positive (&isem->value);
else
{
- __sparc32_atomic_do_lock24 (futex + 1);
- val = *futex;
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
if (val > 0)
- *futex = val - 1;
- __sparc32_atomic_do_unlock24 (futex + 1);
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
}
+
if (val > 0)
return 0;
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
- err = lll_futex_wait (futex, 0);
+ err = lll_futex_wait (futex, 0,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
@@ -67,8 +167,5 @@ __new_sem_wait (sem_t *sem)
return -1;
}
-versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_wait, __old_sem_wait)
compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c
deleted file mode 100644
index b2ebc4cbb5..0000000000
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "../../../../../../../sem_init.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c
index 4a6eac88f5..73d7c56675 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c
@@ -1 +1 @@
-#include "../../../sem_post.c"
+#include "../../sem_post.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c
index b2526db02c..03945b7279 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c
@@ -1 +1 @@
-#include "../../../sem_timedwait.c"
+#include "../../sem_timedwait.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c
index 31157f636f..a5dbc5a4b8 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c
@@ -1 +1 @@
-#include "../../../sem_wait.c"
+#include "../../sem_wait.c"