sem_timedwait implementation on Linux/SH.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_rwlock_timedrdlock.S
1 /* Copyright (C) 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <sysdep.h>
20 #include <lowlevelrwlock.h>
21 #include <tcb-offsets.h>
22 #include "lowlevel-atomic.h"
23
24 #define SYS_gettimeofday        __NR_gettimeofday
25 #define SYS_futex               240
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
28
29 #define EAGAIN          11
30 #define EDEADLK         35
31 #define ETIMEDOUT       110
32
33
34         .text
35
36         .globl  pthread_rwlock_timedrdlock
37         .type   pthread_rwlock_timedrdlock,@function
38         .align  5
39 pthread_rwlock_timedrdlock:
40         mov.l   r12, @-r15
41         mov.l   r9, @-r15
42         mov.l   r8, @-r15
43         sts.l   pr, @-r15
44         add     #-8, r15
45         mov     r4, r8
46         mov     r5, r9
47
48         /* Get the lock.  */
49         mov     #1, r3
50 #if MUTEX == 0
51         XADD    (r3, @r4, r2)
52 #else
53         XADD    (r3, @(MUTEX,r4), r2)
54 #endif
55         tst     r2, r2
56         bf      1f
57 2:
58         mov.l   @(WRITER,r8), r0
59         tst     r0, r0
60         bf      14f
61         mov.l   @(WRITERS_QUEUED,r8), r0
62         tst     r0, r0
63         bt      5f
64         mov.l   @(FLAGS,r8), r0
65         tst     r0, r0
66         bt      5f
67 3:
68         mov.l   @(READERS_QUEUED,r8), r0
69         add     #1, r0
70         mov.l   r0, @(READERS_QUEUED,r8)
71         tst     r0, r0
72         bt      4f
73
74 #if MUTEX == 0
75         DEC (@r8, r2)
76 #else
77         DEC (@(MUTEX,r8), r2)
78 #endif
79         tst     r2, r2
80         bf      10f
81
82 11:
83         /* Get current time.  */
84         mov     r15, r4
85         mov     #0, r5
86         mov     #SYS_gettimeofday, r3
87         trapa   #0x12
88         SYSCALL_INST_PAD
89
90         mov.l   @(4,r15), r0
91         mov.w   .L1k0, r1
92         dmulu.l r0, r1          /* Milli seconds to nano seconds.  */
93         mov.l   @r9, r2
94         mov.l   @(4,r9), r3
95         mov.l   @r15, r0
96         sts     macl, r1
97         sub     r0, r2
98         clrt
99         subc    r1, r3
100         bf      15f
101         mov.l   .L1g0, r1
102         add     r1, r3
103         add     #-1, r2
104 15:
105         cmp/pz  r2
106         bf      16f             /* Time is already up.  */
107
108         /* Store relative timeout.  */
109         mov.l   r2, @r15
110         mov.l   r3, @(4,r15)
111
112         /* Futex call.  */
113         mov     r15, r7
114         mov     #FUTEX_WAIT, r5
115         mov     #0, r6
116         mov     r8, r4
117         add     #READERS_WAKEUP, r4
118         mov     #SYS_futex, r3
119         extu.b  r3, r3
120         trapa   #0x14
121         SYSCALL_INST_PAD
122         mov     r0, r3
123
124 17:
125         /* Reget the lock.  */
126         mov     r8, r4
127         mov     #1, r5
128 #if MUTEX == 0
129         XADD    (r5, @r4, r2)
130 #else
131         XADD    (r5, @(MUTEX,r4), r2)
132 #endif
133         tst     r2, r2
134         bf      12f
135
136 13:
137         mov     #-ETIMEDOUT, r0
138         cmp/eq  r0, r3
139         bt      18f
140         mov.l   @(READERS_QUEUED,r8), r0
141         add     #-1, r0
142         mov.l   r0, @(READERS_QUEUED,r8)
143         tst     r0, r0
144         bf      2b
145         bra     2b
146          mov.l  r0, @(READERS_WAKEUP,r8)
147
148 5:
149         mov     #0, r3
150         mov.l   @(NR_READERS,r8), r0
151         add     #1, r0
152         mov.l   r0, @(NR_READERS,r8)
153         tst     r0, r0
154         bt      8f
155
156 9:
157 #if MUTEX == 0
158         DEC (@r8, r2)
159 #else
160         DEC (@(MUTEX,r8), r2)
161 #endif
162         tst     r2, r2
163         bf      6f
164 7:
165         add     #8,r15
166         lds.l   @r15+, pr
167         mov.l   @r15+, r8
168         mov.l   @r15+, r9
169         mov.l   @r15+, r12
170         rts
171          mov    r3, r0
172
173         .align  2
174 .L1k0:
175         .long   1000
176 .L1g0:
177         .long   1000000000
178
179 1:
180         mov     r8, r5
181 #if MUTEX != 0
182         add     #MUTEX, r5
183 #endif
184         mov     r2, r4
185         mov.l   .Lwait2, r1
186         bsrf    r1
187          nop
188 .Lwait2b:
189         bra     2b
190          nop
191 14:
192         stc     gbr, r1
193         mov.w   .Ltcboff,r2
194         sub     r2,r1
195         mov.l   @(8,r1),r1
196         cmp/eq  r1, r0
197         bf      3b
198         /* Deadlock detected.  */
199         bra     9b
200          mov    #EDEADLK, r3
201
202 6:
203         mov     r8, r4
204 #if MUTEX != 0
205         add     #MUTEX, r4
206 #endif
207         mov.l   .Lwake2, r1
208         bsrf    r1
209          nop
210 .Lwake2b:
211         bra     7b
212          mov    #0, r3
213
214 8:
215         /* Overflow.  */
216         mov.l   @(NR_READERS,r8), r1
217         add     #-1, r1
218         mov.l   r1, @(NR_READERS,r8)
219         bra     9b
220          mov    #EAGAIN, r3
221
222 4:
223         /* Overflow.  */
224         mov.l   @(READERS_QUEUED,r8), r1
225         add     #-1, r1
226         mov.l   r1, @(READERS_QUEUED,r8)
227         bra     9b
228          mov    #EAGAIN, r3
229
230 10:
231         mov     r8, r4
232 #if MUTEX != 0
233         add     #MUTEX, r4
234 #endif
235         mov.l   .Lwake3, r1
236         bsrf    r1
237          nop
238 .Lwake3b:
239         bra     11b
240          nop
241
242 12:
243         mov     r8, r5
244 #if MUTEX != 0
245         add     #MUTEX, r5
246 #endif
247         mov     r2, r4
248         mov.l   .Lwait3, r1
249         bsrf    r1
250          nop
251 .Lwait3b:
252         bra     13b
253          nop
254
255 16:
256         bra     17b
257          mov    #-ETIMEDOUT, r3
258
259 18:
260         bra     9b
261          mov    #ETIMEDOUT, r3
262
263 .Ltcboff:
264         .word   TLS_PRE_TCB_SIZE
265         .align  2
266 .Lwait2:        
267         .long   __lll_mutex_lock_wait-.Lwait2b
268 .Lwake2:
269         .long   __lll_mutex_unlock_wake-.Lwake2b
270 .Lwait3:        
271         .long   __lll_mutex_lock_wait-.Lwait3b
272 .Lwake3:
273         .long   __lll_mutex_unlock_wake-.Lwake3b
274         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock