Updated to fedora-glibc-20080612T1619
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_timedwrlock.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 <kernel-features.h>
25
26
27         .text
28
29         .globl  pthread_rwlock_timedwrlock
30         .type   pthread_rwlock_timedwrlock,@function
31         .align  16
32 pthread_rwlock_timedwrlock:
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)
48
49         movl    28(%esp), %ebp
50         movl    32(%esp), %edi
51
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
62
63 2:      movl    WRITER(%ebp), %eax
64         testl   %eax, %eax
65         jne     14f
66         cmpl    $0, NR_READERS(%ebp)
67         je      5f
68
69         /* Check the value of the timeout parameter.  */
70 3:      cmpl    $1000000000, 4(%edi)
71         jae     19f
72
73         addl    $1, WRITERS_QUEUED(%ebp)
74         je      4f
75
76         movl    WRITERS_WAKEUP(%ebp), %esi
77
78         LOCK
79 #if MUTEX == 0
80         subl    $1, (%ebp)
81 #else
82         subl    $1, MUTEX(%ebp)
83 #endif
84         jne     10f
85
86         /* Get current time.  */
87 11:     movl    %esp, %ebx
88         xorl    %ecx, %ecx
89         movl    $__NR_gettimeofday, %eax
90         ENTER_KERNEL
91
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.  */
105
106         /* Futex call.  */
107         movl    %ecx, (%esp)    /* Store relative timeout.  */
108         movl    %edx, 4(%esp)
109
110         movl    %esi, %edx
111 #ifdef __ASSUME_PRIVATE_FUTEX
112         movzbl  PSHARED(%ebp), %ecx
113         xorl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
114 #else
115         movzbl  PSHARED(%ebp), %ecx
116 # if FUTEX_WAIT != 0
117         orl     $FUTEX_WAIT, %ecx
118 # endif
119         xorl    %gs:PRIVATE_FUTEX, %ecx
120 #endif
121         movl    %esp, %esi
122         leal    WRITERS_WAKEUP(%ebp), %ebx
123         movl    $SYS_futex, %eax
124         ENTER_KERNEL
125         movl    %eax, %esi
126 17:
127
128         /* Reget the lock.  */
129         movl    $1, %edx
130         xorl    %eax, %eax
131         LOCK
132 #if MUTEX == 0
133         cmpxchgl %edx, (%ebp)
134 #else
135         cmpxchgl %edx, MUTEX(%ebp)
136 #endif
137         jnz     12f
138
139 13:     subl    $1, WRITERS_QUEUED(%ebp)
140         cmpl    $-ETIMEDOUT, %esi
141         jne     2b
142
143 18:     movl    $ETIMEDOUT, %edx
144         jmp     9f
145
146
147 5:      xorl    %edx, %edx
148         movl    %gs:TID, %eax
149         movl    %eax, WRITER(%ebp)
150 9:      LOCK
151 #if MUTEX == 0
152         subl    $1, (%ebp)
153 #else
154         subl    $1, MUTEX(%ebp)
155 #endif
156         jne     6f
157
158 7:      movl    %edx, %eax
159
160         addl    $8, %esp
161         cfi_adjust_cfa_offset(-8)
162         popl    %ebp
163         cfi_adjust_cfa_offset(-4)
164         cfi_restore(%ebp)
165         popl    %ebx
166         cfi_adjust_cfa_offset(-4)
167         cfi_restore(%ebx)
168         popl    %edi
169         cfi_adjust_cfa_offset(-4)
170         cfi_restore(%edi)
171         popl    %esi
172         cfi_adjust_cfa_offset(-4)
173         cfi_restore(%esi)
174         ret
175
176         cfi_adjust_cfa_offset(24)
177         cfi_offset(%esi, -8)
178         cfi_offset(%edi, -12)
179         cfi_offset(%ebx, -16)
180         cfi_offset(%ebp, -20)
181 1:
182 #if MUTEX == 0
183         movl    %ebp, %edx
184 #else
185         leal    MUTEX(%ebp), %edx
186 #endif
187         movzbl  PSHARED(%ebp), %ecx
188         call    __lll_lock_wait
189         jmp     2b
190
191 14:     cmpl    %gs:TID, %eax
192         jne     3b
193 20:     movl    $EDEADLK, %edx
194         jmp     9b
195
196 6:
197 #if MUTEX == 0
198         movl    %ebp, %eax
199 #else
200         leal    MUTEX(%ebp), %eax
201 #endif
202         movzbl  PSHARED(%ebp), %ecx
203         call    __lll_unlock_wake
204         jmp     7b
205
206         /* Overflow.  */
207 4:      subl    $1, WRITERS_QUEUED(%ebp)
208         movl    $EAGAIN, %edx
209         jmp     9b
210
211 10:
212 #if MUTEX == 0
213         movl    %ebp, %eax
214 #else
215         leal    MUTEX(%ebp), %eax
216 #endif
217         movzbl  PSHARED(%ebp), %ecx
218         call    __lll_unlock_wake
219         jmp     11b
220
221 12:
222 #if MUTEX == 0
223         movl    %ebp, %edx
224 #else
225         leal    MUTEX(%ebp), %edx
226 #endif
227         movzbl  PSHARED(%ebp), %ecx
228         call    __lll_lock_wait
229         jmp     13b
230
231 16:     movl    $-ETIMEDOUT, %esi
232         jmp     17b
233
234 19:     movl    $EINVAL, %edx
235         jmp     9b
236         cfi_endproc
237         .size   pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock