pthread_cond_signal implementation for Linux/i486.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_signal.S
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
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.
9
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.
14
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.  */
19
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevelcond.h>
23
24 #ifdef UP
25 # define LOCK
26 #else
27 # define LOCK lock
28 #endif
29
30 #define SYS_futex               240
31 #define FUTEX_WAIT              0
32 #define FUTEX_WAKE              1
33
34
35         .text
36
37         /* int pthread_cond_signal (pthread_cond_t *cond) */
38         .globl  __pthread_cond_signal
39         .type   __pthread_cond_signal, @function
40         .align  16
41 __pthread_cond_signal:
42
43         pushl   %esi
44         pushl   %ebx
45 #if cond_lock != 0
46         addl    $cond_lock, %ebx
47 #endif
48
49         movl    12(%esp), %ebx
50
51         /* Get internal lock.  */
52         movl    $1, %eax
53         LOCK
54 #if cond_lock == 0
55         xaddl   %eax, (%ebx)
56 #else
57         xaddl   %eax, cond_lock(%ebx)
58 #endif
59         testl   %eax, %eax
60         jne     1f
61
62 2:      movl    total_seq+4(%ebx), %eax
63         movl    total_seq(%ebx), %ecx
64         cmpl    wakeup_seq+4(%ebx), %eax
65         ja      3f
66         jb      4f
67         cmpl    wakeup_seq(%ebx), %ecx
68         jbe     4f
69
70         /* Bump the wakeup number.  */
71 3:      addl    $1, wakeup_seq(%ebx)
72         adcl    $0, wakeup_seq+4(%ebx)
73
74         /* Wake up one thread.  */
75         addl    $wakeup_seq-cond_lock, %ebx
76         movl    $FUTEX_WAKE, %ecx
77         xorl    %esi, %esi
78         movl    $SYS_futex, %eax
79         movl    %ecx, %edx      /* movl $1, %edx */
80         ENTER_KERNEL
81
82         subl    $wakeup_seq-cond_lock, %ebx
83
84         /* Unlock.  */
85 4:      LOCK
86 #if cond_lock == 0
87         decl    (%ebx)
88 #else
89         decl    cond_lock(%ebx)
90 #endif
91         jne     5f
92
93 6:      xorl    %eax, %eax
94         popl    %ebx
95         popl    %esi
96         ret
97
98         /* Initial locking failed.  */
99 1:
100 #if cond_lock == 0
101         movl    %ebx, %ecx
102 #else
103         leal    cond_lock(%ebx), %ecx
104 #endif
105         call    __lll_mutex_lock_wait
106         jmp     2b
107
108         /* Unlock in loop requires waekup.  */
109 5:
110 #if cond_lock == 0
111         movl    %ebx, %eax
112 #else
113         leal    cond_lock(%ebx), %eax
114 #endif
115         call    __lll_mutex_unlock_wake
116         jmp     6b
117         .size   __pthread_cond_signal, .-__pthread_cond_signal
118 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
119                   GLIBC_2_3_2)