Extend x86-64 __lll_robust_timedlock_wait to use futex syscall with absolute timeout.
authorUlrich Drepper <drepper@redhat.com>
Sun, 19 Jul 2009 07:00:17 +0000 (00:00 -0700)
committerUlrich Drepper <drepper@redhat.com>
Sun, 19 Jul 2009 07:00:17 +0000 (00:00 -0700)
nptl/ChangeLog
nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S

index dc576a7..e9cac73 100644 (file)
@@ -1,5 +1,9 @@
 2009-07-18  Ulrich Drepper  <drepper@redhat.com>
 
+       * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
+       (__lll_robust_timedlock_wait): If possible use FUTEX_WAIT_BITSET to
+       directly use absolute timeout.
+
        * tst-sem5.c (do_test): Add test for premature timeout.
        * Makefile: Linu tst-sem5 with librt.
 
index fa7516e..02db0a4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -32,6 +32,8 @@
 #ifdef __ASSUME_PRIVATE_FUTEX
 # 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
 #else
 # if FUTEX_WAIT == 0
 #  define LOAD_FUTEX_WAIT(reg) \
        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
 #endif
 
 /* For the calculation see asm/vsyscall.h.  */
@@ -110,6 +116,73 @@ __lll_robust_lock_wait:
        .align  16
 __lll_robust_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(8)
+       cfi_rel_offset(%r9, 0)
+       movq    %rdx, %r10
+       movl    $0xffffffff, %r9d
+       LOAD_FUTEX_WAIT_ABS (%esi)
+
+1:     testl   $FUTEX_OWNER_DIED, %eax
+       jnz     3f
+
+       movl    %eax, %edx
+       orl     $FUTEX_WAITERS, %edx
+
+       cmpl    %eax, %edx
+       je      5f
+
+       LOCK
+       cmpxchgl %edx, (%rdi)
+       movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
+       jnz     6f
+
+5:     movl    $SYS_futex, %eax
+       syscall
+       movl    %eax, %ecx
+
+       movl    (%rdi), %eax
+
+6:     testl   %eax, %eax
+       jne     2f
+
+       movl    %fs:TID, %edx
+       orl     $FUTEX_WAITERS, %edx
+       LOCK
+       cmpxchgl %edx, (%rdi)
+       jnz     2f
+
+3:     popq    %r9
+       cfi_adjust_cfa_offset(-8)
+       cfi_restore(%r9)
+       retq
+
+       cfi_adjust_cfa_offset(8)
+       cfi_rel_offset(%r9, 0)
+       /* Check whether the time expired.  */
+2:     cmpl    $-ETIMEDOUT, %ecx
+       je      4f
+       cmpl    $-EINVAL, %ecx
+       jne     1b
+
+4:     movl    %ecx, %eax
+       negl    %eax
+       jmp     3b
+       cfi_adjust_cfa_offset(-8)
+       cfi_restore(%r9)
+
+
+# ifndef __ASSUME_FUTEX_CLOCK_REALTIME
+.Lreltmo:
        /* Check for a valid timeout value.  */
        cmpq    $1000000000, 8(%rdx)
        jae     3f
@@ -223,10 +296,11 @@ __lll_robust_timedlock_wait:
        cfi_offset(%r12, -32)
        cfi_offset(%r13, -40)
        /* Check whether the time expired.  */
-7:     cmpq    $-ETIMEDOUT, %rcx
+7:     cmpl    $-ETIMEDOUT, %ecx
        jne     1b
 
 8:     movl    $ETIMEDOUT, %eax
        jmp     6b
+#endif
        cfi_endproc
        .size   __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait