fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_barrier_wait.S
index 8348f6e..77d252d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
    02111-1307 USA.  */
 
 #include <sysdep.h>
-
-#define SYS_futex      240
-#define FUTEX_WAIT     0
-#define FUTEX_WAKE     1
-
-#ifndef UP
-# define LOCK lock
-#else
-# define LOCK
-#endif
-
-#define CURR_EVENT     0
-#define MUTEX          4
-#define LEFT           8
-#define        INIT_COUNT      12
-
+#include <lowlevellock.h>
+#include <lowlevelbarrier.h>
 
        .text
 
        .type   pthread_barrier_wait,@function
        .align  16
 pthread_barrier_wait:
-       pushl   %esi
        pushl   %ebx
 
-       movl    12(%esp), %ebx
-       xorl    %esi, %esi
+       movl    8(%esp), %ebx
 
        /* Get the mutex.  */
-       orl     $-1, %eax
+       movl    $1, %edx
+       xorl    %eax, %eax
        LOCK
-       xaddl   %eax, MUTEX(%ebx)
-       jne     1f
+       cmpxchgl %edx, MUTEX(%ebx)
+       jnz     1f
 
        /* One less waiter.  If this was the last one needed wake
           everybody.  */
-2:     decl    LEFT(%ebx)
+2:     subl    $1, LEFT(%ebx)
        je      3f
 
        /* There are more threads to come.  */
+       pushl   %esi
+
 #if CURR_EVENT == 0
        movl    (%ebx), %edx
 #else
@@ -67,12 +54,19 @@ pthread_barrier_wait:
 
        /* Release the mutex.  */
        LOCK
-       incl    MUTEX(%ebx)
-       jng     6f
+       subl    $1, MUTEX(%ebx)
+       jne     6f
 
        /* Wait for the remaining threads.  The call will return immediately
           if the CURR_EVENT memory has meanwhile been changed.  */
-7:     movl    %esi, %ecx              /* movl $FUTEX_WAIT, %ecx */
+7:
+#if FUTEX_WAIT == 0
+       movl    PRIVATE(%ebx), %ecx
+#else
+       movl    $FUTEX_WAIT, %ecx
+       orl     PRIVATE(%ebx), %ecx
+#endif
+       xorl    %esi, %esi
 8:     movl    $SYS_futex, %eax
        ENTER_KERNEL
 
@@ -84,53 +78,91 @@ pthread_barrier_wait:
 #else
        cmpl    %edx, CURR_EVENT(%ebx)
 #endif
-       je,pn   8b
+       je      8b
+
+       /* Increment LEFT.  If this brings the count back to the
+          initial count unlock the object.  */
+       movl    $1, %edx
+       movl    INIT_COUNT(%ebx), %ecx
+       LOCK
+       xaddl   %edx, LEFT(%ebx)
+       subl    $1, %ecx
+       cmpl    %ecx, %edx
+       jne     10f
+
+       /* Release the mutex.  We cannot release the lock before
+          waking the waiting threads since otherwise a new thread might
+          arrive and gets waken up, too.  */
+       LOCK
+       subl    $1, MUTEX(%ebx)
+       jne     9f
 
        /* Note: %esi is still zero.  */
-       movl    %esi, %eax              /* != PTHREAD_BARRIER_SERIAL_THREAD */
+10:    movl    %esi, %eax              /* != PTHREAD_BARRIER_SERIAL_THREAD */
 
-       popl    %ebx
        popl    %esi
+       popl    %ebx
        ret
 
        /* The necessary number of threads arrived.  */
-3:     movl    INIT_COUNT(%ebx), %eax
-       movl    %eax, LEFT(%ebx)
+3:
 #if CURR_EVENT == 0
-       incl    (%ebx)
+       addl    $1, (%ebx)
 #else
-       incl    CURR_EVENT(%ebx)
+       addl    $1, CURR_EVENT(%ebx)
 #endif
 
        /* Wake up all waiters.  The count is a signed number in the kernel
           so 0x7fffffff is the highest value.  */
        movl    $0x7fffffff, %edx
        movl    $FUTEX_WAKE, %ecx
+       orl     PRIVATE(%ebx), %ecx
        movl    $SYS_futex, %eax
        ENTER_KERNEL
 
+       /* Increment LEFT.  If this brings the count back to the
+          initial count unlock the object.  */
+       movl    $1, %edx
+       movl    INIT_COUNT(%ebx), %ecx
+       LOCK
+       xaddl   %edx, LEFT(%ebx)
+       subl    $1, %ecx
+       cmpl    %ecx, %edx
+       jne     5f
+
        /* Release the mutex.  We cannot release the lock before
           waking the waiting threads since otherwise a new thread might
           arrive and gets waken up, too.  */
        LOCK
-       incl    MUTEX(%ebx)
-       jng     4f
+       subl    $1, MUTEX(%ebx)
+       jne     4f
 
 5:     orl     $-1, %eax               /* == PTHREAD_BARRIER_SERIAL_THREAD */
 
        popl    %ebx
-       popl    %esi
        ret
 
-1:     leal    MUTEX(%ebx), %ecx
+1:     movl    PRIVATE(%ebx), %ecx
+       leal    MUTEX(%ebx), %edx
+       xorl    $LLL_SHARED, %ecx
        call    __lll_lock_wait
        jmp     2b
 
-4:     leal    MUTEX(%ebx), %eax
+4:     movl    PRIVATE(%ebx), %ecx
+       leal    MUTEX(%ebx), %eax
+       xorl    $LLL_SHARED, %ecx
        call    __lll_unlock_wake
        jmp     5b
 
-6:     leal    MUTEX(%ebx), %eax
+6:     movl    PRIVATE(%ebx), %ecx
+       leal    MUTEX(%ebx), %eax
+       xorl    $LLL_SHARED, %ecx
        call    __lll_unlock_wake
        jmp     7b
+
+9:     movl    PRIVATE(%ebx), %ecx
+       leal    MUTEX(%ebx), %eax
+       xorl    $LLL_SHARED, %ecx
+       call    __lll_unlock_wake
+       jmp     10b
        .size   pthread_barrier_wait,.-pthread_barrier_wait