]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_WAKE_OP,
authorJakub Jelinek <jakub@redhat.com>
Mon, 29 Aug 2005 19:34:43 +0000 (19:34 +0000)
committerJakub Jelinek <jakub@redhat.com>
Mon, 29 Aug 2005 19:34:43 +0000 (19:34 +0000)
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(lll_futex_wake_unlock): Define.
* sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_WAKE_OP,
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(lll_futex_wake_unlock): Define.
* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_WAKE_OP,
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(lll_futex_wake_unlock): Define.
* sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_WAKE_OP,
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(lll_futex_wake_unlock): Define.
* sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_WAKE_OP,
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(lll_futex_wake_unlock): Define.
* sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): Use
lll_futex_wake_unlock.
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
(FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(__pthread_cond_signal): Use FUTEX_WAKE_OP.
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
(FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
(__pthread_cond_signal): Use FUTEX_WAKE_OP.

nptl/ChangeLog
nptl/sysdeps/pthread/pthread_cond_signal.c
nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S

index b6d66d87bb64104c6b8e56b04472c8289705d484..d728d923161dcfb98eb237e7ab8be2154c0f47e6 100644 (file)
@@ -1,3 +1,29 @@
+2005-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_WAKE_OP,
+       FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (lll_futex_wake_unlock): Define.
+       * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_WAKE_OP,
+       FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (lll_futex_wake_unlock): Define.
+       * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_WAKE_OP,
+       FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (lll_futex_wake_unlock): Define.
+       * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_WAKE_OP,
+       FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (lll_futex_wake_unlock): Define.
+       * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_WAKE_OP,
+       FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (lll_futex_wake_unlock): Define.
+       * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): Use
+       lll_futex_wake_unlock.
+       * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
+       (FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (__pthread_cond_signal): Use FUTEX_WAKE_OP.
+       * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
+       (FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define.
+       (__pthread_cond_signal): Use FUTEX_WAKE_OP.
+
 2005-08-23  Ulrich Drepper  <drepper@redhat.com>
 
        * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread):
index f5623480f8bc7000852af1151e4fc90b23cb0132..5a9bbcad914de47c729cb999afea91bddf57d008 100644 (file)
@@ -43,6 +43,11 @@ __pthread_cond_signal (cond)
       ++cond->__data.__futex;
 
       /* Wake one.  */
+      if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, 1,
+                                                    1, &cond->__data.__lock),
+                                                    0))
+       return 0;
+
       lll_futex_wake (&cond->__data.__futex, 1);
     }
 
index fd4a7ca4bb4feab5d4ae30498acce3ce46d76a43..ab325d2b061c926175b1ec768fa7deb2ae48748c 100644 (file)
@@ -31,6 +31,8 @@
 #define FUTEX_WAKE             1
 #define FUTEX_REQUEUE          3
 #define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 /* Initializer for compatibility lock. */
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                 \
   })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,                               \
+                             (futexp), FUTEX_WAKE_OP, (nr_wake),             \
+                             (nr_wake2), (futexp2),                          \
+                             FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                 \
+  })
+
+
+
 
 static inline int __attribute__((always_inline))
 __lll_mutex_trylock(int *futex)
index 3c5a1db59cbc8ae1dd2947b13ee6eea0cc60a0bc..d0f931ff15bf835417eba87ef8ea62bd5ea3c544 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -31,7 +31,9 @@
 #define SYS_futex              240
 #define FUTEX_WAIT             0
 #define FUTEX_WAKE             1
-#define FUTEX_REQUEUE          3
+#define FUTEX_WAKE_OP          5
+
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 #define EINVAL                 22
 
@@ -79,21 +81,46 @@ __pthread_cond_signal:
        addl    $1, (%ebx)
 
        /* Wake up one thread.  */
-       movl    $FUTEX_WAKE, %ecx
+       pushl   %esi
+       pushl   %ebp
+       movl    $FUTEX_WAKE_OP, %ecx
        movl    $SYS_futex, %eax
        movl    $1, %edx
+       movl    $1, %esi
+       movl    $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp
+       /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
+          sysenter.
+       ENTER_KERNEL  */
+       int     $0x80
+       popl    %ebp
+       popl    %esi
+
+       /* For any kind of error, we try again with WAKE.
+          The general test also covers running on old kernels.  */
+       cmpl    $-4095, %eax
+       jae     7f
+
+6:     xorl    %eax, %eax
+       popl    %edi
+       popl    %ebx
+       ret
+
+7:     movl    $FUTEX_WAKE, %ecx
+       movl    $SYS_futex, %eax
+       /* %edx should be 1 already from $FUTEX_WAKE_OP syscall.
+       movl    $1, %edx  */
        ENTER_KERNEL
 
        /* Unlock.  Note that at this point %edi always points to
           cond_lock.  */
 4:     LOCK
        subl    $1, (%edi)
-       jne     5f
+       je      6b
 
-6:     xorl    %eax, %eax
-       popl    %edi
-       popl    %ebx
-       ret
+       /* Unlock in loop requires wakeup.  */
+5:     movl    %edi, %eax
+       call    __lll_mutex_unlock_wake
+       jmp     6b
 
        /* Initial locking failed.  */
 1:
@@ -105,10 +132,6 @@ __pthread_cond_signal:
        call    __lll_mutex_lock_wait
        jmp     2b
 
