(pthread_barrier_wait): Don't save, load, and restore %esi for last thread.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_barrier_wait.S
index b77c342..d36bc7e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
        .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
@@ -59,7 +57,13 @@ pthread_barrier_wait:
        je      3f
 
        /* There are more threads to come.  */
+       pushl   %esi
+
+#if CURR_EVENT == 0
+       movl    (%ebx), %edx
+#else
        movl    CURR_EVENT(%ebx), %edx
+#endif
 
        /* Release the mutex.  */
        LOCK
@@ -68,27 +72,36 @@ pthread_barrier_wait:
 
        /* 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:     xorl    %ecx, %ecx              /* movl $FUTEX_WAIT, %ecx */
+       xorl    %esi, %esi
 8:     movl    $SYS_futex, %eax
        ENTER_KERNEL
 
        /* Don't return on spurious wakeups.  The syscall does not change
           any register except %eax so there is no need to reload any of
           them.  */
+#if CURR_EVENT == 0
+       cmpl    %edx, (%ebx)
+#else
        cmpl    %edx, CURR_EVENT(%ebx)
+#endif
        je,pn   8b
 
        /* Note: %esi is still zero.  */
        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)
+#if CURR_EVENT == 0
+       incl    (%ebx)
+#else
        incl    CURR_EVENT(%ebx)
+#endif
 
        /* Wake up all waiters.  The count is a signed number in the kernel
           so 0x7fffffff is the highest value.  */
@@ -97,7 +110,9 @@ pthread_barrier_wait:
        movl    $SYS_futex, %eax
        ENTER_KERNEL
 
-       /* Release the mutex.  */
+       /* 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
@@ -105,7 +120,6 @@ pthread_barrier_wait:
 5:     orl     $-1, %eax               /* == PTHREAD_BARRIER_SERIAL_THREAD */
 
        popl    %ebx
-       popl    %esi
        ret
 
 1:     leal    MUTEX(%ebx), %ecx