(lll_unlock_wake_cb): Don't save and restore %esi.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevellock.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
22         .text
23
24 #ifdef UP
25 # define LOCK
26 #else
27 # define LOCK lock
28 #endif
29
30 #define SYS_gettimeofday        __NR_gettimeofday
31 #define SYS_futex               240
32 #define FUTEX_WAIT              0
33 #define FUTEX_WAKE              1
34
35 #define ETIMEDOUT               110
36
37
38         .globl  __lll_lock_wait
39         .type   __lll_lock_wait,@function
40         .hidden __lll_lock_wait
41         .align  16
42 __lll_lock_wait:
43         pushl   %esi
44         pushl   %ebx
45         pushl   %edx
46
47         movl    %ecx, %ebx
48         xorl    %esi, %esi      /* No timeout.  */
49         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
50 1:
51         leal    -1(%eax), %edx  /* account for the preceeded xadd.  */
52         movl    $SYS_futex, %eax
53         ENTER_KERNEL
54
55         orl     $-1, %eax       /* Load -1.  */
56         LOCK
57         xaddl   %eax, (%ebx)
58         jne,pn  1b
59
60         movl    $-1, (%ebx)
61
62         popl    %edx
63         popl    %ebx
64         popl    %esi
65         ret
66         .size   __lll_lock_wait,.-__lll_lock_wait
67
68
69         .globl  lll_unlock_wake_cb
70         .type   lll_unlock_wake_cb,@function
71         .hidden lll_unlock_wake_cb
72         .align  16
73 lll_unlock_wake_cb:
74         pushl   %ebx
75         pushl   %ecx
76         pushl   %edx
77
78         movl    20(%esp), %ebx
79         LOCK
80         incl    (%ebx)
81         jng     1f
82
83         popl    %edx
84         popl    %ecx
85         popl    %ebx
86         ret
87         .size   lll_unlock_wake_cb,.-lll_unlock_wake_cb
88
89
90         .globl  __lll_unlock_wake
91         .type   __lll_unlock_wake,@function
92         .hidden __lll_unlock_wake
93         .align  16
94 __lll_unlock_wake:
95         pushl   %ebx
96         pushl   %ecx
97         pushl   %edx
98
99         movl    %eax, %ebx
100 1:      movl    $FUTEX_WAKE, %ecx
101         movl    $1, %edx        /* Wake one thread.  */
102         movl    %edx, (%ebx)    /* Stores '$1'.  */
103         movl    $SYS_futex, %eax
104         ENTER_KERNEL
105
106         popl    %edx
107         popl    %ecx
108         popl    %ebx
109         ret
110         .size   __lll_unlock_wake,.-__lll_unlock_wake
111
112
113         .globl  __lll_timedwait_tid
114         .type   __lll_timedwait_tid,@function
115         .hidden __lll_timedwait_tid
116         .align  16
117 __lll_timedwait_tid:
118         pushl   %edi
119         pushl   %esi
120         pushl   %ebx
121         pushl   %ebp
122
123         movl    %eax, %ebp
124         movl    %edx, %edi
125         subl    $8, %esp
126
127         /* Get current time.  */
128 2:      movl    %esp, %ebx
129         xorl    %ecx, %ecx
130         movl    $SYS_gettimeofday, %eax
131         ENTER_KERNEL
132
133         /* Compute relative timeout.  */
134         movl    4(%esp), %eax
135         movl    $1000, %edx
136         mul     %edx            /* Milli seconds to nano seconds.  */
137         movl    (%edi), %ecx
138         movl    4(%edi), %edx
139         subl    (%esp), %ecx
140         subl    %eax, %edx
141         jns     5f
142         addl    $1000000000, %edx
143         decl    %ecx
144 5:      testl   %ecx, %ecx
145         js      6f              /* Time is already up.  */
146
147         movl    %ecx, (%esp)    /* Store relative timeout.  */
148         movl    %edx, 4(%esp)
149
150         movl    (%ebp), %edx
151         testl   %edx, %edx
152         jz      4f
153
154         movl    %esp, %esi
155         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
156         movl    %ebp, %ebx
157         movl    $SYS_futex, %eax
158         ENTER_KERNEL
159
160         movl    %eax, %edx
161
162         cmpl    $0, (%ebx)
163         jne     1f
164 4:      xorl    %eax, %eax
165
166 3:      addl    $8, %esp
167         popl    %ebp
168         popl    %ebx
169         popl    %esi
170         popl    %edi
171         ret
172
173 1:      cmpl    $-ETIMEDOUT, %edx
174         jne     2b
175 6:      movl    $ETIMEDOUT, %eax
176         jmp     3b
177         .size   __lll_timedwait_tid,.-__lll_timedwait_tid