[BZ #5240]
authorUlrich Drepper <drepper@redhat.com>
Fri, 9 Nov 2007 09:09:07 +0000 (09:09 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 9 Nov 2007 09:09:07 +0000 (09:09 +0000)
* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait):
If we time out, try one last time to lock the futex to avoid
losing a wakeup signal.
* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise.

nptl/ChangeLog
nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
nptl/sysdeps/unix/sysv/linux/lowlevellock.c
nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S

index bcec5e9..c5019e4 100644 (file)
@@ -1,5 +1,12 @@
 2007-11-08  Ulrich Drepper  <drepper@redhat.com>
 
+       [BZ #5240]
+       * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait):
+       If we time out, try one last time to lock the futex to avoid
+       losing a wakeup signal.
+       * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise.
+       * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise.
+
        [BZ #5245]
        * sysdeps/pthread/createthread.c (do_clone): Translate clone error
        if necessary.
index 745ab91..6d3943b 100644 (file)
@@ -203,7 +203,7 @@ __lll_timedlock_wait:
        addl    $1000000000, %edx
        subl    $1, %ecx
 4:     testl   %ecx, %ecx
-       js      5f              /* Time is already up.  */
+       js      9f              /* Time is already up.  */
 
        /* Store relative timeout.  */
        movl    %ecx, (%esp)
@@ -271,6 +271,10 @@ __lll_timedlock_wait:
 
 5:     movl    $ETIMEDOUT, %eax
        jmp     6b
+
+9:     movl    $-ETIMEDOUT, %ecx
+       movl    $2, %edx
+       jmp     8b
        cfi_endproc
        .size   __lll_timedlock_wait,.-__lll_timedlock_wait
 #endif
index f0e4295..c2cdf3a 100644 (file)
@@ -59,10 +59,10 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
     return EINVAL;
 
+  struct timespec rt;
   do
     {
       struct timeval tv;
-      struct timespec rt;
 
       /* Get the current time.  */
       (void) __gettimeofday (&tv, NULL);
@@ -76,18 +76,21 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
          --rt.tv_sec;
        }
 
-      /* Already timed out?  */
-      if (rt.tv_sec < 0)
-       return ETIMEDOUT;
+      /* If timed out do not go to sleep.  */
+      if (__builtin_expect (rt.tv_sec >= 0, 1))
+       {
+         /* Wait.  */
+         int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
+         if (oldval != 0)
+           lll_futex_timed_wait (futex, 2, &rt, private);
+       }
 
-      /* Wait.  */
-      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
-      if (oldval != 0)
-       lll_futex_timed_wait (futex, 2, &rt, private);
+      if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) == 0)
+       return 0;
     }
-  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
+  while (rt.tv_sec >= 0);
 
-  return 0;
+  return ETIMEDOUT;
 }
 
 
index 7065cfa..a5ad88c 100644 (file)
@@ -199,14 +199,16 @@ __lll_timedlock_wait:
        addq    $1000000000, %rsi
        decq    %rdi
 4:     testq   %rdi, %rdi
-       js      5f              /* Time is already up.  */
+       movq    $-ETIMEDOUT, %rcx
+       movl    $2, %edx
+       js      8f              /* Time is already up.  */
 
        /* Futex call.  */
        movq    %rdi, (%rsp)    /* Store relative timeout.  */
        movq    %rsi, 8(%rsp)
 
        movl    $1, %eax
-       movl    $2, %edx
+                               /* NB: $edx has been loaded early.  */
        LOCK
        cmpxchgl %edx, (%r12)