summaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-01-03 05:06:46 +0000
committerUlrich Drepper <drepper@redhat.com>2009-01-03 05:06:46 +0000
commitcbd8aeb836c8061c23a5e00419e0fb25a34abee7 (patch)
tree3f205876a4edffbc06a9474542dfe2a8cdcb27a4 /nptl
parent7dd650d7fc8191aa99c14602b9a44bccb276d4f8 (diff)
* 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/ChangeLog6
-rw-r--r--nptl/init.c26
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S58
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