-       /* Unlock in loop requires wakeup.  */
-5:     movl    %edi, %eax
-       call    __lll_mutex_unlock_wake
-       jmp     6b
        .size   __pthread_cond_signal, .-__pthread_cond_signal
 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
                  GLIBC_2_3_2)
index e13358ffefca474e8c47abcf23f36de1f8c0561b..4219fe2716d48ce61cbc0340dd9e779cf8595435 100644 (file)
@@ -31,6 +31,8 @@
 #define FUTEX_WAKE             1
 #define FUTEX_REQUEUE          3
 #define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 /* Delay in spinlock loop.  */
 #define BUSY_WAIT_NOP          asm ("hint @pause")
    _r10 == -1;                                                              \
 })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(ftx, nr_wake, nr_wake2, ftx2)                 \
+({                                                                          \
+   DO_INLINE_SYSCALL(futex, 6, (long) (ftx), FUTEX_WAKE_OP,                 \
+                    (int) (nr_wake), (int) (nr_wake2), (long) (ftx2),       \
+                    FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                         \
+   _r10 == -1;                                                              \
+})
+
 
 #define __lll_mutex_trylock(futex) \
   (atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0)
index 1f2f481d6421c2d83ac7b50fdfd592958f8326ae..f9eaa11e9861e11d658e0ab84772a47112c0bc55 100644 (file)
@@ -33,6 +33,8 @@
 #define FUTEX_WAKE             1
 #define FUTEX_REQUEUE          3
 #define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 /* Initializer for compatibility lock. */
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                 \
   })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+                                                                             \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,                               \
+                             (futexp), FUTEX_WAKE_OP, (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       ""
index f4ed98a50339dfaa851d431de5f17b679ec7fef3..5f20537943ca3c4e8cecacf06e16d3fc28c30252 100644 (file)
@@ -30,6 +30,8 @@
 #define FUTEX_WAKE             1
 #define FUTEX_REQUEUE          3
 #define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 /* Initializer for compatibility lock. */
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
   })
 
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futex, nr_wake, nr_wake2, futex2) \
+  ({                                                                         \
+    register unsigned long int __r2 asm ("2") = (unsigned long int) (futex);  \
+    register unsigned long int __r3 asm ("3") = FUTEX_WAKE_OP;       \
+    register unsigned long int __r4 asm ("4") = (long int) (nr_wake);        \
+    register unsigned long int __r5 asm ("5") = (long int) (nr_wake2);       \
+    register unsigned long int __r6 asm ("6") = (unsigned long int) (futex2); \
+    register unsigned long int __r7 asm ("7")                                \
+      = (int) FUTEX_OP_CLEAR_WAKE_IF_GT_ONE;                                 \
+    register unsigned long __result asm ("2");                               \
+                                                                             \
+    __asm __volatile ("svc %b1"                                                      \
+                     : "=d" (__result)                                       \
+                     : "i" (SYS_futex), "0" (__r2), "d" (__r3),              \
+                       "d" (__r4), "d" (__r5), "d" (__r6), "d" (__r7)        \
+                     : "cc", "memory" );                                     \
+    __result > -4096UL;                                                              \
+  })
+
+
 #define lll_compare_and_swap(futex, oldval, newval, operation) \
   do {                                                                       \
     __typeof (futex) __futex = (futex);                                              \
index 4626aec5245a5a20a0d29e5f9a54710c52cbbcf9..8d12db3a16cc2ad3c55efc2bfd3f0d9f85fcebdd 100644 (file)
@@ -30,6 +30,8 @@
 #define FUTEX_WAKE             1
 #define FUTEX_REQUEUE          3
 #define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 /* Initializer for compatibility lock. */
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                 \
   })
 
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+                                                                             \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,                               \
+                             (futexp), FUTEX_WAKE_OP, (nr_wake),             \
+                             (nr_wake2), (futexp2),                          \
+                             FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                 \
+  })
+
 #ifdef __sparc32_atomic_do_lock
 #error SPARC < v9 does not support compare and swap which is essential for futex based locking
 #endif
index de9e109f455a81a027908235a1f47c9427f3aad0..3dbb9e81e3601acd34de0500d70fdc46e2272a4a 100644 (file)
@@ -31,7 +31,9 @@
 #define SYS_futex              202
 #define FUTEX_WAIT             0
 #define FUTEX_WAKE             1
-#define FUTEX_REQUEUE          3
+#define FUTEX_WAKE_OP          5
+
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
 
 #define EINVAL                 22
 
@@ -66,9 +68,30 @@ __pthread_cond_signal:
        addl    $1, (%rdi)
 
        /* Wake up one thread.  */
-       movl    $FUTEX_WAKE, %esi
+       movl    $FUTEX_WAKE_OP, %esi
        movl    $SYS_futex, %eax
        movl    $1, %edx
+       movl    $1, %r10d
+#if cond_lock != 0
+       addq    $cond_lock, %r8
+#endif
+       movl    $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d
+       syscall
+#if cond_lock != 0
+       subq    $cond_lock, %r8
+#endif
+       /* For any kind of error, we try again with WAKE.
+          The general test also covers running on old kernels.  */
+       cmpq    $-4095, %rax
+       jae     7f
+
+       xorl    %eax, %eax
+       retq
+
+7:     movl    $FUTEX_WAKE, %esi
+       movl    $SYS_futex, %eax
+       /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
+       movl    $1, %edx  */
        syscall
 
        /* Unlock.  */