* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Access
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_timedrdlock.S
blob89027284ec677ccf97950ad110f6d36cafe61803
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         pushl   %esi
34         pushl   %edi
35         pushl   %ebx
36         pushl   %ebp
37         subl    $8, %esp
39         movl    28(%esp), %ebp
40         movl    32(%esp), %edi
42         /* Get the lock.  */
43         movl    $1, %edx
44         xorl    %eax, %eax
45         LOCK
46 #if MUTEX == 0
47         cmpxchgl %edx, (%ebp)
48 #else
49         cmpxchgl %edx, MUTEX(%ebp)
50 #endif
51         jnz     1f
53 2:      movl    WRITER(%ebp), %eax
54         testl   %eax, %eax
55         jne     14f
56         cmpl    $0, WRITERS_QUEUED(%ebp)
57         je      5f
58         cmpb    $0, FLAGS(%ebp)
59         je      5f
61         /* Check the value of the timeout parameter.  */
62 3:      cmpl    $1000000000, 4(%edi)
63         jae     19f
65         addl    $1, READERS_QUEUED(%ebp)
66         je      4f
68         movl    READERS_WAKEUP(%ebp), %esi
70         LOCK
71 #if MUTEX == 0
72         subl    $1, (%ebp)
73 #else
74         subl    $1, MUTEX(%ebp)
75 #endif
76         jne     10f
78         /* Get current time.  */
79 11:     movl    %esp, %ebx
80         xorl    %ecx, %ecx
81         movl    $__NR_gettimeofday, %eax
82         ENTER_KERNEL
84         /* Compute relative timeout.  */
85         movl    4(%esp), %eax
86         movl    $1000, %edx
87         mul     %edx            /* Milli seconds to nano seconds.  */
88         movl    (%edi), %ecx
89         movl    4(%edi), %edx
90         subl    (%esp), %ecx
91         subl    %eax, %edx
92         jns     15f
93         addl    $1000000000, %edx
94         subl    $1, %ecx
95 15:     testl   %ecx, %ecx
96         js      16f             /* Time is already up.  */
98         /* Futex call.  */
99         movl    %ecx, (%esp)    /* Store relative timeout.  */
100         movl    %edx, 4(%esp)
102         movl    %esi, %edx
103 #ifdef __ASSUME_PRIVATE_FUTEX
104         movzbl  PSHARED(%ebp), %ecx
105         xorl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
106 #else
107         movzbl  PSHARED(%ebp), %ecx
108 # if FUTEX_WAIT != 0
109         orl     $FUTEX_WAIT, %ecx
110 # endif
111         xorl    %gs:PRIVATE_FUTEX, %ecx
112 #endif
113         movl    %esp, %esi
114         leal    READERS_WAKEUP(%ebp), %ebx
115         movl    $SYS_futex, %eax
116         ENTER_KERNEL
117         movl    %eax, %esi
120         /* Reget the lock.  */
121         movl    $1, %edx
122         xorl    %eax, %eax
123         LOCK
124 #if MUTEX == 0
125         cmpxchgl %edx, (%ebp)
126 #else
127         cmpxchgl %edx, MUTEX(%ebp)
128 #endif
129         jnz     12f
131 13:     subl    $1, READERS_QUEUED(%ebp)
132         cmpl    $-ETIMEDOUT, %esi
133         jne     2b
135 18:     movl    $ETIMEDOUT, %edx
136         jmp     9f
139 5:      xorl    %edx, %edx
140         addl    $1, NR_READERS(%ebp)
141         je      8f
142 9:      LOCK
143 #if MUTEX == 0
144         subl    $1, (%ebp)
145 #else
146         subl    $1, MUTEX(%ebp)
147 #endif
148         jne     6f
150 7:      movl    %edx, %eax
152         addl    $8, %esp
153         popl    %ebp
154         popl    %ebx
155         popl    %edi
156         popl    %esi
157         ret
160 #if MUTEX == 0
161         movl    %ebp, %edx
162 #else
163         leal    MUTEX(%ebp), %edx
164 #endif
165         movzbl  PSHARED(%ebp), %ecx
166         call    __lll_lock_wait
167         jmp     2b
169 14:     cmpl    %gs:TID, %eax
170         jne     3b
171         movl    $EDEADLK, %edx
172         jmp     9b
175 #if MUTEX == 0
176         movl    %ebp, %eax
177 #else
178         leal    MUTEX(%ebp), %eax
179 #endif
180         movzbl  PSHARED(%ebp), %ecx
181         call    __lll_unlock_wake
182         jmp     7b
184         /* Overflow.  */
185 8:      subl    $1, NR_READERS(%ebp)
186         movl    $EAGAIN, %edx
187         jmp     9b
189         /* Overflow.  */
190 4:      subl    $1, READERS_QUEUED(%ebp)
191         movl    $EAGAIN, %edx
192         jmp     9b
195 #if MUTEX == 0
196         movl    %ebp, %eax
197 #else
198         leal    MUTEX(%ebp), %eax
199 #endif
200         movzbl  PSHARED(%ebp), %ecx
201         call    __lll_unlock_wake
202         jmp     11b
205 #if MUTEX == 0
206         movl    %ebp, %edx
207 #else
208         leal    MUTEX(%ebp), %edx
209 #endif
210         movzbl  PSHARED(%ebp), %ecx
211         call    __lll_lock_wait
212         jmp     13b
214 16:     movl    $-ETIMEDOUT, %esi
215         jmp     17b
217 19:     movl    $EINVAL, %edx
218         jmp     9b
219         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock