diff options
Diffstat (limited to 'nptl/sysdeps')
98 files changed, 2546 insertions, 993 deletions
diff --git a/nptl/sysdeps/alpha/tls.h b/nptl/sysdeps/alpha/tls.h index 64ddcd5c01..e77b1ffca9 100644 --- a/nptl/sysdeps/alpha/tls.h +++ b/nptl/sysdeps/alpha/tls.h @@ -131,7 +131,7 @@ typedef struct = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ THREAD_GSCOPE_FLAG_UNUSED); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/i386/tcb-offsets.sym b/nptl/sysdeps/i386/tcb-offsets.sym index 7c8d9a5ca5..69f9deb368 100644 --- a/nptl/sysdeps/i386/tcb-offsets.sym +++ b/nptl/sysdeps/i386/tcb-offsets.sym @@ -12,3 +12,6 @@ CLEANUP offsetof (struct pthread, cleanup) CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev) MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h index b97729ce4b..b5127420cf 100644 --- a/nptl/sysdeps/i386/tls.h +++ b/nptl/sysdeps/i386/tls.h @@ -27,6 +27,8 @@ # include <stdint.h> # include <stdlib.h> # include <list.h> +# include <sysdep.h> +# include <kernel-features.h> /* Type for the dtv. */ @@ -52,6 +54,9 @@ typedef struct uintptr_t stack_guard; uintptr_t pointer_guard; int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif } tcbhead_t; # define TLS_MULTIPLE_THREADS_IN_TCB 1 @@ -444,7 +449,7 @@ union user_desc_init : "i" (offsetof (struct pthread, header.gscope_flag)), \ "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/ia64/tls.h b/nptl/sysdeps/ia64/tls.h index a144c28b09..936ff01a72 100644 --- a/nptl/sysdeps/ia64/tls.h +++ b/nptl/sysdeps/ia64/tls.h @@ -173,7 +173,7 @@ register struct pthread *__thread_self __asm__("r13"); = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ THREAD_GSCOPE_FLAG_UNUSED); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/powerpc/tcb-offsets.sym b/nptl/sysdeps/powerpc/tcb-offsets.sym index 4a8671e802..eda43dce8e 100644 --- a/nptl/sysdeps/powerpc/tcb-offsets.sym +++ b/nptl/sysdeps/powerpc/tcb-offsets.sym @@ -15,3 +15,4 @@ MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) PID thread_offsetof (pid) TID thread_offsetof (tid) POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +PRIVATE_FUTEX_OFFSET thread_offsetof (header.private_futex) diff --git a/nptl/sysdeps/powerpc/tls.h b/nptl/sysdeps/powerpc/tls.h index bd9c99e06e..0f4d5290dd 100644 --- a/nptl/sysdeps/powerpc/tls.h +++ b/nptl/sysdeps/powerpc/tls.h @@ -190,7 +190,7 @@ register void *__thread_register __asm__ ("r13"); = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ THREAD_GSCOPE_FLAG_UNUSED); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/pthread/aio_misc.h b/nptl/sysdeps/pthread/aio_misc.h index c5a11f4550..f36825e06f 100644 --- a/nptl/sysdeps/pthread/aio_misc.h +++ b/nptl/sysdeps/pthread/aio_misc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2007 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 @@ -30,7 +30,7 @@ #define AIO_MISC_NOTIFY(waitlist) \ do { \ if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \ - lll_futex_wake (waitlist->counterp, 1); \ + lll_futex_wake (waitlist->counterp, 1, LLL_PRIVATE); \ } while (0) #define AIO_MISC_WAIT(result, futex, timeout, cancel) \ @@ -49,7 +49,8 @@ int status; \ do \ { \ - status = lll_futex_timed_wait (futexaddr, oldval, timeout); \ + status = lll_futex_timed_wait (futexaddr, oldval, timeout, \ + LLL_PRIVATE); \ if (status != -EWOULDBLOCK) \ break; \ \ diff --git a/nptl/sysdeps/pthread/bits/stdio-lock.h b/nptl/sysdeps/pthread/bits/stdio-lock.h index cd64bc37e2..5f2382104b 100644 --- a/nptl/sysdeps/pthread/bits/stdio-lock.h +++ b/nptl/sysdeps/pthread/bits/stdio-lock.h @@ -1,5 +1,5 @@ /* Thread package specific definitions of stream lock type. NPTL version. - Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2007 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 @@ -94,9 +94,15 @@ typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; __attribute__((cleanup (_IO_acquire_lock_fct))) \ = (_fp); \ _IO_flockfile (_IO_acquire_lock_file); - +# define _IO_acquire_lock_clear_flags2(_fp) \ + do { \ + _IO_FILE *_IO_acquire_lock_file \ + __attribute__((cleanup (_IO_acquire_lock_clear_flags2_fct))) \ + = (_fp); \ + _IO_flockfile (_IO_acquire_lock_file); # else # define _IO_acquire_lock(_fp) _IO_acquire_lock_needs_exceptions_enabled +# define _IO_acquire_lock_clear_flags2(_fp) _IO_acquire_lock (_fp) # endif # define _IO_release_lock(_fp) ; } while (0) diff --git a/nptl/sysdeps/pthread/gai_misc.h b/nptl/sysdeps/pthread/gai_misc.h index 9f6a73dad1..0a2686cb27 100644 --- a/nptl/sysdeps/pthread/gai_misc.h +++ b/nptl/sysdeps/pthread/gai_misc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2007 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 @@ -31,7 +31,7 @@ #define GAI_MISC_NOTIFY(waitlist) \ do { \ if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \ - lll_futex_wake (waitlist->counterp, 1); \ + lll_futex_wake (waitlist->counterp, 1, LLL_PRIVATE); \ } while (0) #define GAI_MISC_WAIT(result, futex, timeout, cancel) \ @@ -50,7 +50,8 @@ int status; \ do \ { \ - status = lll_futex_timed_wait (futexaddr, oldval, timeout); \ + status = lll_futex_timed_wait (futexaddr, oldval, timeout, \ + LLL_PRIVATE); \ if (status != -EWOULDBLOCK) \ break; \ \ diff --git a/nptl/sysdeps/pthread/pt-initfini.c b/nptl/sysdeps/pthread/pt-initfini.c index 1e35edd3eb..9c00dc0b7d 100644 --- a/nptl/sysdeps/pthread/pt-initfini.c +++ b/nptl/sysdeps/pthread/pt-initfini.c @@ -72,7 +72,7 @@ call_initialize_minimal (void) } SECTION (".init"); -extern void _init (void); +extern void __attribute__ ((section (".init"))) _init (void); void _init (void) { @@ -93,7 +93,7 @@ asm ("\n/*@_init_EPILOG_ENDS*/"); asm ("\n/*@_fini_PROLOG_BEGINS*/"); SECTION (".fini"); -extern void _fini (void); +extern void __attribute__ ((section (".fini"))) _fini (void); void _fini (void) { diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h index a13b937032..0c404fcbb3 100644 --- a/nptl/sysdeps/pthread/pthread-functions.h +++ b/nptl/sysdeps/pthread/pthread-functions.h @@ -97,7 +97,6 @@ struct pthread_functions void (*ptr__nptl_deallocate_tsd) (void); int (*ptr__nptl_setxid) (struct xid_command *); void (*ptr_freeres) (void); - void (*ptr_wait_lookup_done) (int); }; /* Variable in libc.so. */ diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h index 4dc0b2272b..d175f312ee 100644 --- a/nptl/sysdeps/pthread/pthread.h +++ b/nptl/sysdeps/pthread/pthread.h @@ -21,6 +21,7 @@ #define _PTHREAD_H 1 #include <features.h> +#include <endian.h> #include <sched.h> #include <time.h> @@ -120,21 +121,23 @@ enum }; /* Read-write lock initializers. */ -# if __WORDSIZE == 64 -# define PTHREAD_RWLOCK_INITIALIZER \ +# define PTHREAD_RWLOCK_INITIALIZER \ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } -# else -# define PTHREAD_RWLOCK_INITIALIZER \ - { { 0, 0, 0, 0, 0, 0, 0, 0 } } -# endif # ifdef __USE_GNU # if __WORDSIZE == 64 # define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } # else -# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ - { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 0 } } +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ + 0, 0, 0, 0 } } +# else +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ + 0 } } +# endif # endif # endif #endif /* Unix98 or XOpen2K */ diff --git a/nptl/sysdeps/s390/tls.h b/nptl/sysdeps/s390/tls.h index 251dfd4a46..3be459e32c 100644 --- a/nptl/sysdeps/s390/tls.h +++ b/nptl/sysdeps/s390/tls.h @@ -27,6 +27,7 @@ # include <stdint.h> # include <stdlib.h> # include <list.h> +# include <kernel-features.h> /* Type for the dtv. */ @@ -51,6 +52,9 @@ typedef struct uintptr_t sysinfo; uintptr_t stack_guard; int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif } tcbhead_t; # ifndef __s390x__ @@ -179,7 +183,7 @@ typedef struct = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ THREAD_GSCOPE_FLAG_UNUSED); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/sh/tcb-offsets.sym b/nptl/sysdeps/sh/tcb-offsets.sym index 4ad866335b..753b72b2dd 100644 --- a/nptl/sysdeps/sh/tcb-offsets.sym +++ b/nptl/sysdeps/sh/tcb-offsets.sym @@ -10,3 +10,6 @@ MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads) TLS_PRE_TCB_SIZE sizeof (struct pthread) MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (struct pthread, header.private_futex) +#endif diff --git a/nptl/sysdeps/sh/tls.h b/nptl/sysdeps/sh/tls.h index 6d6eff665f..a2d4d565ff 100644 --- a/nptl/sysdeps/sh/tls.h +++ b/nptl/sysdeps/sh/tls.h @@ -26,6 +26,10 @@ # include <stdbool.h> # include <stddef.h> # include <stdint.h> +# include <stdlib.h> +# include <list.h> +# include <sysdep.h> +# include <kernel-features.h> /* Type for the dtv. */ typedef union dtv @@ -160,7 +164,7 @@ typedef struct = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ THREAD_GSCOPE_FLAG_UNUSED); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/sparc/tls.h b/nptl/sysdeps/sparc/tls.h index 60e52fd4ea..601b53732b 100644 --- a/nptl/sysdeps/sparc/tls.h +++ b/nptl/sysdeps/sparc/tls.h @@ -46,9 +46,15 @@ typedef struct dtv_t *dtv; void *self; int multiple_threads; +#if __WORDSIZE == 64 + int gscope_flag; +#endif uintptr_t sysinfo; uintptr_t stack_guard; uintptr_t pointer_guard; +#if __WORDSIZE != 64 + int gscope_flag; +#endif } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -151,7 +157,7 @@ register struct pthread *__thread_self __asm__("%g7"); = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ THREAD_GSCOPE_FLAG_UNUSED); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile index cfcdb6d97f..ad5ae6ad12 100644 --- a/nptl/sysdeps/unix/sysv/linux/Makefile +++ b/nptl/sysdeps/unix/sysv/linux/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -25,7 +25,8 @@ libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \ lowlevelbarrier.sym unwindbuf.sym \ - lowlevelrobustlock.sym pthread-pi-defines.sym + lowlevelrobustlock.sym pthread-pi-defines.sym \ + structsem.sym endif ifeq ($(subdir),posix) diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h index 58b4806eb2..5f08673c43 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 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 @@ -36,34 +36,63 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + /* 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); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ - }) +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) -#define lll_futex_timed_wait(futexp, val, timespec) \ +#define lll_futex_timed_wait(futexp, val, timespec, private) \ ({ \ 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), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ }) -#define lll_futex_wake(futexp, nr) \ +#define lll_futex_wake(futexp, nr, private) \ ({ \ 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), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ }) @@ -72,7 +101,7 @@ { \ int *__futexp = &(futexv); \ atomic_or (__futexp, FUTEX_OWNER_DIED); \ - lll_futex_wake (__futexp, 1); \ + lll_futex_wake (__futexp, 1, LLL_SHARED); \ } \ while (0) @@ -198,7 +227,7 @@ __lll_mutex_unlock (int *futex) { int val = atomic_exchange_rel (futex, 0); if (__builtin_expect (val > 1, 0)) - lll_futex_wake (futex, 1); + lll_futex_wake (futex, 1, LLL_SHARED); } #define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) @@ -208,7 +237,7 @@ __lll_robust_mutex_unlock (int *futex, int mask) { int val = atomic_exchange_rel (futex, 0); if (__builtin_expect (val & mask, 0)) - lll_futex_wake (futex, 1); + lll_futex_wake (futex, 1, LLL_SHARED); } #define lll_robust_mutex_unlock(futex) \ __lll_robust_mutex_unlock(&(futex), FUTEX_WAITERS) @@ -218,7 +247,7 @@ static inline void __attribute__ ((always_inline)) __lll_mutex_unlock_force (int *futex) { (void) atomic_exchange_rel (futex, 0); - lll_futex_wake (futex, 1); + lll_futex_wake (futex, 1, LLL_SHARED); } #define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex)) @@ -237,8 +266,6 @@ typedef int lll_lock_t; #define LLL_LOCK_INITIALIZER (0) #define LLL_LOCK_INITIALIZER_LOCKED (1) -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; - /* The states of a lock are: 0 - untaken 1 - taken by one user @@ -254,10 +281,10 @@ 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, LLL_SHARED); \ } while (0) extern int __lll_timedwait_tid (int *, const struct timespec *) diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c index 79a3c47aed..0e7e9790dd 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c +++ b/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2007 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 @@ -28,7 +28,7 @@ clear_once_control (void *arg) pthread_once_t *once_control = (pthread_once_t *) arg; *once_control = 0; - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); } int @@ -72,7 +72,7 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) break; /* Same generation, some other thread was faster. Wait. */ - lll_futex_wait (once_control, oldval); + lll_futex_wait (once_control, oldval, LLL_PRIVATE); } /* This thread is the first here. Do the initialization. @@ -88,7 +88,7 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) atomic_increment (once_control); /* Wake up all other threads. */ - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); return 0; } diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c index 98bb237c06..f9913c343e 100644 --- a/nptl/sysdeps/unix/sysv/linux/fork.c +++ b/nptl/sysdeps/unix/sysv/linux/fork.c @@ -203,7 +203,7 @@ __libc_fork (void) if (atomic_decrement_and_test (&allp->handler->refcntr) && allp->handler->need_signal) - lll_futex_wake (allp->handler->refcntr, 1); + lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE); allp = allp->next; } diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h index f53d0e5a72..9e3e016fb8 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 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 @@ -128,7 +128,10 @@ typedef union unsigned int __nr_writers_queued; /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ - unsigned int __flags; + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; int __writer; } __data; char __size[__SIZEOF_PTHREAD_RWLOCK_T]; diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S index 88885b735d..830f628578 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,14 +17,19 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* In libc.so we do not unconditionally use the lock prefix. Only if - the application is using threads. */ -#ifndef UP -# define LOCK \ - cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \ - je 0f; \ - lock; \ -0: +#include <kernel-features.h> + +/* All locks in libc are private. Use the kernel feature if possible. */ +#define FUTEX_PRIVATE_FLAG 128 +#ifdef __ASSUME_PRIVATE_FUTEX +# define FUTEX_WAIT (0 | FUTEX_PRIVATE_FLAG) +# define FUTEX_WAKE (1 | FUTEX_PRIVATE_FLAG) +#else +# define LOAD_FUTEX_WAIT(reg) \ + movl %gs:PRIVATE_FUTEX, reg +# define LOAD_FUTEX_WAKE(reg) \ + movl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg #endif #include "lowlevellock.S" diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S index e2da5b04cf..cfcc7dafc4 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -32,8 +32,22 @@ #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 +#ifndef FUTEX_WAIT +# define FUTEX_WAIT 0 +# define FUTEX_WAKE 1 +#endif + +#ifndef LOAD_FUTEX_WAIT +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl reg, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + movl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAKE(reg) \ + movl $FUTEX_WAKE, reg +#endif .globl __lll_mutex_lock_wait @@ -55,7 +69,7 @@ __lll_mutex_lock_wait: movl $2, %edx movl %ecx, %ebx xorl %esi, %esi /* No timeout. */ - xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + LOAD_FUTEX_WAIT (%ecx) cmpl %edx, %eax /* NB: %edx == 2 */ jne 2f @@ -151,7 +165,7 @@ __lll_mutex_timedlock_wait: /* Futex call. */ movl %esp, %esi - xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + LOAD_FUTEX_WAIT (%ecx) movl $SYS_futex, %eax ENTER_KERNEL movl %eax, %ecx @@ -205,35 +219,6 @@ __lll_mutex_timedlock_wait: #endif -#ifdef NOT_IN_libc - .globl lll_unlock_wake_cb - .type lll_unlock_wake_cb,@function - .hidden lll_unlock_wake_cb - .align 16 -lll_unlock_wake_cb: - pushl %ebx - pushl %ecx - pushl %edx - - movl 20(%esp), %ebx - LOCK - subl $1, (%ebx) - je 1f - - movl $FUTEX_WAKE, %ecx - movl $1, %edx /* Wake one thread. */ - movl $SYS_futex, %eax - movl $0, (%ebx) - ENTER_KERNEL - -1: popl %edx - popl %ecx - popl %ebx - ret - .size lll_unlock_wake_cb,.-lll_unlock_wake_cb -#endif - - .globl __lll_mutex_unlock_wake .type __lll_mutex_unlock_wake,@function .hidden __lll_mutex_unlock_wake @@ -252,7 +237,7 @@ __lll_mutex_unlock_wake: movl %eax, %ebx movl $0, (%eax) - movl $FUTEX_WAKE, %ecx + LOAD_FUTEX_WAKE (%ecx) movl $1, %edx /* Wake one thread. */ movl $SYS_futex, %eax ENTER_KERNEL @@ -314,6 +299,8 @@ __lll_timedwait_tid: jz 4f movl %esp, %esi + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ movl %ebp, %ebx movl $SYS_futex, %eax diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S index fe7a8b9c66..29857195f0 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -69,7 +69,13 @@ pthread_barrier_wait: /* Wait for the remaining threads. The call will return immediately if the CURR_EVENT memory has meanwhile been changed. */ -7: xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ +7: +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif xorl %esi, %esi 8: movl $SYS_futex, %eax ENTER_KERNEL @@ -120,6 +126,7 @@ pthread_barrier_wait: so 0x7fffffff is the highest value. */ movl $0x7fffffff, %edx movl $FUTEX_WAKE, %ecx + orl PRIVATE(%ebx), %ecx movl $SYS_futex, %eax ENTER_KERNEL diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S index f481a8e43c..93f4d56b32 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -87,7 +87,7 @@ __pthread_cond_timedwait: addl $1, total_seq(%ebx) adcl $0, total_seq+4(%ebx) addl $1, cond_futex(%ebx) - addl $(1 << clock_bits), cond_nwaiters(%ebx) + addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) #define FRAME_SIZE 24 subl $FRAME_SIZE, %esp @@ -106,7 +106,7 @@ __pthread_cond_timedwait: #ifdef __NR_clock_gettime /* Get the clock number. */ movl cond_nwaiters(%ebx), %ebx - andl $((1 << clock_bits) - 1), %ebx + andl $((1 << nwaiters_shift) - 1), %ebx /* Only clocks 0 and 1 are allowed so far. Both are handled in the kernel. */ leal 4(%esp), %ecx @@ -228,7 +228,7 @@ __pthread_cond_timedwait: 14: addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) -24: subl $(1 << clock_bits), cond_nwaiters(%ebx) +24: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) /* Wake up a thread which wants to destroy the condvar object. */ movl total_seq(%ebx), %eax @@ -236,7 +236,7 @@ __pthread_cond_timedwait: cmpl $0xffffffff, %eax jne 25f movl cond_nwaiters(%ebx), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 25f addl $cond_nwaiters, %ebx @@ -424,7 +424,7 @@ __condvar_tw_cleanup: 7: addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) -3: subl $(1 << clock_bits), cond_nwaiters(%ebx) +3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) /* Wake up a thread which wants to destroy the condvar object. */ xorl %edi, %edi @@ -433,7 +433,7 @@ __condvar_tw_cleanup: cmpl $0xffffffff, %eax jne 4f movl cond_nwaiters(%ebx), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 4f addl $cond_nwaiters, %ebx diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S index f16c7d9198..c92cfbc718 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -80,7 +80,7 @@ __pthread_cond_wait: addl $1, total_seq(%ebx) adcl $0, total_seq+4(%ebx) addl $1, cond_futex(%ebx) - addl $(1 << clock_bits), cond_nwaiters(%ebx) + addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) #define FRAME_SIZE 16 subl $FRAME_SIZE, %esp @@ -157,7 +157,7 @@ __pthread_cond_wait: adcl $0, woken_seq+4(%ebx) /* Unlock */ -16: subl $(1 << clock_bits), cond_nwaiters(%ebx) +16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) /* Wake up a thread which wants to destroy the condvar object. */ movl total_seq(%ebx), %eax @@ -165,7 +165,7 @@ __pthread_cond_wait: cmpl $0xffffffff, %eax jne 17f movl cond_nwaiters(%ebx), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 17f addl $cond_nwaiters, %ebx @@ -315,7 +315,7 @@ __condvar_w_cleanup: 7: addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) -3: subl $(1 << clock_bits), cond_nwaiters(%ebx) +3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) /* Wake up a thread which wants to destroy the condvar object. */ xorl %edi, %edi @@ -324,7 +324,7 @@ __condvar_w_cleanup: cmpl $0xffffffff, %eax jne 4f movl cond_nwaiters(%ebx), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 4f addl $cond_nwaiters, %ebx diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S index db0639d21c..c61c697985 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -61,7 +61,7 @@ __pthread_rwlock_rdlock: jne 14f cmpl $0, WRITERS_QUEUED(%ebx) je 5f - cmpl $0, FLAGS(%ebx) + cmpb $0, FLAGS(%ebx) je 5f 3: addl $1, READERS_QUEUED(%ebx) @@ -77,8 +77,18 @@ __pthread_rwlock_rdlock: #endif jne 10f -11: addl $READERS_WAKEUP, %ebx - movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ +11: +#if __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebx), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebx), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $READERS_WAKEUP, %ebx movl $SYS_futex, %eax ENTER_KERNEL diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S index eb5665b432..c6a584fed0 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -65,7 +65,7 @@ pthread_rwlock_timedrdlock: jne 14f cmpl $0, WRITERS_QUEUED(%ebp) je 5f - cmpl $0, FLAGS(%ebp) + cmpb $0, FLAGS(%ebp) je 5f /* Check the value of the timeout parameter. */ @@ -108,8 +108,18 @@ pthread_rwlock_timedrdlock: /* Futex call. */ movl %ecx, (%esp) /* Store relative timeout. */ movl %edx, 4(%esp) + movl %esi, %edx - xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ +#if __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebp), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebp), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif movl %esp, %esi leal READERS_WAKEUP(%ebp), %ebx movl $SYS_futex, %eax diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S index d9db77ba05..5e9faf93fb 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -106,8 +106,18 @@ pthread_rwlock_timedwrlock: /* Futex call. */ movl %ecx, (%esp) /* Store relative timeout. */ movl %edx, 4(%esp) + movl %esi, %edx - xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ +#if __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebp), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebp), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif movl %esp, %esi leal WRITERS_WAKEUP(%ebp), %ebx movl $SYS_futex, %eax diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S index 64aac3255a..35c40c2c1c 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -61,9 +61,8 @@ __pthread_rwlock_unlock: 5: movl $0, WRITER(%edi) - movl $1, %ecx + movl $1, %edx leal WRITERS_WAKEUP(%edi), %ebx - movl %ecx, %edx cmpl $0, WRITERS_QUEUED(%edi) jne 0f @@ -83,7 +82,16 @@ __pthread_rwlock_unlock: #endif jne 7f -8: movl $SYS_futex, %eax +8: +#if __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%edi), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %ecx +#else + movzbl PSHARED(%edi), %ecx + orl $FUTEX_WAKE, %ecx + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax ENTER_KERNEL xorl %eax, %eax diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S index ea9cc170db..88044c040b 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -75,8 +75,18 @@ __pthread_rwlock_wrlock: #endif jne 10f -11: addl $WRITERS_WAKEUP, %ebx - movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ +11: +#if __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebx), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebx), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $WRITERS_WAKEUP, %ebx movl $SYS_futex, %eax ENTER_KERNEL diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S index 71e96d2228..280dc2fe27 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,6 +20,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #ifndef UP # define LOCK lock @@ -40,19 +41,27 @@ __new_sem_post: pushl %ebx movl 8(%esp), %ebx - movl $1, %edx + LOCK - xaddl %edx, (%ebx) +#if VALUE == 0 + addl $1, (%ebx) +#else + addl $1, VALUE(%ebx) +#endif + + cmpl $0, NWAITERS(%ebx) + je 2f - movl $SYS_futex, %eax movl $FUTEX_WAKE, %ecx - addl $1, %edx + orl PRIVATE(%ebx), %ecx + movl $1, %edx + movl $SYS_futex, %eax ENTER_KERNEL testl %eax, %eax js 1f - xorl %eax, %eax +2: xorl %eax, %eax popl %ebx ret diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S index bf70e17fca..57b5b58186 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -20,6 +20,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #ifndef UP # define LOCK lock @@ -29,7 +30,12 @@ #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 -#define FUTEX_WAKE 1 +#define FUTEX_WAIT 0 + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif .text @@ -37,14 +43,8 @@ .globl sem_timedwait .type sem_timedwait,@function .align 16 - cfi_startproc sem_timedwait: - /* First check for cancellation. */ - movl %gs:CANCELHANDLING, %eax - andl $0xfffffff9, %eax - cmpl $8, %eax - je 10f - +.LSTARTCODE: movl 4(%esp), %ecx movl (%ecx), %eax @@ -61,24 +61,24 @@ sem_timedwait: /* Check whether the timeout value is valid. */ 1: pushl %esi - cfi_adjust_cfa_offset(4) +.Lpush_esi: pushl %edi - cfi_adjust_cfa_offset(4) +.Lpush_edi: pushl %ebx - cfi_adjust_cfa_offset(4) +.Lpush_ebx: subl $12, %esp - cfi_adjust_cfa_offset(12) +.Lsub_esp: movl 32(%esp), %edi - cfi_offset(7, -12) /* %edi */ /* Check for invalid nanosecond field. */ cmpl $1000000000, 4(%edi) movl $EINVAL, %esi - cfi_offset(6, -8) /* %esi */ jae 6f - cfi_offset(3, -16) /* %ebx */ + LOCK + incl NWAITERS(%ecx) + 7: xorl %ecx, %ecx movl %esp, %ebx movl %ecx, %edx @@ -103,19 +103,26 @@ sem_timedwait: movl %ecx, (%esp) /* Store relative timeout. */ movl %edx, 4(%esp) +.LcleanupSTART: call __pthread_enable_asynccancel movl %eax, 8(%esp) - movl 28(%esp), %ebx - xorl %ecx, %ecx + movl 28(%esp), %ebx /* Load semaphore address. */ +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif movl %esp, %esi - movl $SYS_futex, %eax xorl %edx, %edx + movl $SYS_futex, %eax ENTER_KERNEL movl %eax, %esi movl 8(%esp), %eax call __pthread_disable_asynccancel +.LcleanupEND: testl %esi, %esi je 9f @@ -131,24 +138,22 @@ sem_timedwait: cmpxchgl %ecx, (%ebx) jne 8b - addl $12, %esp - cfi_adjust_cfa_offset(-12) xorl %eax, %eax + +10: LOCK + decl NWAITERS(%ebx) + + addl $12, %esp +.Ladd_esp: popl %ebx - cfi_adjust_cfa_offset(-4) - cfi_restore(3) +.Lpop_ebx: popl %edi - cfi_adjust_cfa_offset(-4) - cfi_restore(7) +.Lpop_edi: popl %esi - cfi_adjust_cfa_offset(-4) - cfi_restore(6) +.Lpop_esi: ret - cfi_adjust_cfa_offset(24) - cfi_offset(6, -8) /* %esi */ - cfi_offset(7, -12) /* %edi */ - cfi_offset(3, -16) /* %ebx */ +.Lafter_ret: 3: negl %esi 6: #ifdef PIC @@ -172,25 +177,163 @@ sem_timedwait: movl %esi, (%eax) #endif - addl $12, %esp - cfi_adjust_cfa_offset(-12) + movl 28(%esp), %ebx /* Load semaphore address. */ orl $-1, %eax - popl %ebx - cfi_adjust_cfa_offset(-4) - cfi_restore(3) - popl %edi - cfi_adjust_cfa_offset(-4) - cfi_restore(7) - popl %esi - cfi_adjust_cfa_offset(-4) - cfi_restore(6) - ret + jmp 10b + .size sem_timedwait,.-sem_timedwait -10: /* Canceled. */ - movl $0xffffffff, %gs:RESULT + + .type sem_wait_cleanup,@function +sem_wait_cleanup: LOCK - orl $0x10, %gs:CANCELHANDLING - movl %gs:CLEANUP_JMP_BUF, %eax - jmp HIDDEN_JUMPTARGET (__pthread_unwind) - cfi_endproc - .size sem_timedwait,.-sem_timedwait + decl NWAITERS(%ebx) + movl %eax, (%esp) +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -4 # Data alignment factor. + .byte 8 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 6 # Augmentation value length. + .byte 0x0 # Personality: absolute + .long __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. +#else + .long .LSTARTCODE # Start address of the code. +#endif + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size +#ifdef SHARED + .long .LexceptSTART-. +#else + .long .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_esi-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_edi-.Lpush_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x87 # DW_CFA_offset %edi + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_ebx-.Lpush_edi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 4 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsub_esp-.Lpush_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 28 + .byte 4 # DW_CFA_advance_loc4 + .long .Ladd_esp-.Lsub_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_ebx-.Ladd_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0xc3 # DW_CFA_restore %ebx + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_edi-.Lpop_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0xc7 # DW_CFA_restore %edi + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_esi-.Lpop_edi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0xc6 # DW_CFA_restore %esi + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_ret-.Lpop_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 28 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 2 + .byte 0x87 # DW_CFA_offset %edi + .uleb128 3 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 4 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S index b1296275d0..d0eef75144 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,6 +20,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #ifndef UP # define LOCK lock @@ -28,22 +29,261 @@ #endif #define SYS_futex 240 -#define FUTEX_WAKE 1 +#define FUTEX_WAIT 0 +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + .text .globl __new_sem_wait .type __new_sem_wait,@function .align 16 - cfi_startproc __new_sem_wait: - /* First check for cancellation. */ - movl %gs:CANCELHANDLING, %eax - andl $0xfffffff9, %eax - cmpl $8, %eax - je 5f +.LSTARTCODE: + pushl %ebx +.Lpush_ebx: + pushl %esi +.Lpush_esi: + subl $4, %esp +.Lsub_esp: + + movl 16(%esp), %ebx + + movl (%ebx), %eax +2: testl %eax, %eax + je 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ebx) + jne 2b +7: xorl %eax, %eax + +9: movl 4(%esp), %esi + movl 8(%esp), %ebx + addl $12, %esp +.Ladd_esp: + ret + +.Lafter_ret: +1: LOCK + incl NWAITERS(%ebx) + +.LcleanupSTART: +6: call __pthread_enable_asynccancel + movl %eax, (%esp) + +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + xorl %esi, %esi + xorl %edx, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi + + movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + testl %esi, %esi + je 3f + cmpl $-EWOULDBLOCK, %esi + jne 4f + +3: + movl (%ebx), %eax +5: testl %eax, %eax + je 6b + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ebx) + jne 5b + + LOCK + decl NWAITERS(%ebx) + jmp 7b + +4: LOCK + decl NWAITERS(%ebx) + + negl %esi +#ifdef PIC + call __i686.get_pc_thunk.bx +#else + movl $8f, %ebx +8: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl %esi, (%eax) +#endif + orl $-1, %eax + + jmp 9b + .size __new_sem_wait,.-__new_sem_wait + versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + LOCK + decl NWAITERS(%ebx) + movl %eax, (%esp) +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -4 # Data alignment factor. + .byte 8 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 6 # Augmentation value length. + .byte 0x0 # Personality: absolute + .long __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. +#else + .long .LSTARTCODE # Start address of the code. +#endif + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size +#ifdef SHARED + .long .LexceptSTART-. +#else + .long .LexceptSTART +#endif + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_ebx-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_esi-.Lpush_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsub_esp-.Lpush_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 4 # DW_CFA_advance_loc4 + .long .Ladd_esp-.Lsub_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0xc3 # DW_CFA_restore %ebx + .byte 0xc6 # DW_CFA_restore %esi + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_ret-.Ladd_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 2 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 3 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) + .section ".text.compat", "ax" + .global __old_sem_wait + .type __old_sem_wait,@function + .align 16 + cfi_startproc +__old_sem_wait: pushl %ebx cfi_adjust_cfa_offset(4) pushl %esi @@ -52,9 +292,9 @@ __new_sem_wait: cfi_adjust_cfa_offset(4) movl 16(%esp), %ebx - cfi_offset(3, -8) /* %ebx */ + cfi_offset(ebx, -8) - cfi_offset(6, -12) /* %esi */ + cfi_offset(esi, -12) 3: movl (%ebx), %eax 2: testl %eax, %eax je 1f @@ -65,17 +305,17 @@ __new_sem_wait: jne 2b xorl %eax, %eax - movl 4(%esp), %esi - cfi_restore(6) +5: movl 4(%esp), %esi movl 8(%esp), %ebx - cfi_restore(3) addl $12, %esp + cfi_restore(ebx) + cfi_restore(esi) cfi_adjust_cfa_offset(-12) ret cfi_adjust_cfa_offset(12) - cfi_offset(3, -8) /* %ebx */ - cfi_offset(6, -12) /* %esi */ + cfi_offset(ebx, -8) + cfi_offset(esi, -12) 1: call __pthread_enable_asynccancel movl %eax, (%esp) @@ -115,25 +355,8 @@ __new_sem_wait: movl %esi, (%eax) #endif orl $-1, %eax - movl 4(%esp), %esi - cfi_restore(6) - movl 8(%esp), %ebx - cfi_restore(3) - addl $12, %esp - cfi_adjust_cfa_offset(-12) - ret - -5: /* Canceled. */ - movl $0xffffffff, %gs:RESULT - LOCK - orl $0x10, %gs:CANCELHANDLING - movl %gs:CLEANUP_JMP_BUF, %eax - jmp HIDDEN_JUMPTARGET (__pthread_unwind) + jmp 5b cfi_endproc - .size __new_sem_wait,.-__new_sem_wait - versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) -#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) - .global __old_sem_wait -__old_sem_wait = __new_sem_wait + .size __old_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/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h index 21de09fe91..56f63a4623 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -23,6 +23,8 @@ #include <time.h> #include <sys/param.h> #include <bits/pthreadtypes.h> +#include <kernel-features.h> +#include <tcb-offsets.h> #ifndef LOCK_INSTR # ifdef UP @@ -38,6 +40,41 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG); \ + asm ("andl %%fs:%P1, %0" : "+r" (__fl) \ + : "i" (offsetof (struct pthread, header.private_futex))); \ + __fl | (fl); })) +# endif +#endif /* Initializer for compatibility lock. */ @@ -144,23 +181,11 @@ LLL_STUB_UNWIND_INFO_START \ LLL_STUB_UNWIND_INFO_END -#define lll_futex_wait(futex, val) \ - ({ \ - int __status; \ - register __typeof (val) _val asm ("edx") = (val); \ - __asm __volatile (LLL_EBX_LOAD \ - LLL_ENTER_KERNEL \ - LLL_EBX_LOAD \ - : "=a" (__status) \ - : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0), \ - "c" (FUTEX_WAIT), "d" (_val), \ - "i" (offsetof (tcbhead_t, sysinfo)) \ - : "memory"); \ - __status; \ - }) +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) -#define lll_futex_timed_wait(futex, val, timeout) \ +#define lll_futex_timed_wait(futex, val, timeout, private) \ ({ \ int __status; \ register __typeof (val) _val asm ("edx") = (val); \ @@ -169,14 +194,14 @@ LLL_STUB_UNWIND_INFO_END LLL_EBX_LOAD \ : "=a" (__status) \ : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ - "c" (FUTEX_WAIT), "d" (_val), \ - "i" (offsetof (tcbhead_t, sysinfo)) \ + "c" (__lll_private_flag (FUTEX_WAIT, private)), \ + "d" (_val), "i" (offsetof (tcbhead_t, sysinfo)) \ : "memory"); \ __status; \ }) -#define lll_futex_wake(futex, nr) \ +#define lll_futex_wake(futex, nr, private) \ do { \ int __ignore; \ register __typeof (nr) _nr asm ("edx") = (nr); \ @@ -185,7 +210,8 @@ LLL_STUB_UNWIND_INFO_END LLL_EBX_LOAD \ : "=a" (__ignore) \ : "0" (SYS_futex), LLL_EBX_REG (futex), \ - "c" (FUTEX_WAKE), "d" (_nr), \ + "c" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr), \ "i" (0) /* phony, to align next arg's number */, \ "i" (offsetof (tcbhead_t, sysinfo))); \ } while (0) @@ -414,21 +440,6 @@ extern int __lll_mutex_unlock_wake (int *__futex) "i" (offsetof (tcbhead_t, sysinfo))); }) -#define lll_futex_wake(futex, nr) \ - do { \ - int __ignore; \ - register __typeof (nr) _nr asm ("edx") = (nr); \ - __asm __volatile (LLL_EBX_LOAD \ - LLL_ENTER_KERNEL \ - LLL_EBX_LOAD \ - : "=a" (__ignore) \ - : "0" (SYS_futex), LLL_EBX_REG (futex), \ - "c" (FUTEX_WAKE), "d" (_nr), \ - "i" (0) /* phony, to align next arg's number */, \ - "i" (offsetof (tcbhead_t, sysinfo))); \ - } while (0) - - #define lll_mutex_islocked(futex) \ (futex != 0) @@ -448,7 +459,6 @@ extern int __lll_lock_wait (int val, int *__futex) __attribute ((regparm (2))) attribute_hidden; extern int __lll_unlock_wake (int *__futex) __attribute ((regparm (1))) attribute_hidden; -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; /* The states of a lock are: diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S index 312933c5e4..8ff0dad27f 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -19,6 +19,8 @@ #include <unwindbuf.h> #include <sysdep.h> +#include <kernel-features.h> + #ifndef UP # define LOCK lock @@ -26,8 +28,10 @@ # define LOCK #endif -#define SYS_futex 240 -#define FUTEX_WAKE 1 +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .comm __fork_generation, 4, 4 @@ -90,7 +94,16 @@ __pthread_once: jnz 3f /* Different for generation -> run initializer. */ /* Somebody else got here first. Wait. */ - movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %ecx +#else +# if FUTEX_WAIT == 0 + movl %gs:PRIVATE_FUTEX, %ecx +# else + movl $FUTEX_WAIT, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +# endif +#endif movl $SYS_futex, %eax ENTER_KERNEL jmp 6b @@ -131,7 +144,12 @@ __pthread_once: /* Wake up all other threads. */ movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +#else movl $FUTEX_WAKE, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +#endif movl $SYS_futex, %eax ENTER_KERNEL @@ -152,7 +170,12 @@ __pthread_once: movl $0, (%ebx) movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +#else movl $FUTEX_WAKE, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +#endif movl $SYS_futex, %eax ENTER_KERNEL diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h index 8df997a262..095f0e8aca 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -36,6 +36,39 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + /* Delay in spinlock loop. */ #define BUSY_WAIT_NOP asm ("hint @pause") @@ -43,18 +76,22 @@ /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) -#define lll_futex_wait(futex, val) lll_futex_timed_wait (futex, val, 0) +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) -#define lll_futex_timed_wait(ftx, val, timespec) \ +#define lll_futex_timed_wait(ftx, val, timespec, private) \ ({ \ - DO_INLINE_SYSCALL(futex, 4, (long) (ftx), FUTEX_WAIT, (int) (val), \ - (long) (timespec)); \ + DO_INLINE_SYSCALL(futex, 4, (long) (ftx), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (int) (val), (long) (timespec)); \ _r10 == -1 ? -_retval : _retval; \ }) -#define lll_futex_wake(ftx, nr) \ +#define lll_futex_wake(ftx, nr, private) \ ({ \ - DO_INLINE_SYSCALL(futex, 3, (long) (ftx), FUTEX_WAKE, (int) (nr)); \ + DO_INLINE_SYSCALL(futex, 3, (long) (ftx), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (int) (nr)); \ _r10 == -1 ? -_retval : _retval; \ }) @@ -188,7 +225,7 @@ extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) int __val = atomic_exchange_rel (__futex, 0); \ \ if (__builtin_expect (__val > 1, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_mutex_unlock(futex) \ __lll_mutex_unlock(&(futex)) @@ -200,7 +237,7 @@ extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) int __val = atomic_exchange_rel (__futex, 0); \ \ if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_robust_mutex_unlock(futex) \ __lll_robust_mutex_unlock(&(futex)) @@ -210,7 +247,7 @@ extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) ((void) ({ \ int *__futex = (futex); \ (void) atomic_exchange_rel (__futex, 0); \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_mutex_unlock_force(futex) \ __lll_mutex_unlock_force(&(futex)) @@ -226,8 +263,6 @@ extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *) /* 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) @@ -243,12 +278,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, LLL_SHARED); \ + } \ while (0) extern int __lll_timedwait_tid (int *, const struct timespec *) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c index 3b07cc127d..22e2dd3c0c 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c +++ b/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* 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. @@ -30,7 +30,7 @@ clear_once_control (void *arg) pthread_once_t *once_control = (pthread_once_t *) arg; *once_control = 0; - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); } @@ -65,7 +65,7 @@ __pthread_once (once_control, init_routine) if (((oldval ^ newval) & -4) == 0) { /* Same generation, some other thread was faster. Wait. */ - lll_futex_wait (once_control, newval); + lll_futex_wait (once_control, newval, LLL_PRIVATE); continue; } } @@ -84,7 +84,7 @@ __pthread_once (once_control, init_routine) atomic_increment (once_control); /* Wake up all other threads. */ - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); break; } diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h index 1dec19e57d..add20b6f72 100644 --- a/nptl/sysdeps/unix/sysv/linux/internaltypes.h +++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -76,9 +76,11 @@ struct pthread_condattr /* The __NWAITERS field is used as a counter and to house the number - of bits which represent the clock. COND_CLOCK_BITS is the number - of bits reserved for the clock. */ -#define COND_CLOCK_BITS 1 + of bits for other purposes. COND_CLOCK_BITS is the number + of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT + is the number of bits reserved for other purposes like the clock. */ +#define COND_CLOCK_BITS 1 +#define COND_NWAITERS_SHIFT 1 /* Read-write lock variable attribute data structure. */ @@ -96,6 +98,7 @@ struct pthread_barrier int lock; unsigned int left; unsigned int init_count; + int private; }; @@ -137,9 +140,16 @@ struct pthread_key_struct /* Semaphore variable structure. */ -struct sem +struct new_sem { - unsigned int count; + unsigned int value; + int private; + unsigned long int nwaiters; +}; + +struct old_sem +{ + unsigned int value; }; diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c index 92a188a2f3..4b614bd1a6 100644 --- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -26,6 +26,7 @@ #include <pthreadP.h> #include <bits/libc-lock.h> #include <sysdep.h> +#include <ldsodefs.h> #ifdef TLS_MULTIPLE_THREADS_IN_TCB diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym index 36e28eb2a6..cfe22b0892 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym +++ b/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym @@ -9,3 +9,4 @@ CURR_EVENT offsetof (struct pthread_barrier, curr_event) MUTEX offsetof (struct pthread_barrier, lock) LEFT offsetof (struct pthread_barrier, left) INIT_COUNT offsetof (struct pthread_barrier, init_count) +PRIVATE offsetof (struct pthread_barrier, private) diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym index c5e7978069..18e1adad43 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym +++ b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym @@ -13,4 +13,4 @@ wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) woken_seq offsetof (pthread_cond_t, __data.__woken_seq) dep_mutex offsetof (pthread_cond_t, __data.__mutex) broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq) -clock_bits COND_CLOCK_BITS +nwaiters_shift COND_NWAITERS_SHIFT diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/lowlevellock.c index 932e27300f..ab7f605f0c 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevellock.c +++ b/nptl/sysdeps/unix/sysv/linux/lowlevellock.c @@ -1,5 +1,5 @@ /* low level locking for pthread library. Generic futex-using version. - Copyright (C) 2003 Free Software Foundation, Inc. + 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. @@ -31,7 +31,9 @@ __lll_lock_wait (int *futex) { int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); if (oldval != 0) - lll_futex_wait (futex, 2); + lll_futex_wait (futex, 2, + // XYZ check mutex flag + LLL_SHARED); } while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); } @@ -68,7 +70,9 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime) /* Wait. */ int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); if (oldval != 0) - lll_futex_timed_wait (futex, 2, &rt); + lll_futex_timed_wait (futex, 2, &rt, + // XYZ check mutex flag + LLL_SHARED); } while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); @@ -76,21 +80,9 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime) } -/* These don't get included in libc.so */ +/* This function doesn't get included in libc.so */ #ifdef IS_IN_libpthread int -lll_unlock_wake_cb (int *futex) -{ - int val = atomic_exchange_rel (futex, 0); - - if (__builtin_expect (val > 1, 0)) - lll_futex_wake (futex, 1); - - return 0; -} - - -int __lll_timedwait_tid (int *tidp, const struct timespec *abstime) { int tid; @@ -120,12 +112,12 @@ __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; } return 0; } - #endif diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c index 30ef991bd0..54cee0859b 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c +++ b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c @@ -44,7 +44,9 @@ __lll_robust_lock_wait (int *futex) && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) continue; - lll_futex_wait (futex, newval); + lll_futex_wait (futex, newval, + // XYZ check mutex flag + LLL_SHARED); try: ; @@ -100,7 +102,9 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime) && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) continue; - lll_futex_timed_wait (futex, newval, &rt); + lll_futex_timed_wait (futex, newval, &rt, + // XYZ check mutex flag + LLL_SHARED); try: ; diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym index e82c878d39..f50b25bfb8 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym +++ b/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym @@ -1,6 +1,7 @@ #include <stddef.h> #include <stdio.h> #include <bits/pthreadtypes.h> +#include <bits/wordsize.h> -- @@ -12,3 +13,4 @@ READERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_readers_queued) WRITERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_writers_queued) FLAGS offsetof (pthread_rwlock_t, __data.__flags) WRITER offsetof (pthread_rwlock_t, __data.__writer) +PSHARED offsetof (pthread_rwlock_t, __data.__shared) diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h index a7150f6aef..c0b59c336f 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -1,5 +1,5 @@ /* Machine-specific pthread type layouts. PowerPC version. - Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -160,9 +160,9 @@ typedef union unsigned int __nr_readers_queued; unsigned int __nr_writers_queued; int __writer; - int __pad1; + int __shared; + unsigned long int __pad1; unsigned long int __pad2; - unsigned long int __pad3; /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ unsigned int __flags; @@ -176,9 +176,12 @@ typedef union unsigned int __writer_wakeup; unsigned int __nr_readers_queued; unsigned int __nr_writers_queued; + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ - unsigned int __flags; + unsigned char __flags; int __writer; } __data; # endif diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h index 239f4ddf55..cf91f21483 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h @@ -37,37 +37,63 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif /* 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); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ - }) +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) -#define lll_futex_timed_wait(futexp, val, timespec) \ +#define lll_futex_timed_wait(futexp, val, timespec, private) \ ({ \ 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), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ }) -#define lll_futex_wake(futexp, nr) \ +#define lll_futex_wake(futexp, nr, private) \ ({ \ 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), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ }) @@ -95,18 +121,19 @@ }) /* Returns non-zero if error happened, zero if success. */ -#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ \ - __ret = INTERNAL_SYSCALL (futex, __err, 6, \ - (futexp), FUTEX_WAKE_OP, (nr_wake), \ - (nr_wake2), (futexp2), \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) - + + #ifdef UP # define __lll_acq_instr "" # define __lll_rel_instr "" @@ -228,7 +255,7 @@ extern int __lll_robust_timedlock_wait int *__futex = &(lock); \ int __val = atomic_exchange_rel (__futex, 0); \ if (__builtin_expect (__val > 1, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_robust_mutex_unlock(lock) \ @@ -236,7 +263,7 @@ extern int __lll_robust_timedlock_wait int *__futex = &(lock); \ int __val = atomic_exchange_rel (__futex, 0); \ if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_mutex_unlock_force(lock) \ @@ -244,7 +271,7 @@ extern int __lll_robust_timedlock_wait int *__futex = &(lock); \ *__futex = 0; \ __asm __volatile (__lll_rel_instr ::: "memory"); \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_mutex_islocked(futex) \ @@ -261,8 +288,6 @@ typedef int lll_lock_t; #define LLL_LOCK_INITIALIZER (0) #define LLL_LOCK_INITIALIZER_LOCKED (1) -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; - /* The states of a lock are: 0 - untaken 1 - taken by one user @@ -281,7 +306,7 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; do { \ __typeof (tid) __tid; \ while ((__tid = (tid)) != 0) \ - lll_futex_wait (&(tid), __tid); \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ } while (0) extern int __lll_timedwait_tid (int *, const struct timespec *) diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c index 9472dd17ef..6fedac1b33 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c @@ -1,3 +1,4 @@ +#include <unistd.h> /* For __getpagesize. */ #define NEW_VERNUM GLIBC_2_6 #define STACKSIZE_ADJUST \ do { \ diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c index e1afff8a38..969078094d 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -30,7 +30,7 @@ clear_once_control (void *arg) pthread_once_t *once_control = (pthread_once_t *) arg; *once_control = 0; - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); } @@ -74,7 +74,7 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) break; /* Same generation, some other thread was faster. Wait. */ - lll_futex_wait (once_control, oldval); + lll_futex_wait (once_control, oldval, LLL_PRIVATE); } @@ -92,7 +92,7 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) atomic_increment (once_control); /* Wake up all other threads. */ - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); return 0; } diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c b/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c index 91b9955181..0b18cdbcde 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c @@ -1,5 +1,5 @@ /* sem_post -- post to a POSIX semaphore. Powerpc version. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -33,7 +33,7 @@ __new_sem_post (sem_t *sem) __asm __volatile (__lll_rel_instr ::: "memory"); int nr = atomic_increment_val (futex); - int err = lll_futex_wake (futex, nr); + int err = lll_futex_wake (futex, nr, LLL_SHARED); if (__builtin_expect (err, 0) < 0) { __set_errno (-err); diff --git a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h index 6b3d3682da..4a49925588 100644 --- a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h +++ b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h @@ -1,5 +1,5 @@ /* Defintions for lowlevel handling in ld.so. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 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 @@ -24,115 +24,6 @@ #include <lowlevellock.h> -/* Special multi-reader lock used in ld.so. */ -#define __RTLD_MRLOCK_WRITER 1 -#define __RTLD_MRLOCK_RWAIT 2 -#define __RTLD_MRLOCK_WWAIT 4 -#define __RTLD_MRLOCK_RBITS \ - ~(__RTLD_MRLOCK_WRITER | __RTLD_MRLOCK_RWAIT | __RTLD_MRLOCK_WWAIT) -#define __RTLD_MRLOCK_INC 8 -#define __RTLD_MRLOCK_TRIES 5 - - -typedef int __rtld_mrlock_t; - - -#define __rtld_mrlock_define(CLASS,NAME) \ - CLASS __rtld_mrlock_t NAME; - - -#define _RTLD_MRLOCK_INITIALIZER 0 -#define __rtld_mrlock_initialize(NAME) \ - (void) ((NAME) = 0) - - -#define __rtld_mrlock_lock(lock) \ - do { \ - __label__ out; \ - while (1) \ - { \ - int oldval; \ - for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries) \ - { \ - oldval = lock; \ - while (__builtin_expect ((oldval \ - & (__RTLD_MRLOCK_WRITER \ - | __RTLD_MRLOCK_WWAIT)) \ - == 0, 1)) \ - { \ - int newval = ((oldval & __RTLD_MRLOCK_RBITS) \ - + __RTLD_MRLOCK_INC); \ - int ret = atomic_compare_and_exchange_val_acq (&(lock), \ - newval, \ - oldval); \ - if (__builtin_expect (ret == oldval, 1)) \ - goto out; \ - oldval = ret; \ - } \ - atomic_delay (); \ - } \ - if ((oldval & __RTLD_MRLOCK_RWAIT) == 0) \ - { \ - atomic_or (&(lock), __RTLD_MRLOCK_RWAIT); \ - oldval |= __RTLD_MRLOCK_RWAIT; \ - } \ - lll_futex_wait (lock, oldval); \ - } \ - out:; \ - } while (0) - - -#define __rtld_mrlock_unlock(lock) \ - do { \ - int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_INC); \ - if (__builtin_expect ((oldval \ - & (__RTLD_MRLOCK_RBITS | __RTLD_MRLOCK_WWAIT)) \ - == (__RTLD_MRLOCK_INC | __RTLD_MRLOCK_WWAIT), 0)) \ - /* We have to wake all threads since there might be some queued \ - readers already. */ \ - lll_futex_wake (&(lock), 0x7fffffff); \ - } while (0) - - -/* There can only ever be one thread trying to get the exclusive lock. */ -#define __rtld_mrlock_change(lock) \ - do { \ - __label__ out; \ - while (1) \ - { \ - int oldval; \ - for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries) \ - { \ - oldval = lock; \ - while (__builtin_expect ((oldval & __RTLD_MRLOCK_RBITS) == 0, 1)) \ - { \ - int newval = ((oldval & __RTLD_MRLOCK_RWAIT) \ - + __RTLD_MRLOCK_WRITER); \ - int ret = atomic_compare_and_exchange_val_acq (&(lock), \ - newval, \ - oldval); \ - if (__builtin_expect (ret == oldval, 1)) \ - goto out; \ - oldval = ret; \ - } \ - atomic_delay (); \ - } \ - atomic_or (&(lock), __RTLD_MRLOCK_WWAIT); \ - oldval |= __RTLD_MRLOCK_WWAIT; \ - lll_futex_wait (lock, oldval); \ - } \ - out:; \ - } while (0) - - -#define __rtld_mrlock_done(lock) \ - do { \ - int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_WRITER); \ - if (__builtin_expect ((oldval & __RTLD_MRLOCK_RWAIT) != 0, 0)) \ - lll_futex_wake (&(lock), 0x7fffffff); \ - } while (0) - - /* Function to wait for variable become zero. Used in ld.so for reference counters. */ #define __rtld_waitzero(word) \ @@ -142,12 +33,12 @@ typedef int __rtld_mrlock_t; int val = word; \ if (val == 0) \ break; \ - lll_futex_wait (&(word), val); \ + lll_futex_wait (&(word), val, LLL_PRIVATE); \ } \ } while (0) #define __rtld_notify(word) \ - lll_futex_wake (&(word), 1) + lll_futex_wake (&(word), 1, LLL_PRIVATE) #endif diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h index 38d9f2ac41..4758b63bd0 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. @@ -35,31 +35,50 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) -#define lll_futex_wait(futex, val) \ - ({ \ - register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ - register unsigned long int __r3 asm ("3") = FUTEX_WAIT; \ - register unsigned long int __r4 asm ("4") = (unsigned long int) (val); \ - register unsigned long int __r5 asm ("5") = 0ul; \ - register unsigned long __result asm ("2"); \ - \ - __asm __volatile ("svc %b1" \ - : "=d" (__result) \ - : "i" (SYS_futex), "0" (__r2), "d" (__r3), \ - "d" (__r4), "d" (__r5) \ - : "cc", "memory" ); \ - __result; \ - }) +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) - -#define lll_futex_timed_wait(futex, val, timespec) \ +#define lll_futex_timed_wait(futex, val, timespec, private) \ ({ \ register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ - register unsigned long int __r3 asm ("3") = FUTEX_WAIT; \ + register unsigned long int __r3 asm ("3") \ + = __lll_private_flag (FUTEX_WAIT, private); \ register unsigned long int __r4 asm ("4") = (unsigned long int) (val); \ register unsigned long int __r5 asm ("5") = (unsigned long int)(timespec);\ register unsigned long int __result asm ("2"); \ @@ -73,10 +92,11 @@ }) -#define lll_futex_wake(futex, nr) \ +#define lll_futex_wake(futex, nr, private) \ ({ \ register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ - register unsigned long int __r3 asm ("3") = FUTEX_WAKE; \ + register unsigned long int __r3 asm ("3") \ + __lll_private_flag (FUTEX_WAKE, private); \ register unsigned long int __r4 asm ("4") = (unsigned long int) (nr); \ register unsigned long int __result asm ("2"); \ \ @@ -94,7 +114,7 @@ int *__futexp = &(futexv); \ \ atomic_or (__futexp, FUTEX_OWNER_DIED); \ - lll_futex_wake (__futexp, 1); \ + lll_futex_wake (__futexp, 1, LLL_SHARED); \ } \ while (0) @@ -271,7 +291,7 @@ __lll_mutex_unlock (int *futex) lll_compare_and_swap (futex, oldval, newval, "slr %2,%2"); if (oldval > 1) - lll_futex_wake (futex, 1); + lll_futex_wake (futex, 1, LLL_SHARED); } #define lll_mutex_unlock(futex) \ __lll_mutex_unlock(&(futex)) @@ -286,7 +306,7 @@ __lll_robust_mutex_unlock (int *futex, int mask) lll_compare_and_swap (futex, oldval, newval, "slr %2,%2"); if (oldval & mask) - lll_futex_wake (futex, 1); + lll_futex_wake (futex, 1, LLL_SHARED); } #define lll_robust_mutex_unlock(futex) \ __lll_robust_mutex_unlock(&(futex), FUTEX_WAITERS) @@ -297,7 +317,7 @@ __attribute__ ((always_inline)) __lll_mutex_unlock_force (int *futex) { *futex = 0; - lll_futex_wake (futex, 1); + lll_futex_wake (futex, 1, LLL_SHARED); } #define lll_mutex_unlock_force(futex) \ __lll_mutex_unlock_force(&(futex)) @@ -321,8 +341,6 @@ typedef int lll_lock_t; #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; - /* The states of a lock are: 1 - untaken 0 - taken by one user @@ -340,7 +358,7 @@ __lll_wait_tid (int *ptid) int tid; while ((tid = *ptid) != 0) - lll_futex_wait (ptid, tid); + lll_futex_wait (ptid, tid, LLL_SHARED); } #define lll_wait_tid(tid) __lll_wait_tid(&(tid)) diff --git a/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c index f29e23fd4b..0012e9ae27 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c +++ b/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. @@ -30,7 +30,7 @@ clear_once_control (void *arg) pthread_once_t *once_control = (pthread_once_t *) arg; *once_control = 0; - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); } @@ -76,7 +76,7 @@ __pthread_once (once_control, init_routine) if (((oldval ^ newval) & -4) == 0) { /* Same generation, some other thread was faster. Wait. */ - lll_futex_wait (once_control, newval); + lll_futex_wait (once_control, newval, LLL_PRIVATE); continue; } } @@ -101,7 +101,7 @@ __pthread_once (once_control, init_routine) : "m" (*once_control) : "cc" ); /* Wake up all other threads. */ - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); break; } diff --git a/nptl/sysdeps/unix/sysv/linux/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sem_post.c index 671b43f7f7..7f90325585 100644 --- a/nptl/sysdeps/unix/sysv/linux/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/sem_post.c @@ -1,5 +1,5 @@ /* sem_post -- post to a POSIX semaphore. Generic futex-using version. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + 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. @@ -29,10 +29,36 @@ int __new_sem_post (sem_t *sem) { + struct new_sem *isem = (struct 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, + // XYZ check mutex flag + LLL_SHARED); + 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) +{ int *futex = (int *) sem; int nr = atomic_increment_val (futex); - int err = lll_futex_wake (futex, nr); + /* 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); @@ -40,8 +66,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/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c index ef897c1e93..8f92d78abe 100644 --- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c +++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c @@ -1,5 +1,5 @@ /* sem_timedwait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003 Free Software Foundation, Inc. + 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,28 +28,29 @@ #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 new_sem *isem = (struct new_sem *) sem; int err; - if (*futex > 0) + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { - val = atomic_decrement_if_positive (futex); - if (val > 0) - return 0; + __set_errno (EINVAL); + return -1; } - err = -EINVAL; - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - goto error_return; + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); - do + while (1) { struct timeval tv; struct timespec rt; @@ -70,7 +71,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; @@ -79,21 +84,30 @@ 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, + // XYZ check mutex flag + LLL_SHARED); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (oldtype); if (err != 0 && err != -EWOULDBLOCK) - goto error_return; + { + __set_errno (-err); + err = -1; + break; + } - val = atomic_decrement_if_positive (futex); + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } } - while (val <= 0); - return 0; + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); - error_return: - __set_errno (-err); - return -1; + return err; } diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c index e6733e88a3..12f3f16c2d 100644 --- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -1,5 +1,5 @@ /* sem_wait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003 Free Software Foundation, Inc. + 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,12 +28,69 @@ #include <shlib-compat.h> +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct new_sem *isem = (struct new_sem *) arg; + + atomic_decrement (&isem->nwaiters); +} + + int __new_sem_wait (sem_t *sem) { - /* First check for cancellation. */ - CANCELLATION_P (THREAD_SELF); + struct new_sem *isem = (struct 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, + // XYZ check mutex flag + LLL_SHARED); + + /* 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) +{ int *futex = (int *) sem; int err; @@ -45,7 +102,8 @@ __new_sem_wait (sem_t *sem) /* Enable asynchronous cancellation. Required by the standard. */ int oldtype = __pthread_enable_asynccancel (); - err = lll_futex_wait (futex, 0); + /* Always assume the semaphore is shared. */ + err = lll_futex_wait (futex, 0, LLL_SHARED); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (oldtype); @@ -56,8 +114,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/sh/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h index 969686dd5a..badcda5701 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,6 +21,8 @@ #ifndef _BITS_PTHREADTYPES_H #define _BITS_PTHREADTYPES_H 1 +#include <endian.h> + #define __SIZEOF_PTHREAD_ATTR_T 36 #define __SIZEOF_PTHREAD_MUTEX_T 24 #define __SIZEOF_PTHREAD_MUTEXATTR_T 4 @@ -127,9 +130,21 @@ typedef union unsigned int __writer_wakeup; unsigned int __nr_readers_queued; unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ - unsigned int __flags; + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif pthread_t __writer; } __data; char __size[__SIZEOF_PTHREAD_RWLOCK_T]; diff --git a/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S index 94a24b46ee..be85ab7414 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 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 @@ -16,4 +16,32 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <kernel-features.h> + +/* All locks in libc are private. Use the kernel feature if possible. */ +#define FUTEX_PRIVATE_FLAG 128 +#ifdef __ASSUME_PRIVATE_FUTEX +# define FUTEX_WAIT (0 | FUTEX_PRIVATE_FLAG) +# define FUTEX_WAKE (1 | FUTEX_PRIVATE_FLAG) +#else +# define LOAD_FUTEX_WAIT(reg,tmp) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + bra 98f ; \ + mov.l @tmp, reg ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: + +# define LOAD_FUTEX_WAKE(reg,tmp) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + mov.l @tmp, reg ; \ + bra 98f ; \ + mov #FUTEX_WAKE, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: or tmp, reg +#endif + #include "lowlevellock.S" diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S index ac3169889f..b10903bcd7 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2005, 2007 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 @@ -24,8 +24,24 @@ #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 +#ifndef FUTEX_WAIT +# define FUTEX_WAIT 0 +# define FUTEX_WAKE 1 +#endif + +#ifndef LOAD_FUTEX_WAIT +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg,tmp) \ + xor reg, reg +# else +# define LOAD_FUTEX_WAIT(reg,tmp) \ + mov #FUTEX_WAIT, reg; \ + extu.b reg, reg +# endif +# define LOAD_FUTEX_WAKE(reg,tmp) \ + mov #FUTEX_WAKE, reg; \ + extu.b reg, reg +#endif .globl __lll_mutex_lock_wait @@ -40,7 +56,7 @@ __lll_mutex_lock_wait: mov r4, r6 mov r5, r8 mov #0, r7 /* No timeout. */ - mov #FUTEX_WAIT, r5 + LOAD_FUTEX_WAIT (r5, r0) mov #2, r4 cmp/eq r4, r6 @@ -133,7 +149,7 @@ __lll_mutex_timedlock_wait: bt 8f mov r8, r4 - mov #FUTEX_WAIT, r5 + LOAD_FUTEX_WAIT (r5, r0) mov r10, r6 mov r15, r7 mov #SYS_futex, r3 @@ -186,41 +202,13 @@ __lll_mutex_timedlock_wait: #endif -#ifdef NOT_IN_libc - .globl lll_unlock_wake_cb - .type lll_unlock_wake_cb,@function - .hidden lll_unlock_wake_cb - .align 5 - cfi_startproc -lll_unlock_wake_cb: - DEC (@r4, r2) - tst r2, r2 - bt 1f - - mov #FUTEX_WAKE, r5 - mov #1, r6 /* Wake one thread. */ - mov #0, r7 - mov.l r7, @r4 /* Stores 0. */ - mov #SYS_futex, r3 - extu.b r3, r3 - trapa #0x14 - SYSCALL_INST_PAD - -1: - rts - nop - cfi_endproc - .size lll_unlock_wake_cb,.-lll_unlock_wake_cb -#endif - - .globl __lll_mutex_unlock_wake .type __lll_mutex_unlock_wake,@function .hidden __lll_mutex_unlock_wake .align 5 cfi_startproc __lll_mutex_unlock_wake: - mov #FUTEX_WAKE, r5 + LOAD_FUTEX_WAKE (r5, r0) mov #1, r6 /* Wake one thread. */ mov #0, r7 mov.l r7, @r4 /* Stores 0. */ @@ -289,7 +277,10 @@ __lll_timedwait_tid: bt 4f mov r8, r4 - mov #FUTEX_WAIT, r5 + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ + mov #0, r5 + extu.b r5, r5 mov r2, r6 mov r15, r7 mov #SYS_futex, r3 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h index 0eb1f0114c..be47bd752e 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 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 @@ -22,6 +22,7 @@ #include <time.h> #include <sys/param.h> #include <bits/pthreadtypes.h> +#include <kernel-features.h> #define SYS_futex 240 #define FUTEX_WAIT 0 @@ -29,6 +30,39 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif /* Initializer for compatibility lock. */ @@ -251,7 +285,7 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden; and %2,%0\n\ mov.l %0,@%1\n\ 1: mov r1,r15"\ - : "=&r" (__result) : "r" (__futex), "r" (FUTEX_TID_MASK) \ + : "=&r" (__result) : "r" (__futex), "r" (FUTEX_WAITERS) \ : "r0", "r1", "memory"); \ if (__result) \ __lll_mutex_unlock_wake (__futex); }) @@ -269,7 +303,7 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden; 1: mov r1,r15"\ : "=&r" (__ignore) : "r" (__futex), "r" (FUTEX_OWNER_DIED) \ : "r0", "r1", "memory"); \ - lll_futex_wake (__futex, 1); }) + lll_futex_wake (__futex, 1, LLL_SHARED); }) #define lll_mutex_islocked(futex) \ (futex != 0) @@ -294,29 +328,17 @@ typedef int lll_lock_t; trapa #0x14" # endif -#define lll_futex_wait(futex, val) \ - ({ \ - int __status; \ - register unsigned long __r3 asm ("r3") = SYS_futex; \ - register unsigned long __r4 asm ("r4") = (unsigned long) (futex); \ - register unsigned long __r5 asm ("r5") = FUTEX_WAIT; \ - register unsigned long __r6 asm ("r6") = (unsigned long) (val); \ - register unsigned long __r7 asm ("r7") = 0; \ - __asm __volatile (SYSCALL_WITH_INST_PAD \ - : "=z" (__status) \ - : "r" (__r3), "r" (__r4), "r" (__r5), \ - "r" (__r6), "r" (__r7) \ - : "memory", "t"); \ - __status; \ - }) +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) -#define lll_futex_timed_wait(futex, val, timeout) \ +#define lll_futex_timed_wait(futex, val, timeout, private) \ ({ \ int __status; \ register unsigned long __r3 asm ("r3") = SYS_futex; \ register unsigned long __r4 asm ("r4") = (unsigned long) (futex); \ - register unsigned long __r5 asm ("r5") = FUTEX_WAIT; \ + register unsigned long __r5 asm ("r5") \ + = __lll_private_flag (FUTEX_WAIT, private); \ register unsigned long __r6 asm ("r6") = (unsigned long) (val); \ register unsigned long __r7 asm ("r7") = (timeout); \ __asm __volatile (SYSCALL_WITH_INST_PAD \ @@ -328,12 +350,13 @@ typedef int lll_lock_t; }) -#define lll_futex_wake(futex, nr) \ +#define lll_futex_wake(futex, nr, private) \ do { \ int __ignore; \ register unsigned long __r3 asm ("r3") = SYS_futex; \ register unsigned long __r4 asm ("r4") = (unsigned long) (futex); \ - register unsigned long __r5 asm ("r5") = FUTEX_WAKE; \ + register unsigned long __r5 asm ("r5") \ + = __lll_private_flag (FUTEX_WAKE, private); \ register unsigned long __r6 asm ("r6") = (unsigned long) (nr); \ register unsigned long __r7 asm ("r7") = 0; \ __asm __volatile (SYSCALL_WITH_INST_PAD \ @@ -344,9 +367,6 @@ typedef int lll_lock_t; } while (0) -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; - - /* The states of a lock are: 0 - untaken 1 - taken by one user @@ -370,7 +390,7 @@ extern int __lll_wait_tid (int *tid) attribute_hidden; do { \ __typeof (tid) *__tid = &(tid); \ while (*__tid != 0) \ - lll_futex_wait (__tid, *__tid); \ + lll_futex_wait (__tid, *__tid, LLL_SHARED); \ } while (0) extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S index 1fbb23a5a6..35dd607fc1 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2007 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 @@ -65,7 +65,13 @@ pthread_barrier_wait: #if CURR_EVENT != 0 add #CURR_EVENT, r4 #endif +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else mov #FUTEX_WAIT, r5 + mov.l @(PRIVATE,r8), r0 + or r0, r5 +#endif mov #0, r7 8: mov #SYS_futex, r3 @@ -118,6 +124,8 @@ pthread_barrier_wait: #endif mov #0, r7 mov #FUTEX_WAKE, r5 + mov.l @(PRIVATE,r8), r0 + or r0, r5 mov #SYS_futex, r3 extu.b r3, r3 trapa #0x14 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 6c782c8a76..0173cfb7d8 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 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 @@ -120,7 +120,7 @@ __pthread_cond_timedwait: mov.l @(cond_futex,r8), r0 add r2, r0 mov.l r0, @(cond_futex,r8) - mov #(1 << clock_bits), r2 + mov #(1 << nwaiters_shift), r2 mov.l @(cond_nwaiters,r8), r0 add r2, r0 mov.l r0, @(cond_nwaiters,r8) @@ -136,7 +136,7 @@ __pthread_cond_timedwait: #ifdef __NR_clock_gettime /* Get the clock number. */ mov.l @(cond_nwaiters,r8), r4 - mov #((1 << clock_bits) - 1), r0 + mov #((1 << nwaiters_shift) - 1), r0 and r0, r4 /* Only clocks 0 and 1 are allowed. Both are handled in the kernel. */ @@ -323,7 +323,7 @@ __pthread_cond_timedwait: mov.l r1,@(woken_seq+4,r8) 24: - mov #(1 << clock_bits), r2 + mov #(1 << nwaiters_shift), r2 mov.l @(cond_nwaiters,r8),r0 sub r2, r0 mov.l r0,@(cond_nwaiters,r8) @@ -335,7 +335,7 @@ __pthread_cond_timedwait: not r0, r0 cmp/eq #0, r0 bf/s 25f - mov #((1 << clock_bits) - 1), r1 + mov #((1 << nwaiters_shift) - 1), r1 not r1, r1 mov.l @(cond_nwaiters,r8),r0 tst r1, r0 @@ -557,7 +557,7 @@ __condvar_tw_cleanup: mov.l r1,@(woken_seq+4,r8) 3: - mov #(1 << clock_bits), r2 + mov #(1 << nwaiters_shift), r2 mov.l @(cond_nwaiters,r8),r0 sub r2, r0 mov.l r0,@(cond_nwaiters,r8) @@ -570,7 +570,7 @@ __condvar_tw_cleanup: not r0, r0 cmp/eq #0, r0 bf/s 4f - mov #((1 << clock_bits) - 1), r1 + mov #((1 << nwaiters_shift) - 1), r1 not r1, r1 mov.l @(cond_nwaiters,r8),r0 tst r1, r0 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 6c59f3e6c0..5eb332e484 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 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 @@ -107,7 +107,7 @@ __pthread_cond_wait: mov.l @(cond_futex,r8),r0 add r2, r0 mov.l r0,@(cond_futex,r8) - mov #(1 << clock_bits), r2 + mov #(1 << nwaiters_shift), r2 mov.l @(cond_nwaiters,r8), r0 add r2, r0 mov.l r0, @(cond_nwaiters,r8) @@ -197,7 +197,7 @@ __pthread_cond_wait: mov.l r1,@(woken_seq+4,r8) 16: - mov #(1 << clock_bits), r2 + mov #(1 << nwaiters_shift), r2 mov.l @(cond_nwaiters,r8),r0 sub r2, r0 mov.l r0,@(cond_nwaiters,r8) @@ -209,7 +209,7 @@ __pthread_cond_wait: not r0, r0 cmp/eq #0, r0 bf/s 17f - mov #((1 << clock_bits) - 1), r1 + mov #((1 << nwaiters_shift) - 1), r1 not r1, r1 mov.l @(cond_nwaiters,r8),r0 tst r1, r0 @@ -421,7 +421,7 @@ __condvar_w_cleanup: mov.l r1,@(woken_seq+4,r8) 3: - mov #(1 << clock_bits), r2 + mov #(1 << nwaiters_shift), r2 mov.l @(cond_nwaiters,r8),r0 sub r2, r0 mov.l r0,@(cond_nwaiters,r8) @@ -434,7 +434,7 @@ __condvar_w_cleanup: not r0, r0 cmp/eq #0, r0 bf/s 4f - mov #((1 << clock_bits) - 1), r1 + mov #((1 << nwaiters_shift) - 1), r1 not r1, r1 mov.l @(cond_nwaiters,r8),r0 tst r1, r0 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S index 02af56b4c7..3d694d8376 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2007 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 @@ -18,11 +18,13 @@ #include <unwindbuf.h> #include <sysdep.h> +#include <kernel-features.h> #include "lowlevel-atomic.h" -#define SYS_futex 240 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .comm __fork_generation, 4, 4 @@ -95,7 +97,19 @@ __pthread_once: bf 3f /* Different for generation -> run initializer. */ /* Somebody else got here first. Wait. */ - mov #FUTEX_WAIT, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif +#endif mov r3, r6 mov #0, r7 mov #SYS_futex, r3 @@ -157,7 +171,17 @@ __pthread_once: INC (@r9, r2) /* Wake up all other threads. */ mov r9, r4 - mov #FUTEX_WAKE, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), 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 mov #-1, r6 shlr r6 /* r6 = 0x7fffffff */ mov #0, r7 @@ -192,7 +216,17 @@ __pthread_once: mov #0, r7 mov.l r7, @r9 mov r9, r4 - mov #FUTEX_WAKE, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif + extu.b r5, r5 mov #-1, r6 shlr r6 /* r6 = 0x7fffffff */ mov #SYS_futex, r3 @@ -208,6 +242,10 @@ __pthread_once: sleep cfi_endproc +#if !__ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif .align 2 .Lsigsetjmp: .long __sigsetjmp@PLT-(.Lsigsetjmp0-.) @@ -224,23 +262,3 @@ __pthread_once_internal = __pthread_once .globl pthread_once pthread_once = __pthread_once - - - .type clear_once_control,@function - .align 5 -clear_once_control: - mov #0, r0 - mov.l r0, @r4 - - mov #FUTEX_WAKE, r5 - mov #-1, r6 - shlr r6 /* r6 = 0x7fffffff */ - mov #0, r7 - mov #SYS_futex, r3 - extu.b r3, r3 - trapa #0x14 - SYSCALL_INST_PAD - - rts - nop - .size clear_once_control,.-clear_once_control 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 f64c7217c9..f1795131f8 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 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 @@ -20,11 +20,13 @@ #include <lowlevelrwlock.h> #include <pthread-errnos.h> #include <tcb-offsets.h> +#include <kernel-features.h> #include "lowlevel-atomic.h" #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .text @@ -55,7 +57,8 @@ __pthread_rwlock_rdlock: mov.l @(WRITERS_QUEUED,r8), r0 tst r0, r0 bt 5f - mov.l @(FLAGS,r8), r0 + mov #FLAGS, r0 + mov.b @(r0,r8), r0 tst r0, r0 bt 5f 3: @@ -75,9 +78,28 @@ __pthread_rwlock_rdlock: tst r2, r2 bf 10f 11: +#if __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif mov r8, r4 add #READERS_WAKEUP, r4 - mov #FUTEX_WAIT, r5 mov r9, r6 mov #0, r7 mov #SYS_futex, r3 @@ -124,6 +146,11 @@ __pthread_rwlock_rdlock: rts mov r3, r0 +#if !__ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + 1: mov r8, r5 #if MUTEX != 0 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 633a14b1aa..e87326e9bd 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 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 @@ -20,12 +20,14 @@ #include <lowlevelrwlock.h> #include <pthread-errnos.h> #include <tcb-offsets.h> +#include <kernel-features.h> #include "lowlevel-atomic.h" #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .text @@ -59,7 +61,8 @@ pthread_rwlock_timedrdlock: mov.l @(WRITERS_QUEUED,r8), r0 tst r0, r0 bt 5f - mov.l @(FLAGS,r8), r0 + mov #FLAGS, r0 + mov.b @(r0,r8), r0 tst r0, r0 bt 5f 3: @@ -117,7 +120,26 @@ pthread_rwlock_timedrdlock: /* Futex call. */ mov r15, r7 - mov #FUTEX_WAIT, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif mov r10, r6 mov r8, r4 add #READERS_WAKEUP, r4 @@ -176,6 +198,10 @@ pthread_rwlock_timedrdlock: rts mov r3, r0 +#if !__ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif .align 2 .L1k0: .long 1000 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 29e29b6f65..18641fe9df 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 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 @@ -20,12 +20,14 @@ #include <lowlevelrwlock.h> #include <pthread-errnos.h> #include <tcb-offsets.h> +#include <kernel-features.h> #include "lowlevel-atomic.h" #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .text @@ -114,7 +116,26 @@ pthread_rwlock_timedwrlock: /* Futex call. */ mov r15, r7 - mov #FUTEX_WAIT, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif mov r10, r6 mov r8, r4 add #WRITERS_WAKEUP, r4 @@ -175,6 +196,10 @@ pthread_rwlock_timedwrlock: rts mov r3, r0 +#if !__ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif .L1k1: .word 1000 .align 2 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 172689bec3..df4df60d7f 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 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 @@ -18,11 +18,13 @@ #include <sysdep.h> #include <lowlevelrwlock.h> +#include <kernel-features.h> #include "lowlevel-atomic.h" #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .text @@ -87,7 +89,24 @@ __pthread_rwlock_unlock: bf 7f 8: - mov #FUTEX_WAKE, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif mov #SYS_futex, r3 mov #0, r7 extu.b r3, r3 @@ -154,6 +173,10 @@ __pthread_rwlock_unlock: bra 8b mov.l @r15+, r4 +#if !__ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif .align 2 .Lwait8: .long __lll_mutex_lock_wait-.Lwait8b 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 995d823e80..13a2fda9fd 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 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 @@ -20,11 +20,13 @@ #include <lowlevelrwlock.h> #include <pthread-errnos.h> #include <tcb-offsets.h> +#include <kernel-features.h> #include "lowlevel-atomic.h" #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .text @@ -74,7 +76,26 @@ __pthread_rwlock_wrlock: 11: mov r8, r4 add #WRITERS_WAKEUP, r4 - mov #FUTEX_WAIT, r5 +#if __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif mov r9, r6 mov #0, r7 mov #SYS_futex, r3 @@ -152,6 +173,10 @@ __pthread_rwlock_wrlock: bra 7b mov #0, r3 +#if !__ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif .Ltidoff: .word TID - TLS_PRE_TCB_SIZE diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S index 9bc12da7e0..a63233feab 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2007 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 @@ -19,6 +19,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #include "lowlevel-atomic.h" @@ -34,11 +35,14 @@ .align 5 __new_sem_post: mov #1, r3 - XADD (r3, @r4, r2) - + XADD (r3, @(VALUE,r4), r2) + mov.l @(NWAITERS,r4), r2 + tst r2, r2 + bt 2f mov #FUTEX_WAKE, r5 - mov r2, r6 - add #1, r6 + mov.l @(PRIVATE,r4), r1 + or r1, r5 + mov #1, r6 mov #0, r7 mov #SYS_futex, r3 extu.b r3, r3 @@ -47,6 +51,7 @@ __new_sem_post: cmp/pz r0 bf 1f +2: rts mov #0, r0 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S index acb7d0f78b..e5e064b3a5 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2007 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 @@ -20,32 +20,25 @@ #include <shlib-compat.h> #include <pthread-errnos.h> #include <tcb-offsets.h> +#include <structsem.h> #include "lowlevel-atomic.h" #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 #define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif .text .globl sem_timedwait .type sem_timedwait,@function .align 5 - cfi_startproc sem_timedwait: - /* First check for cancellation. */ - stc gbr, r0 - mov.w .Lchand, r1 - mov.l @(r0,r1), r0 - mov #0xf9, r1 - and r1, r0 - cmp/eq #8, r0 - bf 0f - bra 10f - stc gbr, r0 -0: +.LSTARTCODE: mov.l @r4, r0 2: tst r0, r0 @@ -62,22 +55,17 @@ sem_timedwait: 1: /* Check whether the timeout value is valid. */ mov.l r8, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r8, 0) +.Lpush_r8: mov.l r9, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r9, 0) +.Lpush_r9: mov.l r10, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r10, 0) +.Lpush_r10: mov.l r12, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r12, 0) +.Lpush_r12: sts.l pr, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (pr, 0) +.Lpush_pr: add #-8, r15 - cfi_adjust_cfa_offset(8) +.Lalloc: mov r4, r8 mov r5, r9 @@ -87,13 +75,9 @@ sem_timedwait: cmp/hs r1, r0 bt/s 6f mov #EINVAL, r0 -7: - mov.l .Lenable0, r1 - bsrf r1 - nop -.Lenable0b: - mov r0, r10 + INC (@(NWAITERS,r8),r2) +7: /* Compute relative timeout. */ mov r15, r4 mov #0, r5 @@ -124,9 +108,21 @@ sem_timedwait: mov.l r2, @r15 mov.l r3, @(4,r15) - /* Futex call. */ +.LcleanupSTART: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov r0, r10 + mov r8, r4 - mov #FUTEX_WAIT, r5 +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov.l @(PRIVATE,r8), r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif mov #0, r6 mov r15, r7 mov #SYS_futex, r3 @@ -140,6 +136,7 @@ sem_timedwait: mov r0, r10 .Ldisable0b: mov r10, r0 +.LcleanupEND: tst r0, r0 bt 9f @@ -158,6 +155,10 @@ sem_timedwait: bf/s 8b mov r2, r0 + DEC (@(NWAITERS,r8), r2) + mov #0, r0 + +10: add #8, r15 lds.l @r15+, pr mov.l @r15+, r12 @@ -165,12 +166,12 @@ sem_timedwait: mov.l @r15+, r9 mov.l @r15+, r8 rts - mov #0, r0 + nop 3: neg r0, r0 6: - mov r0, r8 + mov r0, r10 mova .Lgot2, r0 mov.l .Lgot2, r12 add r0, r12 @@ -180,46 +181,20 @@ sem_timedwait: stc gbr, r1 mov.l @(r0, r12), r0 add r1, r0 - mov.l r8, @r0 + mov.l r10, @r0 #else mov.l .Lerrloc2, r1 bsrf r1 nop .Lerrloc2b: - mov.l r8, @r0 + mov.l r10, @r0 #endif - add #8, r15 - lds.l @r15+, pr - mov.l @r15+, r12 - mov.l @r15+, r10 - mov.l @r15+, r9 - mov.l @r15+, r8 - rts + DEC (@(NWAITERS,r8), r2) + bra 10b mov #-1, r0 -10: - /* Canceled. */ - mov.w .Lresult, r1 - mov #-1, r2 - mov.l r2, @(r0,r1) - mov.w .Lchand, r0 - or.b #0x10, @(r0,gbr) - stc gbr, r0 - mov.w .Lclbuf, r1 - mov.l .Lunwind, r2 - braf r2 - mov.l @(r0,r1), r4 -.Lunwindb: - cfi_endproc - .L1k: .word 1000 -.Lchand: - .word CANCELHANDLING - TLS_PRE_TCB_SIZE -.Lresult: - .word RESULT - TLS_PRE_TCB_SIZE -.Lclbuf: - .word CLEANUP_JMP_BUF - TLS_PRE_TCB_SIZE .align 2 .L1g: .long 1000000000 @@ -236,6 +211,151 @@ sem_timedwait: .long __pthread_enable_asynccancel-.Lenable0b .Ldisable0: .long __pthread_disable_asynccancel-.Ldisable0b -.Lunwind: - .long HIDDEN_JUMPTARGET (__pthread_unwind)-.Lunwindb .size sem_timedwait,.-sem_timedwait + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + DEC (@(NWAITERS,r8), r2) +.LcallUR: + mov.l .Lresume, r1 +#ifdef PIC + add r12, r1 +#endif + jsr @r1 + nop + sleep + + .align 2 +.Lresume: +#ifdef PIC + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x01 ! call-site format + ! DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 4 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0x88 ! DW_CFA_offset r8 + .uleb128 1 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x89 ! DW_CFA_offset r9 + .uleb128 2 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x8a ! DW_CFA_offset r10 + .uleb128 3 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r12-.Lpush_r10 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x8c ! DW_CFA_offset r12 + .uleb128 4 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 20 + .byte 0x91 ! DW_CFA_offset pr + .uleb128 5 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lalloc-.Lpush_pr + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 28 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S index 9ceb8f1c24..85ce909259 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -20,44 +20,35 @@ #include <shlib-compat.h> #include <pthread-errnos.h> #include <tcb-offsets.h> +#include <structsem.h> #include "lowlevel-atomic.h" #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 #define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif .text .globl __new_sem_wait .type __new_sem_wait,@function .align 5 - cfi_startproc __new_sem_wait: - /* First check for cancellation. */ - stc gbr, r0 - mov.w .Lchand, r1 - mov.l @(r0,r1), r0 - mov #0xf9, r1 - and r1, r0 - cmp/eq #8, r0 - bt 5f - +.LSTARTCODE: mov.l r8, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r8, 0) +.Lpush_r8: mov.l r10, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r10, 0) +.Lpush_r10: mov.l r12, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (r12, 0) +.Lpush_r12: sts.l pr, @-r15 - cfi_adjust_cfa_offset(4) - cfi_rel_offset (pr, 0) +.Lpush_pr: mov r4, r8 -3: + mov.l @r8, r0 2: tst r0, r0 @@ -68,10 +59,21 @@ __new_sem_wait: CMPXCHG (r4, @r8, r3, r2) bf/s 2b mov r2, r0 - bra 9f - mov #0, r0 +7: + mov #0, r0 +9: + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r10 + rts + mov.l @r15+, r8 +.Lafter_ret: 1: + INC (@(NWAITERS,r8),r2) + +.LcleanupSTART: +6: mov.l .Lenable0, r1 bsrf r1 nop @@ -79,7 +81,13 @@ __new_sem_wait: mov r0, r10 mov r8, r4 - mov #FUTEX_WAIT, r5 +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov.l @(PRIVATE,r8), r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif mov #0, r6 mov #0, r7 mov #SYS_futex, r3 @@ -93,14 +101,35 @@ __new_sem_wait: mov r0, r10 .Ldisable0b: mov r10, r0 +.LcleanupEND: tst r0, r0 - bt 3b + bt 3f cmp/eq #-EWOULDBLOCK, r0 - bt 3b - neg r0, r0 + bf 4f + +3: + mov.l @r8, r0 +5: + tst r0, r0 + bt 6b + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 5b + mov r2, r0 + + DEC (@(NWAITERS,r8), r2) + bra 7b + nop - mov r0, r8 +4: + neg r0, r0 + mov r0, r4 + DEC (@(NWAITERS,r8), r2) + mov r4, r8 mova .Lgot0, r0 mov.l .Lgot0, r12 add r0, r12 @@ -118,36 +147,9 @@ __new_sem_wait: .Lerrloc0b: mov.l r8, @r0 #endif - mov #-1, r0 -9: - lds.l @r15+, pr - mov.l @r15+, r12 - mov.l @r15+, r10 - rts - mov.l @r15+, r8 -5: - /* Canceled. */ - stc gbr, r0 - mov.w .Lresult, r1 - mov #-1, r2 - mov.l r2, @(r0,r1) - mov.w .Lchand, r0 - or.b #0x10, @(r0,gbr) - stc gbr, r0 - mov.w .Lclbuf, r1 - mov.l .Lunwind, r2 - braf r2 - mov.l @(r0,r1), r4 -.Lunwindb: - cfi_endproc - -.Lchand: - .word CANCELHANDLING - TLS_PRE_TCB_SIZE -.Lresult: - .word RESULT - TLS_PRE_TCB_SIZE -.Lclbuf: - .word CLEANUP_JMP_BUF - TLS_PRE_TCB_SIZE - .align 2 + bra 9b + mov #-1, r0 + .Lgot0: .long _GLOBAL_OFFSET_TABLE_ #if USE___THREAD @@ -161,7 +163,143 @@ __new_sem_wait: .long __pthread_enable_asynccancel-.Lenable0b .Ldisable0: .long __pthread_disable_asynccancel-.Ldisable0b -.Lunwind: - .long HIDDEN_JUMPTARGET (__pthread_unwind)-.Lunwindb .size __new_sem_wait,.-__new_sem_wait versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + DEC (@(NWAITERS,r8), r2) +.LcallUR: + mov.l .Lresume, r1 +#ifdef PIC + add r12, r1 +#endif + jsr @r1 + nop + sleep + + .align 2 +.Lresume: +#ifdef PIC + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x01 ! call-site format + ! DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 4 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0x88 ! DW_CFA_offset r8 + .uleb128 1 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r10-.Lpush_r8 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x8a ! DW_CFA_offset r10 + .uleb128 2 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r12-.Lpush_r10 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x8c ! DW_CFA_offset r12 + .uleb128 3 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x91 ! DW_CFA_offset pr + .uleb128 4 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h index 5013922a2f..922e3c21d3 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -35,37 +35,66 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 + + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + /* 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; \ - }) +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) -#define lll_futex_timed_wait(futexp, val, timespec) \ +#define lll_futex_timed_wait(futexp, val, timespec, private) \ ({ \ 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), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ __ret; \ }) -#define lll_futex_wake(futexp, nr) \ +#define lll_futex_wake(futexp, nr, private) \ ({ \ 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), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ __ret; \ }) @@ -86,7 +115,7 @@ { \ int *__futexp = &(futexv); \ atomic_or (__futexp, FUTEX_OWNER_DIED); \ - lll_futex_wake (__futexp, 1); \ + lll_futex_wake (__futexp, 1, LLL_SHARED); \ } \ while (0) @@ -212,7 +241,7 @@ __lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime, int *__futex = &(lock); \ int __val = atomic_exchange_24_rel (__futex, 0); \ if (__builtin_expect (__val > 1, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_robust_mutex_unlock(lock) \ @@ -220,14 +249,14 @@ __lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime, int *__futex = &(lock); \ int __val = atomic_exchange_rel (__futex, 0); \ if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_mutex_unlock_force(lock) \ ((void) ({ \ int *__futex = &(lock); \ (void) atomic_exchange_24_rel (__futex, 0); \ - lll_futex_wake (__futex, 1); \ + lll_futex_wake (__futex, 1, LLL_SHARED); \ })) #define lll_mutex_islocked(futex) \ @@ -240,8 +269,6 @@ __lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime, /* 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) @@ -257,12 +284,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, LLL_SHARED); \ + } \ while (0) extern int __lll_timedwait_tid (int *, const struct timespec *) diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c index 3b07cc127d..22e2dd3c0c 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* 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. @@ -30,7 +30,7 @@ clear_once_control (void *arg) pthread_once_t *once_control = (pthread_once_t *) arg; *once_control = 0; - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); } @@ -65,7 +65,7 @@ __pthread_once (once_control, init_routine) if (((oldval ^ newval) & -4) == 0) { /* Same generation, some other thread was faster. Wait. */ - lll_futex_wait (once_control, newval); + lll_futex_wait (once_control, newval, LLL_PRIVATE); continue; } } @@ -84,7 +84,7 @@ __pthread_once (once_control, init_routine) atomic_increment (once_control); /* Wake up all other threads. */ - lll_futex_wake (once_control, INT_MAX); + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); break; } diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c index a7611d6a88..cb9578b47b 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c @@ -1,5 +1,5 @@ /* low level locking for pthread library. 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. @@ -76,21 +76,9 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime) } -/* These don't get included in libc.so */ +/* This function doesn't get included in libc.so */ #ifdef IS_IN_libpthread int -lll_unlock_wake_cb (int *futex) -{ - int val = atomic_exchange_24_rel (futex, 0); - - if (__builtin_expect (val > 1, 0)) - lll_futex_wake (futex, 1); - - return 0; -} - - -int __lll_timedwait_tid (int *tidp, const struct timespec *abstime) { int tid; @@ -127,5 +115,4 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime) return 0; } - #endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c index 4dfd11dcbe..868e0d2819 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. @@ -52,7 +52,9 @@ pthread_barrier_wait (barrier) ++ibarrier->b.curr_event; /* Wake up everybody. */ - lll_futex_wake (&ibarrier->b.curr_event, INT_MAX); + lll_futex_wake (&ibarrier->b.curr_event, INT_MAX, + // XYZ check mutex flag + LLL_SHARED); /* This is the thread which finished the serialization. */ result = PTHREAD_BARRIER_SERIAL_THREAD; @@ -68,7 +70,9 @@ pthread_barrier_wait (barrier) /* Wait for the event counter of the barrier to change. */ do - lll_futex_wait (&ibarrier->b.curr_event, event); + lll_futex_wait (&ibarrier->b.curr_event, event, + // XYZ check mutex flag + LLL_SHARED); while (event == ibarrier->b.curr_event); } 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 be1cc60b11..527aedfdc7 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c @@ -1,5 +1,5 @@ /* sem_post -- post to a POSIX semaphore. SPARC version. - Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -39,7 +39,9 @@ __new_sem_post (sem_t *sem) nr = ++*futex; __sparc32_atomic_do_unlock24 (futex + 1); } - int err = lll_futex_wake (futex, nr); + int err = lll_futex_wake (futex, nr, + // XYZ check mutex flag + LLL_SHARED); if (__builtin_expect (err, 0) < 0) { __set_errno (-err); diff --git a/nptl/sysdeps/unix/sysv/linux/structsem.sym b/nptl/sysdeps/unix/sysv/linux/structsem.sym new file mode 100644 index 0000000000..4f32c68da5 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/structsem.sym @@ -0,0 +1,10 @@ +#include <stddef.h> +#include <sched.h> +#include <bits/pthreadtypes.h> +#include "internaltypes.h" + +-- + +VALUE offsetof (struct new_sem, value) +PRIVATE offsetof (struct new_sem, private) +NWAITERS offsetof (struct new_sem, nwaiters) diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c index 964f5b7094..bc5b7537a3 100644 --- a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c +++ b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -104,7 +104,7 @@ __unregister_atfork (dso_handle) atomic_decrement (&deleted->handler->refcntr); unsigned int val; while ((val = deleted->handler->refcntr) != 0) - lll_futex_wait (&deleted->handler->refcntr, val); + lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE); deleted = deleted->next; } diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h index 693387a266..7a09c81194 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -159,9 +159,9 @@ typedef union unsigned int __nr_readers_queued; unsigned int __nr_writers_queued; int __writer; - int __pad1; + int __shared; + unsigned long int __pad1; unsigned long int __pad2; - unsigned long int __pad3; /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ unsigned int __flags; @@ -177,7 +177,10 @@ typedef union unsigned int __nr_writers_queued; /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ - unsigned int __flags; + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; int __writer; } __data; # endif diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S index 3621efa4fc..3265eee0ed 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,14 +17,19 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* In libc.so we do not unconditionally use the lock prefix. Only if - the application is using threads. */ -#ifndef UP -# define LOCK \ - cmpl $0, __libc_multiple_threads(%rip); \ - je 0f; \ - lock; \ -0: +#include <kernel-features.h> + +/* All locks in libc are private. Use the kernel feature if possible. */ +#define FUTEX_PRIVATE_FLAG 128 +#ifdef __ASSUME_PRIVATE_FUTEX +# define FUTEX_WAIT (0 | FUTEX_PRIVATE_FLAG) +# define FUTEX_WAKE (1 | FUTEX_PRIVATE_FLAG) +#else +# define LOAD_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg +# define LOAD_FUTEX_WAKE(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg #endif #include "lowlevellock.S" diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S index 6724ded762..502f1d442f 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -31,8 +31,23 @@ #endif #define SYS_futex 202 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 +#ifndef FUTEX_WAIT +# define FUTEX_WAIT 0 +# define FUTEX_WAKE 1 +#endif + +#ifndef LOAD_FUTEX_WAIT +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl reg, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + movl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAKE(reg) \ + movl $FUTEX_WAKE, reg +#endif + /* For the calculation see asm/vsyscall.h. */ #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 @@ -52,11 +67,7 @@ __lll_mutex_lock_wait: cfi_offset(%rdx, -24) xorq %r10, %r10 /* No timeout. */ movl $2, %edx -#if FUTEX_WAIT == 0 - xorl %esi, %esi -#else - movl $FUTEX_WAIT, %esi -#endif + LOAD_FUTEX_WAIT (%esi) cmpl %edx, %eax /* NB: %edx == 2 */ jne 2f @@ -151,11 +162,7 @@ __lll_mutex_timedlock_wait: je 8f movq %rsp, %r10 -#if FUTEX_WAIT == 0 - xorl %esi, %esi -#else - movl $FUTEX_WAIT, %esi -#endif + LOAD_FUTEX_WAIT (%esi) movq %r12, %rdi movl $SYS_futex, %eax syscall @@ -213,26 +220,6 @@ __lll_mutex_timedlock_wait: #endif -#ifdef NOT_IN_libc - .globl lll_unlock_wake_cb - .type lll_unlock_wake_cb,@function - .hidden lll_unlock_wake_cb - .align 16 -lll_unlock_wake_cb: - pushq %rsi - pushq %rdx - - LOCK - addl $1, (%rdi) - jng 1f - - popq %rdx - popq %rsi - retq - .size lll_unlock_wake_cb,.-lll_unlock_wake_cb -#endif - - .globl __lll_mutex_unlock_wake .type __lll_mutex_unlock_wake,@function .hidden __lll_mutex_unlock_wake @@ -247,7 +234,7 @@ __lll_mutex_unlock_wake: cfi_offset(%rdx, -24) movl $0, (%rdi) - movl $FUTEX_WAKE, %esi + LOAD_FUTEX_WAKE (%esi) movl $1, %edx /* Wake one thread. */ movl $SYS_futex, %eax syscall @@ -311,6 +298,8 @@ __lll_timedwait_tid: jz 4f movq %rsp, %r10 + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ #if FUTEX_WAIT == 0 xorl %esi, %esi #else diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index bb988f3b2b..7ec7deff17 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -23,6 +23,8 @@ #include <time.h> #include <sys/param.h> #include <bits/pthreadtypes.h> +#include <kernel-features.h> +#include <tcb-offsets.h> #ifndef LOCK_INSTR # ifdef UP @@ -39,8 +41,41 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG); \ + asm ("andl %%fs:%P1, %0" : "+r" (__fl) \ + : "i" (offsetof (struct pthread, header.private_futex))); \ + __fl | (fl); })) +# endif +#endif + /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED (1) @@ -148,46 +183,39 @@ LLL_STUB_UNWIND_INFO_START \ LLL_STUB_UNWIND_INFO_END -#define lll_futex_wait(futex, val) \ - ({ \ - int __status; \ - register __typeof (val) _val __asm ("edx") = (val); \ - __asm __volatile ("xorq %%r10, %%r10\n\t" \ - "syscall" \ - : "=a" (__status) \ - : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT), \ - "d" (_val) \ - : "memory", "cc", "r10", "r11", "cx"); \ - __status; \ - }) +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait(futex, val, NULL, private) -#define lll_futex_timed_wait(futex, val, timeout) \ +#define lll_futex_timed_wait(futex, val, timeout, private) \ ({ \ register const struct timespec *__to __asm ("r10") = timeout; \ int __status; \ register __typeof (val) _val __asm ("edx") = (val); \ __asm __volatile ("syscall" \ : "=a" (__status) \ - : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT), \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAIT, private)), \ "d" (_val), "r" (__to) \ : "memory", "cc", "r11", "cx"); \ __status; \ }) -#define lll_futex_wake(futex, nr) \ +#define lll_futex_wake(futex, nr, private) \ do { \ int __ignore; \ register __typeof (nr) _nr __asm ("edx") = (nr); \ __asm __volatile ("syscall" \ : "=a" (__ignore) \ - : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAKE), \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAKE, private)), \ "d" (_nr) \ : "memory", "cc", "r10", "r11", "cx"); \ } while (0) + /* Does not preserve %eax and %ecx. */ extern int __lll_mutex_lock_wait (int *__futex, int __val) attribute_hidden; /* Does not preserver %eax, %ecx, and %edx. */ @@ -454,9 +482,6 @@ typedef int lll_lock_t; #define LLL_LOCK_INITIALIZER_LOCKED (1) -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; - - /* The states of a lock are: 0 - untaken 1 - taken by one user diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S index fa8125dd87..63771b3840 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -65,9 +65,10 @@ pthread_barrier_wait: if the CURR_EVENT memory has meanwhile been changed. */ 7: #if FUTEX_WAIT == 0 - xorl %esi, %esi + movl PRIVATE(%rdi), %esi #else movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi #endif xorq %r10, %r10 8: movl $SYS_futex, %eax @@ -116,6 +117,7 @@ pthread_barrier_wait: so 0x7fffffff is the highest value. */ movl $0x7fffffff, %edx movl $FUTEX_WAKE, %esi + orl PRIVATE(%rdi), %esi movl $SYS_futex, %eax syscall diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S index ad3ae1e76e..2afd601b8c 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -111,7 +111,7 @@ __pthread_cond_timedwait: movq 8(%rsp), %rdi incq total_seq(%rdi) incl cond_futex(%rdi) - addl $(1 << clock_bits), cond_nwaiters(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) /* Install cancellation handler. */ #ifdef PIC @@ -137,7 +137,7 @@ __pthread_cond_timedwait: structure stores the number minus 1. */ movq 8(%rsp), %rdi movl cond_nwaiters(%rdi), %edi - andl $((1 << clock_bits) - 1), %edi + andl $((1 << nwaiters_shift) - 1), %edi /* Only clocks 0 and 1 are allowed so far. Both are handled in the kernel. */ leaq 24(%rsp), %rsi @@ -250,13 +250,13 @@ __pthread_cond_timedwait: 9: xorq %r14, %r14 14: incq woken_seq(%rdi) -24: subl $(1 << clock_bits), cond_nwaiters(%rdi) +24: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) /* Wake up a thread which wants to destroy the condvar object. */ cmpq $0xffffffffffffffff, total_seq(%rdi) jne 25f movl cond_nwaiters(%rdi), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 25f addq $cond_nwaiters, %rdi diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S index 969e80da2a..aaad22e020 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -77,14 +77,14 @@ __condvar_cleanup: incl cond_futex(%rdi) 6: incq woken_seq(%rdi) -3: subl $(1 << clock_bits), cond_nwaiters(%rdi) +3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) /* Wake up a thread which wants to destroy the condvar object. */ xorq %r12, %r12 cmpq $0xffffffffffffffff, total_seq(%rdi) jne 4f movl cond_nwaiters(%rdi), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 4f addq $cond_nwaiters, %rdi @@ -185,7 +185,7 @@ __pthread_cond_wait: movq 8(%rsp), %rdi incq total_seq(%rdi) incl cond_futex(%rdi) - addl $(1 << clock_bits), cond_nwaiters(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) /* Install cancellation handler. */ #ifdef PIC @@ -262,13 +262,13 @@ __pthread_cond_wait: incq woken_seq(%rdi) /* Unlock */ -16: subl $(1 << clock_bits), cond_nwaiters(%rdi) +16: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) /* Wake up a thread which wants to destroy the condvar object. */ cmpq $0xffffffffffffffff, total_seq(%rdi) jne 17f movl cond_nwaiters(%rdi), %eax - andl $~((1 << clock_bits) - 1), %eax + andl $~((1 << nwaiters_shift) - 1), %eax jne 17f addq $cond_nwaiters, %rdi diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S index 9db5516913..7740c599d1 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,14 +17,19 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <kernel-features.h> +#include <tcb-offsets.h> + #ifndef UP # define LOCK lock #else # define LOCK #endif -#define SYS_futex 202 -#define FUTEX_WAKE 1 +#define SYS_futex 202 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .comm __fork_generation, 4, 4 @@ -74,10 +79,15 @@ __pthread_once: jnz 3f /* Different for generation -> run initializer. */ /* Somebody else got here first. Wait. */ -#if FUTEX_WAIT == 0 - xorl %esi, %esi +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi #else +# if FUTEX_WAIT == 0 + movl %fs:PRIVATE_FUTEX, %esi +# else movl $FUTEX_WAIT, %esi + orl %fs:PRIVATE_FUTEX, %esi +# endif #endif movl $SYS_futex, %eax syscall @@ -106,7 +116,12 @@ __pthread_once: /* Wake up all other threads. */ movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +#else movl $FUTEX_WAKE, %esi + orl %fs:PRIVATE_FUTEX, %esi +#endif movl $SYS_futex, %eax syscall @@ -133,7 +148,12 @@ clear_once_control: movl $0, (%rdi) movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +#else movl $FUTEX_WAKE, %esi + orl %fs:PRIVATE_FUTEX, %esi +#endif movl $SYS_futex, %eax syscall diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S index 5e9d8fb1d6..e8d257502f 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,11 +20,13 @@ #include <sysdep.h> #include <lowlevelrwlock.h> #include <pthread-errnos.h> +#include <kernel-features.h> #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 #ifndef UP # define LOCK lock @@ -73,12 +75,20 @@ __pthread_rwlock_rdlock: #endif jne 10f -11: addq $READERS_WAKEUP, %rdi -#if FUTEX_WAIT == 0 - xorl %esi, %esi +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%rdi), %esi #else +# if FUTEX_WAIT == 0 + movl PSHARED(%rdi), %esi +# else movl $FUTEX_WAIT, %esi + orl PSHARED(%rdi), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi #endif + addq $READERS_WAKEUP, %rdi movl $SYS_futex, %eax syscall diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S index b44660418a..f703eeb29f 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,11 +20,13 @@ #include <sysdep.h> #include <lowlevelrwlock.h> #include <pthread-errnos.h> +#include <kernel-features.h> #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 /* For the calculation see asm/vsyscall.h. */ #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 @@ -112,10 +114,17 @@ pthread_rwlock_timedrdlock: movq %rcx, (%rsp) /* Store relative timeout. */ movq %rdi, 8(%rsp) -#if FUTEX_WAIT == 0 - xorl %esi, %esi +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%r12), %esi #else +# if FUTEX_WAIT == 0 + movl PSHARED(%r12), %esi +# else movl $FUTEX_WAIT, %esi + orl PSHARED(%r12), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi #endif movq %rsp, %r10 movl %r14d, %edx diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S index 525e5b6b93..fc3bf3d69e 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,11 +20,13 @@ #include <sysdep.h> #include <lowlevelrwlock.h> #include <pthread-errnos.h> +#include <kernel-features.h> #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 /* For the calculation see asm/vsyscall.h. */ #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 @@ -108,10 +110,17 @@ pthread_rwlock_timedwrlock: movq %rcx, (%rsp) /* Store relative timeout. */ movq %rdi, 8(%rsp) -#if FUTEX_WAIT == 0 - xorl %esi, %esi +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%r12), %esi #else +# if FUTEX_WAIT == 0 + movl PSHARED(%r12), %esi +# else movl $FUTEX_WAIT, %esi + orl PSHARED(%r12), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi #endif movq %rsp, %r10 movl %r14d, %edx diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S index 3a6b9f0bad..c4597f60f7 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -19,11 +19,13 @@ #include <sysdep.h> #include <lowlevelrwlock.h> +#include <kernel-features.h> #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 #ifndef UP # define LOCK lock @@ -56,9 +58,8 @@ __pthread_rwlock_unlock: 5: movl $0, WRITER(%rdi) - movl $1, %esi + movl $1, %edx leaq WRITERS_WAKEUP(%rdi), %r10 - movq %rsi, %rdx cmpl $0, WRITERS_QUEUED(%rdi) jne 0f @@ -78,7 +79,16 @@ __pthread_rwlock_unlock: #endif jne 7f -8: movl $SYS_futex, %eax +8: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %esi + xorl PSHARED(%rdi), %esi +#else + movl $FUTEX_WAKE, %esi + orl PSHARED(%rdi), %esi + xorl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax movq %r10, %rdi syscall diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S index 0e82f890aa..7f65726849 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,11 +20,13 @@ #include <sysdep.h> #include <lowlevelrwlock.h> #include <pthread-errnos.h> +#include <kernel-features.h> #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 #ifndef UP # define LOCK lock @@ -71,12 +73,20 @@ __pthread_rwlock_wrlock: #endif jne 10f -11: addq $WRITERS_WAKEUP, %rdi -#if FUTEX_WAIT == 0 - xorl %esi, %esi +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%rdi), %esi #else +# if FUTEX_WAIT == 0 + movl PSHARED(%rdi), %esi +# else movl $FUTEX_WAIT, %esi + orl PSHARED(%rdi), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi #endif + addq $WRITERS_WAKEUP, %rdi movl $SYS_futex, %eax syscall diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S index 7f608a5974..4919c11fd2 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,6 +20,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #ifndef UP # define LOCK lock @@ -37,19 +38,26 @@ .type sem_post,@function .align 16 sem_post: - movl $1, %edx LOCK - xaddl %edx, (%rdi) +#if VALUE == 0 + addl $1, (%rdi) +#else + addl $1, VALUE(%rdi) +#endif + + cmpq $0, NWAITERS(%rdi) + je 2f movl $SYS_futex, %eax movl $FUTEX_WAKE, %esi - incl %edx + orl PRIVATE(%rdi), %esi + movl $1, %edx syscall testq %rax, %rax js 1f - xorl %eax, %eax +2: xorl %eax, %eax retq 1: diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S index 8c5c2a6974..4068a1b6b8 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -20,6 +20,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #ifndef UP # define LOCK lock @@ -28,6 +29,7 @@ #endif #define SYS_futex 202 +#define FUTEX_WAIT 0 /* For the calculation see asm/vsyscall.h. */ #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 @@ -38,15 +40,23 @@ .globl sem_timedwait .type sem_timedwait,@function .align 16 - cfi_startproc sem_timedwait: +.LSTARTCODE: +#if VALUE == 0 movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif 2: testl %eax, %eax je 1f leaq -1(%rax), %rdx LOCK +#if VALUE == 0 cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif jne 2b xorl %eax, %eax @@ -54,25 +64,25 @@ sem_timedwait: /* Check whether the timeout value is valid. */ 1: pushq %r12 - cfi_adjust_cfa_offset(8) +.Lpush_r12: pushq %r13 - cfi_adjust_cfa_offset(8) +.Lpush_r13: pushq %r14 - cfi_adjust_cfa_offset(8) +.Lpush_r14: subq $24, %rsp - cfi_adjust_cfa_offset(24) +.Lsubq: movq %rdi, %r12 - cfi_offset(12, -16) /* %r12 */ movq %rsi, %r13 - cfi_offset(13, -24) /* %r13 */ /* Check for invalid nanosecond field. */ cmpq $1000000000, 8(%r13) movl $EINVAL, %r14d - cfi_offset(14, -24) /* %r14 */ jae 6f + LOCK + addq $1, NWAITERS(%r12) + 7: xorl %esi, %esi movq %rsp, %rdi movq $VSYSCALL_ADDR_vgettimeofday, %rax @@ -96,12 +106,22 @@ sem_timedwait: movq %rdi, (%rsp) /* Store relative timeout. */ movq %rsi, 8(%rsp) +.LcleanupSTART: call __pthread_enable_asynccancel movl %eax, 16(%rsp) movq %rsp, %r10 +#if VALUE == 0 movq %r12, %rdi - xorl %esi, %esi +#else + leaq VALUE(%r12), %rdi +#endif +#if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +#else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +#endif movl $SYS_futex, %eax xorl %edx, %edx syscall @@ -109,39 +129,47 @@ sem_timedwait: movl 16(%rsp), %edi call __pthread_disable_asynccancel +.LcleanupEND: testq %r14, %r14 je 9f cmpq $-EWOULDBLOCK, %r14 jne 3f -9: movl (%r12), %eax +9: +#if VALUE == 0 + movl (%r12), %eax +#else + movl VALUE(%r12), %eax +#endif 8: testl %eax, %eax je 7b leaq -1(%rax), %rcx LOCK +#if VALUE == 0 cmpxchgl %ecx, (%r12) +#else + cmpxchgl %ecx, VALUE(%r12) +#endif jne 8b xorl %eax, %eax -10: addq $24, %rsp - cfi_adjust_cfa_offset(-24) + +10: LOCK + subq $1, NWAITERS(%r12) + + addq $24, %rsp +.Laddq: popq %r14 - cfi_adjust_cfa_offset(-8) - cfi_restore(14) +.Lpop_r14: popq %r13 - cfi_adjust_cfa_offset(-8) - cfi_restore(13) +.Lpop_r13: popq %r12 - cfi_adjust_cfa_offset(-8) - cfi_restore(12) +.Lpop_r12: retq - cfi_adjust_cfa_offset(48) - cfi_offset(12, -16) /* %r12 */ - cfi_offset(13, -24) /* %r13 */ - cfi_offset(14, -32) /* %r14 */ +.Lafter_retq: 3: negq %r14 6: #if USE___THREAD @@ -154,5 +182,159 @@ sem_timedwait: orl $-1, %eax jmp 10b - cfi_endproc .size sem_timedwait,.-sem_timedwait + + + .type sem_timedwait_cleanup,@function +sem_timedwait_cleanup: + LOCK + subq $1, NWAITERS(%r12) + movq %rax, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_timedwait_cleanup,.-sem_timedwait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_timedwait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -8 # Data alignment factor. + .byte 16 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 10 # Augmentation value length. + .byte 0x0 # Personality: absolute + .quad __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 7 + .uleb128 8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 8 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size + .long .LexceptSTART-. +#else + .quad .LSTARTCODE # Start address of the code. + .quad .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 8 # Augmentation size + .quad .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_r12-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x8c # DW_CFA_offset %r12 + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_r13-.Lpush_r12 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 24 + .byte 0x8d # DW_CFA_offset %r13 + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_r14-.Lpush_r13 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 32 + .byte 0x8e # DW_CFA_offset %r14 + .uleb128 4 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsubq-.Lpush_r14 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 56 + .byte 4 # DW_CFA_advance_loc4 + .long .Laddq-.Lsubq + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 32 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_r14-.Laddq + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 24 + .byte 0xce # DW_CFA_restore %r14 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_r13-.Lpop_r14 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0xcd # DW_CFA_restore %r13 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_r12-.Lpop_r13 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0xcc # DW_CFA_restore %r12 + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_retq-.Lpop_r12 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 56 + .byte 0x8c # DW_CFA_offset %r12 + .uleb128 2 + .byte 0x8d # DW_CFA_offset %r13 + .uleb128 3 + .byte 0x8e # DW_CFA_offset %r14 + .uleb128 4 + .align 8 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S index 6b77dfc0d8..643090f065 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -37,7 +37,7 @@ sem_trywait: 2: testl %eax, %eax jz 1f - leaq -1(%rax), %rdx + leal -1(%rax), %edx LOCK cmpxchgl %edx, (%rdi) jne 2b diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S index 5bd78eb944..e099ede029 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S @@ -20,6 +20,7 @@ #include <sysdep.h> #include <shlib-compat.h> #include <pthread-errnos.h> +#include <structsem.h> #ifndef UP # define LOCK lock @@ -28,6 +29,7 @@ #endif #define SYS_futex 202 +#define FUTEX_WAIT 0 .text @@ -35,57 +37,93 @@ .globl sem_wait .type sem_wait,@function .align 16 - cfi_startproc sem_wait: +.LSTARTCODE: pushq %r12 - cfi_adjust_cfa_offset(8) - cfi_offset(12, -16) +.Lpush_r12: pushq %r13 - cfi_adjust_cfa_offset(8) +.Lpush_r13: movq %rdi, %r13 - cfi_offset(13, -24) -3: movl (%r13), %eax +#if VALUE == 0 + movl (%r13), %eax +#else + movl VALUE(%r13), %eax +#endif 2: testl %eax, %eax je 1f - leaq -1(%rax), %rdx + leal -1(%rax), %edx LOCK +#if VALUE == 0 cmpxchgl %edx, (%r13) +#else + cmpxchgl %edx, VALUE(%r13) +#endif jne 2b - xorl %eax, %eax - popq %r13 - cfi_adjust_cfa_offset(-8) - cfi_restore(13) +7: xorl %eax, %eax + +9: popq %r13 +.Lpop_r13: popq %r12 - cfi_adjust_cfa_offset(-8) - cfi_restore(12) +.Lpop_r12: retq - cfi_adjust_cfa_offset(16) - cfi_offset(12, -16) - cfi_offset(13, -24) -1: call __pthread_enable_asynccancel +.Lafter_retq: +1: LOCK + addq $1, NWAITERS(%r13) + +.LcleanupSTART: +6: call __pthread_enable_asynccancel movl %eax, %r8d xorq %r10, %r10 movl $SYS_futex, %eax movq %r13, %rdi - movq %r10, %rsi - movq %r10, %rdx +#if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +#else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +#endif + xorl %edx, %edx syscall movq %rax, %r12 movl %r8d, %edi call __pthread_disable_asynccancel +.LcleanupEND: testq %r12, %r12 - je 3b + je 3f cmpq $-EWOULDBLOCK, %r12 - je 3b - negq %r12 + jne 4f + +3: +#if VALUE == 0 + movl (%r13), %eax +#else + movl VALUE(%r13), %eax +#endif +5: testl %eax, %eax + je 6b + + leal -1(%rax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%r13) +#else + cmpxchgl %edx, VALUE(%r13) +#endif + jne 5b + + LOCK + subq $1, NWAITERS(%r13) + jmp 7b + +4: negq %r12 #if USE___THREAD movq errno@gottpoff(%rip), %rdx movl %r12d, %fs:(%rdx) @@ -95,13 +133,142 @@ sem_wait: #endif orl $-1, %eax - popq %r13 - cfi_adjust_cfa_offset(-8) - cfi_restore(13) - popq %r12 - cfi_adjust_cfa_offset(-8) - cfi_restore(12) + LOCK + subq $1, NWAITERS(%r13) - retq - cfi_endproc + jmp 9b .size sem_wait,.-sem_wait + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + LOCK + subq $1, NWAITERS(%r13) + movq %rax, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -8 # Data alignment factor. + .byte 16 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 10 # Augmentation value length. + .byte 0x0 # Personality: absolute + .quad __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 7 + .uleb128 8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 8 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size + .long .LexceptSTART-. +#else + .quad .LSTARTCODE # Start address of the code. + .quad .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 8 # Augmentation size + .quad .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_r12-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x8c # DW_CFA_offset %r12 + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_r13-.Lpush_r12 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 24 + .byte 0x8d # DW_CFA_offset %r13 + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_r13-.Lpush_r13 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0xcd # DW_CFA_restore %r13 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_r12-.Lpop_r13 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0xcc # DW_CFA_restore %r12 + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_retq-.Lpop_r12 + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 24 + .byte 0x8c # DW_CFA_offset %r12 + .uleb128 2 + .byte 0x8d # DW_CFA_offset %r13 + .uleb128 3 + .align 8 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/nptl/sysdeps/x86_64/tcb-offsets.sym b/nptl/sysdeps/x86_64/tcb-offsets.sym index 21274ecab9..1c70c6bde7 100644 --- a/nptl/sysdeps/x86_64/tcb-offsets.sym +++ b/nptl/sysdeps/x86_64/tcb-offsets.sym @@ -12,3 +12,6 @@ MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) POINTER_GUARD offsetof (tcbhead_t, pointer_guard) VGETCPU_CACHE_OFFSET offsetof (tcbhead_t, vgetcpu_cache) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif diff --git a/nptl/sysdeps/x86_64/tls.h b/nptl/sysdeps/x86_64/tls.h index 4a614c02af..79db61c709 100644 --- a/nptl/sysdeps/x86_64/tls.h +++ b/nptl/sysdeps/x86_64/tls.h @@ -26,6 +26,8 @@ # include <stddef.h> # include <stdint.h> # include <stdlib.h> +# include <sysdep.h> +# include <kernel-features.h> /* Type for the dtv. */ @@ -52,6 +54,9 @@ typedef struct uintptr_t stack_guard; uintptr_t pointer_guard; unsigned long int vgetcpu_cache[2]; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -350,7 +355,7 @@ typedef struct : "i" (offsetof (struct pthread, header.gscope_flag)), \ "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ - lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0) #define THREAD_GSCOPE_SET_FLAG() \ |