diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-01-03 05:06:46 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-01-03 05:06:46 +0000 |
commit | cbd8aeb836c8061c23a5e00419e0fb25a34abee7 (patch) | |
tree | 3f205876a4edffbc06a9474542dfe2a8cdcb27a4 /nptl | |
parent | 7dd650d7fc8191aa99c14602b9a44bccb276d4f8 (diff) | |
download | glibc-cbd8aeb836c8061c23a5e00419e0fb25a34abee7.tar glibc-cbd8aeb836c8061c23a5e00419e0fb25a34abee7.tar.gz glibc-cbd8aeb836c8061c23a5e00419e0fb25a34abee7.tar.bz2 glibc-cbd8aeb836c8061c23a5e00419e0fb25a34abee7.zip |
* init.c (__pthread_initialize_minimal_internal): Check for
FUTEX_CLOCK_REALTIME flag.
* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_timedlock_wait):
Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_READTIME instead of computing
relative timeout.
Diffstat (limited to 'nptl')
-rw-r--r-- | nptl/ChangeLog | 6 | ||||
-rw-r--r-- | nptl/init.c | 26 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S | 58 |
3 files changed, 88 insertions, 2 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 70fc0b1e1e..ae652ff738 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,11 @@ 2009-01-02 Ulrich Drepper <drepper@redhat.com> + * init.c (__pthread_initialize_minimal_internal): Check for + FUTEX_CLOCK_REALTIME flag. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_timedlock_wait): + Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_READTIME instead of computing + relative timeout. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define FUTEX_CLOCK_REALTIME and FUTEX_BITSET_MATCH_ANY. * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. diff --git a/nptl/init.c b/nptl/init.c index d445de0795..af5bb24b59 100644 --- a/nptl/init.c +++ b/nptl/init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. +/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -18,6 +18,7 @@ 02111-1307 USA. */ #include <assert.h> +#include <errno.h> #include <limits.h> #include <signal.h> #include <stdlib.h> @@ -49,6 +50,15 @@ int __set_robust_list_avail; # define set_robust_list_not_avail() do { } while (0) #endif +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +/* Nonzero if we do not have FUTEX_CLOCK_REALTIME. */ +int __have_futex_clock_realtime; +# define __set_futex_clock_realtime() \ + __have_futex_clock_realtime = 1 +#else +#define __set_futex_clock_realtime() do { } while (0) +#endif + /* Version of the library, used in libthread_db to detect mismatches. */ static const char nptl_version[] __attribute_used__ = VERSION; @@ -292,6 +302,20 @@ __pthread_initialize_minimal_internal (void) } #endif +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + { + int word = 0; + word = INTERNAL_SYSCALL (futex, err, 6, &word, + FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME + | FUTEX_PRIVATE_FLAG, 1, NULL, 0, + FUTEX_BITSET_MATCH_ANY); + if (!INTERNAL_SYSCALL_ERROR_P (word, err) + || (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS + && INTERNAL_SYSCALL_ERRNO (word, err) != EINVAL)) + __set_futex_clock_realtime (); + } +#endif + /* Set initial thread's stack block from 0 up to __libc_stack_end. It will be bigger than it actually is, but for unwind.c/pt-longjmp.c purposes this is good enough. */ diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S index 4505e2cec6..72c3858238 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002-2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2002-2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -31,6 +31,8 @@ movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg # define LOAD_FUTEX_WAIT(reg) \ xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg # define LOAD_FUTEX_WAKE(reg) \ xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg #else @@ -55,6 +57,10 @@ andl %fs:PRIVATE_FUTEX, reg ; \ orl $FUTEX_WAIT, reg # endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg # define LOAD_FUTEX_WAKE(reg) \ xorl $FUTEX_PRIVATE_FLAG, reg ; \ andl %fs:PRIVATE_FUTEX, reg ; \ @@ -143,12 +149,61 @@ __lll_lock_wait: cfi_endproc .size __lll_lock_wait,.-__lll_lock_wait + /* %rdi: futex + %rsi: flags + %rdx: timeout + %eax: futex value + */ .globl __lll_timedlock_wait .type __lll_timedlock_wait,@function .hidden __lll_timedlock_wait .align 16 __lll_timedlock_wait: cfi_startproc +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef PIC + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + pushq %r9 + cfi_adjust_cfa_offset(9) + cfi_offset(%r9, -16) + movq %rdx, %r10 + movl $0xffffffff, %r9d + LOAD_FUTEX_WAIT_ABS (%esi) + + movl $2, %edx + cmpl %edx, %eax + jne 2f + +1: movl $SYS_futex, %eax + movl $2, %edx + syscall + +2: xchgl %edx, (%rdi) /* NB: lock is implied */ + + testl %edx, %edx + jz 3f + + cmpl $-ETIMEDOUT, %eax + je 4f + cmpl $-EINVAL, %eax + jne 1b +4: movl %eax, %edx + negl %edx + +3: movl %edx, %eax + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + retq + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: /* Check for a valid timeout value. */ cmpq $1000000000, 8(%rdx) jae 3f @@ -253,6 +308,7 @@ __lll_timedlock_wait: 3: movl $EINVAL, %eax retq +# endif cfi_endproc .size __lll_timedlock_wait,.-__lll_timedlock_wait #endif |