(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_rwlock_timedrdlock.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 <lowlevelrwlock.h>
22
23
24 #define SYS_gettimeofday        __NR_gettimeofday
25 #define SYS_futex               240
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
28
29 #define EAGAIN          11
30 #define EINVAL          22
31 #define EDEADLK         35
32 #define ETIMEDOUT       110
33
34 #ifndef UP
35 # define LOCK lock
36 #else
37 # define LOCK
38 #endif
39
40
41         .text
42
43         .globl  pthread_rwlock_timedrdlock
44         .type   pthread_rwlock_timedrdlock,@function
45         .align  16
46 pthread_rwlock_timedrdlock:
47         pushl   %esi
48         pushl   %edi
49         pushl   %ebx
50         pushl   %ebp
51         subl    $8, %esp
52
53         movl    28(%esp), %ebp
54         movl    32(%esp), %edi
55
56         /* Get the lock.  */
57         movl    $1, %eax
58         LOCK
59 #if MUTEX == 0
60         xaddl   %eax, (%ebp)
61 #else
62         xaddl   %eax, MUTEX(%ebp)
63 #endif
64         testl   %eax, %eax
65         jne     1f
66
67 2:      movl    WRITER(%ebp), %eax
68         testl   %eax, %eax
69         jne     14f
70         cmp     $0, WRITERS_QUEUED(%ebp)
71         je      5f
72         cmpl    $0, FLAGS(%ebp)
73         je      5f
74
75         /* Check the value of the timeout parameter.  */
76 3:      cmpl    $1000000000, 4(%edi)
77         jae     19f
78
79         incl    READERS_QUEUED(%ebp)
80         je      4f
81
82         movl    READERS_WAKEUP(%ebp), %esi
83
84         LOCK
85 #if MUTEX == 0
86         decl    (%ebp)
87 #else
88         decl    MUTEX(%ebp)
89 #endif
90         jne     10f
91
92         /* Get current time.  */
93 11:     movl    %esp, %ebx
94         xorl    %ecx, %ecx
95         movl    $SYS_gettimeofday, %eax
96         ENTER_KERNEL
97
98         /* Compute relative timeout.  */
99         movl    4(%esp), %eax
100         movl    $1000, %edx
101         mul     %edx            /* Milli seconds to nano seconds.  */
102         movl    (%edi), %ecx
103         movl    4(%edi), %edx
104         subl    (%esp), %ecx
105         subl    %eax, %edx
106         jns     15f
107         addl    $1000000000, %edx
108         decl    %ecx
109 15:     testl   %ecx, %ecx
110         js      16f             /* Time is already up.  */
111
112         /* Futex call.  */
113         movl    %ecx, (%esp)    /* Store relative timeout.  */
114         movl    %edx, 4(%esp)
115         movl    %esi, %edx
116         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
117         movl    %esp, %esi
118         leal    READERS_WAKEUP(%ebp), %ebx
119         movl    $SYS_futex, %eax
120         ENTER_KERNEL
121         movl    %eax, %edx
122 17:
123
124         /* Reget the lock.  */
125         movl    $1, %eax
126         LOCK
127 #if MUTEX == 0
128         xaddl   %eax, (%ebp)
129 #else
130         xaddl   %eax, MUTEX(%ebp)
131 #endif
132         testl   %eax, %eax
133         jne     12f
134
135 13:     decl    READERS_QUEUED(%ebp)
136         cmpl    $-ETIMEDOUT, %edx
137         jne     2b
138
139 18:     movl    $ETIMEDOUT, %ecx
140         jmp     9f
141
142
143 5:      xorl    %ecx, %ecx
144         incl    NR_READERS(%ebp)
145         je      8f
146 9:      LOCK
147 #if MUTEX == 0
148         decl    (%ebp)
149 #else
150         decl    MUTEX(%ebp)
151 #endif
152         jne     6f
153
154 7:      movl    %ecx, %eax
155
156         addl    $8, %esp
157         popl    %ebp
158         popl    %ebx
159         popl    %edi
160         popl    %esi
161         ret
162
163 1:
164 #if MUTEX == 0
165         movl    %ebp, %ecx
166 #else
167         leal    MUTEX(%ebp), %ecx
168 #endif
169         call    __lll_mutex_lock_wait
170         jmp     2b
171
172 14:     cmpl    %gs:8, %eax
173         jne     3b
174         movl    $EDEADLK, %ecx
175         jmp     9b
176
177 6:
178 #if MUTEX == 0
179         movl    %ebp, %eax
180 #else
181         leal    MUTEX(%ebp), %eax
182 #endif
183         call    __lll_mutex_unlock_wake
184         jmp     7b
185
186         /* Overflow.  */
187 8:      decl    NR_READERS(%ebp)
188         movl    $EAGAIN, %ecx
189         jmp     9b
190
191         /* Overflow.  */
192 4:      decl    READERS_QUEUED(%ebp)
193         movl    $EAGAIN, %ecx
194         jmp     9b
195
196 10:
197 #if MUTEX == 0
198         movl    %ebp, %eax
199 #else
200         leal    MUTEX(%ebp), %eax
201 #endif
202         call    __lll_mutex_unlock_wake
203         jmp     11b
204
205 12:
206 #if MUTEX == 0
207         movl    %ebp, %ecx
208 #else
209         leal    MUTEX(%ebp), %ecx
210 #endif
211         call    __lll_mutex_lock_wait
212         jmp     13b
213
214 16:     movl    $-ETIMEDOUT, %edx
215         jmp     17b
216
217 19:     movl    $EINVAL, %ecx
218         jmp     9b
219         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock