OSDN Git Service

be4530e13d96a1230b5b275fda248895416a7db5
[uclinux-h8/uClibc.git] / libpthread / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_timedrdlock.S
1 /* Copyright (C) 2002, 2003, 2007 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 <lowlevellock.h>
22 #include <lowlevelrwlock.h>
23 #include <pthread-errnos.h>
24 #include <bits/kernel-features.h>
25 #include <tls.h>
26
27
28         .text
29
30         .globl  pthread_rwlock_timedrdlock
31         .type   pthread_rwlock_timedrdlock,@function
32         .align  16
33 pthread_rwlock_timedrdlock:
34         cfi_startproc
35         pushl   %esi
36         cfi_adjust_cfa_offset(4)
37         pushl   %edi
38         cfi_adjust_cfa_offset(4)
39         pushl   %ebx
40         cfi_adjust_cfa_offset(4)
41         pushl   %ebp
42         cfi_adjust_cfa_offset(4)
43         cfi_offset(%esi, -8)
44         cfi_offset(%edi, -12)
45         cfi_offset(%ebx, -16)
46         cfi_offset(%ebp, -20)
47         subl    $8, %esp
48         cfi_adjust_cfa_offset(8)
49
50         movl    28(%esp), %ebp
51         movl    32(%esp), %edi
52
53         /* Get the lock.  */
54         movl    $1, %edx
55         xorl    %eax, %eax
56         LOCK
57 #if MUTEX == 0
58         cmpxchgl %edx, (%ebp)
59 #else
60         cmpxchgl %edx, MUTEX(%ebp)
61 #endif
62         jnz     1f
63
64 2:      movl    WRITER(%ebp), %eax
65         testl   %eax, %eax
66         jne     14f
67         cmpl    $0, WRITERS_QUEUED(%ebp)
68         je      5f
69         cmpb    $0, FLAGS(%ebp)
70         je      5f
71
72         /* Check the value of the timeout parameter.  */
73 3:      cmpl    $1000000000, 4(%edi)
74         jae     19f
75
76         addl    $1, READERS_QUEUED(%ebp)
77         je      4f
78
79         movl    READERS_WAKEUP(%ebp), %esi
80
81         LOCK
82 #if MUTEX == 0
83         subl    $1, (%ebp)
84 #else
85         subl    $1, MUTEX(%ebp)
86 #endif
87         jne     10f
88
89         /* Get current time.  */
90 11:     movl    %esp, %ebx
91         xorl    %ecx, %ecx
92         movl    $__NR_gettimeofday, %eax
93         ENTER_KERNEL
94
95         /* Compute relative timeout.  */
96         movl    4(%esp), %eax
97         movl    $1000, %edx
98         mul     %edx            /* Milli seconds to nano seconds.  */
99         movl    (%edi), %ecx
100         movl    4(%edi), %edx
101         subl    (%esp), %ecx
102         subl    %eax, %edx
103         jns     15f
104         addl    $1000000000, %edx
105         subl    $1, %ecx
106 15:     testl   %ecx, %ecx
107         js      16f             /* Time is already up.  */
108
109         /* Futex call.  */
110         movl    %ecx, (%esp)    /* Store relative timeout.  */
111         movl    %edx, 4(%esp)
112
113         movl    %esi, %edx
114 #ifdef __ASSUME_PRIVATE_FUTEX
115         movzbl  PSHARED(%ebp), %ecx
116         xorl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
117 #else
118         movzbl  PSHARED(%ebp), %ecx
119 # if FUTEX_WAIT != 0
120         orl     $FUTEX_WAIT, %ecx
121 # endif
122         xorl    %gs:PRIVATE_FUTEX, %ecx
123 #endif
124         movl    %esp, %esi
125         leal    READERS_WAKEUP(%ebp), %ebx
126         movl    $SYS_futex, %eax
127         ENTER_KERNEL
128         movl    %eax, %esi
129 17:
130
131         /* Reget the lock.  */
132         movl    $1, %edx
133         xorl    %eax, %eax
134         LOCK
135 #if MUTEX == 0
136         cmpxchgl %edx, (%ebp)
137 #else
138         cmpxchgl %edx, MUTEX(%ebp)
139 #endif
140         jnz     12f
141
142 13:     subl    $1, READERS_QUEUED(%ebp)
143         cmpl    $-ETIMEDOUT, %esi
144         jne     2b
145
146 18:     movl    $ETIMEDOUT, %edx
147         jmp     9f
148
149
150 5:      xorl    %edx, %edx
151         addl    $1, NR_READERS(%ebp)
152         je      8f
153 9:      LOCK
154 #if MUTEX == 0
155         subl    $1, (%ebp)
156 #else
157         subl    $1, MUTEX(%ebp)
158 #endif
159         jne     6f
160
161 7:      movl    %edx, %eax
162
163         addl    $8, %esp
164         cfi_adjust_cfa_offset(-8)
165         popl    %ebp
166         cfi_adjust_cfa_offset(-4)
167         cfi_restore(%ebp)
168         popl    %ebx
169         cfi_adjust_cfa_offset(-4)
170         cfi_restore(%ebx)
171         popl    %edi
172         cfi_adjust_cfa_offset(-4)
173         cfi_restore(%edi)
174         popl    %esi
175         cfi_adjust_cfa_offset(-4)
176         cfi_restore(%esi)
177         ret
178
179         cfi_adjust_cfa_offset(24)
180         cfi_offset(%esi, -8)
181         cfi_offset(%edi, -12)
182         cfi_offset(%ebx, -16)
183         cfi_offset(%ebp, -20)
184 1:
185 #if MUTEX == 0
186         movl    %ebp, %edx
187 #else
188         leal    MUTEX(%ebp), %edx
189 #endif
190         movzbl  PSHARED(%ebp), %ecx
191         call    __lll_lock_wait
192         jmp     2b
193
194 14:     cmpl    %gs:TID, %eax
195         jne     3b
196         movl    $EDEADLK, %edx
197         jmp     9b
198
199 6:
200 #if MUTEX == 0
201         movl    %ebp, %eax
202 #else
203         leal    MUTEX(%ebp), %eax
204 #endif
205         movzbl  PSHARED(%ebp), %ecx
206         call    __lll_unlock_wake
207         jmp     7b
208
209         /* Overflow.  */
210 8:      subl    $1, NR_READERS(%ebp)
211         movl    $EAGAIN, %edx
212         jmp     9b
213
214         /* Overflow.  */
215 4:      subl    $1, READERS_QUEUED(%ebp)
216         movl    $EAGAIN, %edx
217         jmp     9b
218
219 10:
220 #if MUTEX == 0
221         movl    %ebp, %eax
222 #else
223         leal    MUTEX(%ebp), %eax
224 #endif
225         movzbl  PSHARED(%ebp), %ecx
226         call    __lll_unlock_wake
227         jmp     11b
228
229 12:
230 #if MUTEX == 0
231         movl    %ebp, %edx
232 #else
233         leal    MUTEX(%ebp), %edx
234 #endif
235         movzbl  PSHARED(%ebp), %ecx
236         call    __lll_lock_wait
237         jmp     13b
238
239 16:     movl    $-ETIMEDOUT, %esi
240         jmp     17b
241
242 19:     movl    $EINVAL, %edx
243         jmp     9b
244         cfi_endproc
245         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock