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