* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Access
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_timedwrlock.S
blob0cf02e057ed2ab27a756da82c6e1bb14139f8ba8
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_timedwrlock
30         .type   pthread_rwlock_timedwrlock,@function
31         .align  16
32 pthread_rwlock_timedwrlock:
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, NR_READERS(%ebp)
57         je      5f
59         /* Check the value of the timeout parameter.  */
60 3:      cmpl    $1000000000, 4(%edi)
61         jae     19f
63         addl    $1, WRITERS_QUEUED(%ebp)
64         je      4f
66         movl    WRITERS_WAKEUP(%ebp), %esi
68         LOCK
69 #if MUTEX == 0
70         subl    $1, (%ebp)
71 #else
72         subl    $1, MUTEX(%ebp)
73 #endif
74         jne     10f
76         /* Get current time.  */
77 11:     movl    %esp, %ebx
78         xorl    %ecx, %ecx
79         movl    $__NR_gettimeofday, %eax
80         ENTER_KERNEL
82         /* Compute relative timeout.  */
83         movl    4(%esp), %eax
84         movl    $1000, %edx
85         mul     %edx            /* Milli seconds to nano seconds.  */
86         movl    (%edi), %ecx
87         movl    4(%edi), %edx
88         subl    (%esp), %ecx
89         subl    %eax, %edx
90         jns     15f
91         addl    $1000000000, %edx
92         subl    $1, %ecx
93 15:     testl   %ecx, %ecx
94         js      16f             /* Time is already up.  */
96         /* Futex call.  */
97         movl    %ecx, (%esp)    /* Store relative timeout.  */
98         movl    %edx, 4(%esp)
100         movl    %esi, %edx
101 #ifdef __ASSUME_PRIVATE_FUTEX
102         movzbl  PSHARED(%ebp), %ecx
103         xorl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
104 #else
105         movzbl  PSHARED(%ebp), %ecx
106 # if FUTEX_WAIT != 0
107         orl     $FUTEX_WAIT, %ecx
108 # endif
109         xorl    %gs:PRIVATE_FUTEX, %ecx
110 #endif
111         movl    %esp, %esi
112         leal    WRITERS_WAKEUP(%ebp), %ebx
113         movl    $SYS_futex, %eax
114         ENTER_KERNEL
115         movl    %eax, %esi
118         /* Reget the lock.  */
119         movl    $1, %edx
120         xorl    %eax, %eax
121         LOCK
122 #if MUTEX == 0
123         cmpxchgl %edx, (%ebp)
124 #else
125         cmpxchgl %edx, MUTEX(%ebp)
126 #endif
127         jnz     12f
129 13:     subl    $1, WRITERS_QUEUED(%ebp)
130         cmpl    $-ETIMEDOUT, %esi
131         jne     2b
133 18:     movl    $ETIMEDOUT, %edx
134         jmp     9f
137 5:      xorl    %edx, %edx
138         movl    %gs:TID, %eax
139         movl    %eax, WRITER(%ebp)
140 9:      LOCK
141 #if MUTEX == 0
142         subl    $1, (%ebp)
143 #else
144         subl    $1, MUTEX(%ebp)
145 #endif
146         jne     6f
148 7:      movl    %edx, %eax
150         addl    $8, %esp
151         popl    %ebp
152         popl    %ebx
153         popl    %edi
154         popl    %esi
155         ret
158 #if MUTEX == 0
159         movl    %ebp, %edx
160 #else
161         leal    MUTEX(%ebp), %edx
162 #endif
163         movzbl  PSHARED(%ebp), %ecx
164         call    __lll_lock_wait
165         jmp     2b
167 14:     cmpl    %gs:TID, %eax
168         jne     3b
169 20:     movl    $EDEADLK, %edx
170         jmp     9b
173 #if MUTEX == 0
174         movl    %ebp, %eax
175 #else
176         leal    MUTEX(%ebp), %eax
177 #endif
178         movzbl  PSHARED(%ebp), %ecx
179         call    __lll_unlock_wake
180         jmp     7b
182         /* Overflow.  */
183 4:      subl    $1, WRITERS_QUEUED(%ebp)
184         movl    $EAGAIN, %edx
185         jmp     9b
188 #if MUTEX == 0
189         movl    %ebp, %eax
190 #else
191         leal    MUTEX(%ebp), %eax
192 #endif
193         movzbl  PSHARED(%ebp), %ecx
194         call    __lll_unlock_wake
195         jmp     11b
198 #if MUTEX == 0
199         movl    %ebp, %edx
200 #else
201         leal    MUTEX(%ebp), %edx
202 #endif
203         movzbl  PSHARED(%ebp), %ecx
204         call    __lll_lock_wait
205         jmp     13b
207 16:     movl    $-ETIMEDOUT, %esi
208         jmp     17b
210 19:     movl    $EINVAL, %edx
211         jmp     9b
212         .size   pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock