* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_timedwrlock.S
blob6c6e2faf50daeecb0079116aaa4c12a875ff81ad
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 <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
25 #define SYS_gettimeofday        __NR_gettimeofday
26 #define SYS_futex               240
27 #define FUTEX_WAIT              0
28 #define FUTEX_WAKE              1
30 #ifndef UP
31 # define LOCK lock
32 #else
33 # define LOCK
34 #endif
37         .text
39         .globl  pthread_rwlock_timedwrlock
40         .type   pthread_rwlock_timedwrlock,@function
41         .align  16
42 pthread_rwlock_timedwrlock:
43         pushl   %esi
44         pushl   %edi
45         pushl   %ebx
46         pushl   %ebp
47         subl    $8, %esp
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, NR_READERS(%ebp)
67         je      5f
69         /* Check the value of the timeout parameter.  */
70 3:      cmpl    $1000000000, 4(%edi)
71         jae     19f
73         addl    $1, WRITERS_QUEUED(%ebp)
74         je      4f
76         movl    WRITERS_WAKEUP(%ebp), %esi
78         LOCK
79 #if MUTEX == 0
80         subl    $1, (%ebp)
81 #else
82         subl    $1, MUTEX(%ebp)
83 #endif
84         jne     10f
86         /* Get current time.  */
87 11:     movl    %esp, %ebx
88         xorl    %ecx, %ecx
89         movl    $SYS_gettimeofday, %eax
90         ENTER_KERNEL
92         /* Compute relative timeout.  */
93         movl    4(%esp), %eax
94         movl    $1000, %edx
95         mul     %edx            /* Milli seconds to nano seconds.  */
96         movl    (%edi), %ecx
97         movl    4(%edi), %edx
98         subl    (%esp), %ecx
99         subl    %eax, %edx
100         jns     15f
101         addl    $1000000000, %edx
102         subl    $1, %ecx
103 15:     testl   %ecx, %ecx
104         js      16f             /* Time is already up.  */
106         /* Futex call.  */
107         movl    %ecx, (%esp)    /* Store relative timeout.  */
108         movl    %edx, 4(%esp)
110         movl    %esi, %edx
111 #if __ASSUME_PRIVATE_FUTEX
112         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
113         xorl    PSHARED(%ebp), %ecx
114 #else
115 # if FUTEX_WAIT == 0
116         movl    PSHARED(%ebp), %ecx
117 # else
118         movl    $FUTEX_WAIT, %ecx
119         orl     PSHARED(%ebp), %ecx
120 # endif
121         xorl    %gs:PRIVATE_FUTEX, %ecx
122 #endif
123         movl    %esp, %esi
124         leal    WRITERS_WAKEUP(%ebp), %ebx
125         movl    $SYS_futex, %eax
126         ENTER_KERNEL
127         movl    %eax, %ecx
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, WRITERS_QUEUED(%ebp)
142         cmpl    $-ETIMEDOUT, %ecx
143         jne     2b
145 18:     movl    $ETIMEDOUT, %ecx
146         jmp     9f
149 5:      xorl    %ecx, %ecx
150         movl    %gs:TID, %eax
151         movl    %eax, WRITER(%ebp)
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    %ecx, %eax
162         addl    $8, %esp
163         popl    %ebp
164         popl    %ebx
165         popl    %edi
166         popl    %esi
167         ret
170 #if MUTEX == 0
171         movl    %ebp, %ecx
172 #else
173         leal    MUTEX(%ebp), %ecx
174 #endif
175         call    __lll_mutex_lock_wait
176         jmp     2b
178 14:     cmpl    %gs:TID, %eax
179         jne     3b
180 20:     movl    $EDEADLK, %ecx
181         jmp     9b
184 #if MUTEX == 0
185         movl    %ebp, %eax
186 #else
187         leal    MUTEX(%ebp), %eax
188 #endif
189         call    __lll_mutex_unlock_wake
190         jmp     7b
192         /* Overflow.  */
193 4:      subl    $1, WRITERS_QUEUED(%ebp)
194         movl    $EAGAIN, %ecx
195         jmp     9b
198 #if MUTEX == 0
199         movl    %ebp, %eax
200 #else
201         leal    MUTEX(%ebp), %eax
202 #endif
203         call    __lll_mutex_unlock_wake
204         jmp     11b
207 #if MUTEX == 0
208         movl    %ebp, %ecx
209 #else
210         leal    MUTEX(%ebp), %ecx
211 #endif
212         call    __lll_mutex_lock_wait
213         jmp     13b
215 16:     movl    $-ETIMEDOUT, %ecx
216         jmp     17b
218 19:     movl    $EINVAL, %ecx
219         jmp     9b
220         .size   pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock