2.5-18.1
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_signal.S
blobd0f931ff15bf835417eba87ef8ea62bd5ea3c544
1 /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevelcond.h>
23 #include <kernel-features.h>
25 #ifdef UP
26 # define LOCK
27 #else
28 # define LOCK lock
29 #endif
31 #define SYS_futex               240
32 #define FUTEX_WAIT              0
33 #define FUTEX_WAKE              1
34 #define FUTEX_WAKE_OP           5
36 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE   ((4 << 24) | 1)
38 #define EINVAL                  22
41         .text
43         /* int pthread_cond_signal (pthread_cond_t *cond) */
44         .globl  __pthread_cond_signal
45         .type   __pthread_cond_signal, @function
46         .align  16
47 __pthread_cond_signal:
49         pushl   %ebx
50         pushl   %edi
52         movl    12(%esp), %edi
54         /* Get internal lock.  */
55         movl    $1, %edx
56         xorl    %eax, %eax
57         LOCK
58 #if cond_lock == 0
59         cmpxchgl %edx, (%edi)
60 #else
61         cmpxchgl %edx, cond_lock(%edi)
62 #endif
63         jnz     1f
65 2:      leal    cond_futex(%edi), %ebx
66         movl    total_seq+4(%edi), %eax
67         movl    total_seq(%edi), %ecx
68         cmpl    wakeup_seq+4(%edi), %eax
69 #if cond_lock != 0
70         /* Must use leal to preserve the flags.  */
71         leal    cond_lock(%edi), %edi
72 #endif
73         ja      3f
74         jb      4f
75         cmpl    wakeup_seq-cond_futex(%ebx), %ecx
76         jbe     4f
78         /* Bump the wakeup number.  */
79 3:      addl    $1, wakeup_seq-cond_futex(%ebx)
80         adcl    $0, wakeup_seq-cond_futex+4(%ebx)
81         addl    $1, (%ebx)
83         /* Wake up one thread.  */
84         pushl   %esi
85         pushl   %ebp
86         movl    $FUTEX_WAKE_OP, %ecx
87         movl    $SYS_futex, %eax
88         movl    $1, %edx
89         movl    $1, %esi
90         movl    $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp
91         /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
92            sysenter.
93         ENTER_KERNEL  */
94         int     $0x80
95         popl    %ebp
96         popl    %esi
98         /* For any kind of error, we try again with WAKE.
99            The general test also covers running on old kernels.  */
100         cmpl    $-4095, %eax
101         jae     7f
103 6:      xorl    %eax, %eax
104         popl    %edi
105         popl    %ebx
106         ret
108 7:      movl    $FUTEX_WAKE, %ecx
109         movl    $SYS_futex, %eax
110         /* %edx should be 1 already from $FUTEX_WAKE_OP syscall.
111         movl    $1, %edx  */
112         ENTER_KERNEL
114         /* Unlock.  Note that at this point %edi always points to
115            cond_lock.  */
116 4:      LOCK
117         subl    $1, (%edi)
118         je      6b
120         /* Unlock in loop requires wakeup.  */
121 5:      movl    %edi, %eax
122         call    __lll_mutex_unlock_wake
123         jmp     6b
125         /* Initial locking failed.  */
127 #if cond_lock == 0
128         movl    %edi, %ecx
129 #else
130         leal    cond_lock(%edi), %ecx
131 #endif
132         call    __lll_mutex_lock_wait
133         jmp     2b
135         .size   __pthread_cond_signal, .-__pthread_cond_signal
136 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
137                   GLIBC_2_3_2)