pthread_cond_timedwait implementation for Linux/SH.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_timedwait.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 <shlib-compat.h>
21 #include <lowlevelcond.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 ETIMEDOUT               110
30
31
32         .text
33
34 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
35                                const struct timespec *abstime)  */
36         .globl  __pthread_cond_timedwait
37         .type   __pthread_cond_timedwait, @function
38         .align  5
39 __pthread_cond_timedwait:
40         mov.l   r12, @-r15
41         mov.l   r10, @-r15
42         mov.l   r9, @-r15
43         mov.l   r8, @-r15
44         sts.l   pr, @-r15
45         add     #-48, r15
46         mov     r4, r8
47         mov     r5, r9
48         mov     r6, r10
49
50         /* Get internal lock.  */
51         mov     #1, r3
52 #if cond_lock != 0
53         XADD (r3, @(cond_lock,r8), r2)
54 #else
55         XADD (r3, @r8, r2)
56 #endif
57         tst     r2, r2
58         bt      2f
59         bra     1f
60          nop
61 2:
62         /* Unlock the mutex.  */
63         mov.l   .Lmunlock1, r1
64         bsrf    r1
65          mov    r9, r4
66 .Lmunlock1b:
67
68         mov     #1, r2
69         mov     #0, r3
70
71         clrt
72         mov.l   @(total_seq,r8),r0
73         mov.l   @(total_seq+4,r8),r1
74         addc    r2, r0
75         addc    r3, r1
76         mov.l   r0,@(total_seq,r8)
77         mov.l   r1,@(total_seq+4,r8)
78
79         /* Install cancellation handler.  */
80 #ifdef PIC
81         mova    .Lgot1, r0
82         mov.l   .Lgot1, r12
83         add     r0, r12
84         mov.l   .Lccleanup1, r5
85         add     r12, r5
86 #else
87         mov.l   .Lccleanup1, r5
88 #endif
89         mov     r15, r4
90         add     #28, r4
91
92         mov.l   .Lccpush1, r1
93         bsrf    r1
94          mov    r8, r6
95 .Lccpush1b:
96
97         /* Get and store current wakeup_seq value.  */
98         mov.l   @(wakeup_seq,r8), r0
99         mov.l   @(wakeup_seq+4,r8), r1
100         mov.l   r0, @(12,r15)
101         mov.l   r1, @(16,r15)
102
103         /* Unlock.  */
104 8:
105 #if cond_lock != 0
106         DEC (@(cond_lock,r8), r2)
107 #else
108         DEC (@r8, r2)
109 #endif
110         tst     r2, r2
111         bt      4f
112         bra     3f
113          nop
114 4:
115         mov.l   .Lenable1, r1
116         bsrf    r1
117          nop
118 .Lenable1b:
119         mov.l   r0, @r15
120
121         /* Get current time.  */
122         mov     r15, r4
123         add     #4, r4
124         mov     #0, r5
125         mov     #SYS_gettimeofday, r3
126         trapa   #0x12
127         SYSCALL_INST_PAD
128
129         /* Compute relative timeout.  */
130         mov.l   @(8,r15), r0
131         mov.w   .L1k, r1
132         dmulu.l r0, r1          /* Milli seconds to nano seconds.  */
133         mov.l   @r10, r2
134         mov.l   @(4,r10), r3
135         mov.l   @(4,r15), r0
136         sts     macl, r1
137         sub     r0, r2
138         clrt
139         subc    r1, r3
140         bf      12f
141         mov.l   .L1g, r1
142         add     r1, r3
143         add     #-1, r2
144 12:
145         cmp/pz  r2
146         bf      13f             /* Time is already up.  */
147
148         /* Store relative timeout.  */
149         mov.l   r2, @(4,r15)
150         mov.l   r3, @(8,r15)
151
152         mov     r15, r7
153         add     #4, r7
154         mov     #FUTEX_WAIT, r5
155         mov.l   @(12,r15), r6
156         mov     r8, r4
157         add     #wakeup_seq, r4
158         mov     #SYS_futex, r3
159         extu.b  r3, r3
160         trapa   #0x14
161         SYSCALL_INST_PAD
162         mov.l   r0, @(20,r15)
163
164         mov.l   .Ldisable1, r1
165         bsrf    r1
166          mov.l  @r15, r4
167 .Ldisable1b:    
168
169         /* Lock.  */
170         mov     #1, r3
171 #if cond_lock != 0
172         XADD (r3, @(cond_lock,r8), r2)
173 #else
174         XADD (r3, @r8, r2)
175 #endif
176         tst     r2, r2
177         bf      5f
178 6:
179         mov.l   @(woken_seq,r8), r0
180         mov.l   @(woken_seq+4,r8), r1
181
182         mov.l   @(wakeup_seq,r8), r2
183         mov.l   @(wakeup_seq+4,r8), r3
184
185         mov.l   @(16,r15), r5
186         cmp/hi  r5, r1
187         bt      7f
188         cmp/hi  r1, r5
189         bt      15f
190
191         mov.l   @(12,r15), r5
192         cmp/hi  r0, r5
193         bt      15f
194 7:
195         cmp/hi  r1, r3
196         bt      9f
197         cmp/hi  r3, r1
198         bt      15f
199         cmp/hi  r0, r2
200         bt      9f
201 15:
202         mov.l   @(20,r15),r0
203         cmp/eq  #-ETIMEDOUT, r0
204         bf      8b
205 13:
206         mov     #1, r2
207         mov     #0, r3
208
209         clrt
210         mov.l   @(wakeup_seq,r8),r0
211         mov.l   @(wakeup_seq+4,r8),r1
212         addc    r2, r0
213         addc    r3, r1
214         mov.l   r0,@(wakeup_seq,r8)
215         mov.l   r1,@(wakeup_seq+4,r8)
216         mov     #ETIMEDOUT, r0
217         bra     14f
218          mov.l  r0, @(24,r15)
219
220 9:
221         mov     #0, r0
222         mov.l   r0, @(24,r15)
223 14:
224         mov     #1, r2
225         mov     #0, r3
226
227         clrt
228         mov.l   @(woken_seq,r8),r0
229         mov.l   @(woken_seq+4,r8),r1
230         addc    r2, r0
231         addc    r3, r1
232         mov.l   r0,@(woken_seq,r8)
233         mov.l   r1,@(woken_seq+4,r8)
234
235 #if cond_lock != 0
236         DEC (@(cond_lock,r8), r2)
237 #else
238         DEC (@r8, r2)
239 #endif
240         tst     r2, r2
241         bf      10f
242
243 11:
244         /* Remove cancellation handler.  */
245         mov     r15, r4
246         add     #28, r4
247         mov.l   .Lcpop1, r1
248         bsrf    r1
249          mov    #0, r5
250 .Lcpop1b:
251
252         mov     r9, r4
253         mov.l   .Lmlocki1, r1
254         bsrf    r1
255          mov    #0, r5
256 .Lmlocki1b:
257
258         mov.l   @(24,r15), r0
259
260         add     #48, r15
261
262         /* We return the result of the mutex_lock operation.  */
263         lds.l   @r15+, pr
264         mov.l   @r15+, r8
265         mov.l   @r15+, r9
266         mov.l   @r15+, r10
267         rts
268          mov.l  @r15+, r12
269         ret
270
271 .L1k:
272         .word   1000
273         .align  2
274 .Lmunlock1:
275         .long   __pthread_mutex_unlock_internal-.Lmunlock1b
276 #ifdef PIC
277 .Lgot1:
278         .long   _GLOBAL_OFFSET_TABLE_
279 .Lccleanup1:
280         .long   __condvar_cleanup@GOTOFF
281 #else
282 .Lccleanup1:
283         .long   __condvar_cleanup
284 #endif
285 .Lccpush1:
286         .long   __pthread_cleanup_push-.Lccpush1b
287 .Lenable1:
288         .long   __pthread_enable_asynccancel-.Lenable1b
289 .Ldisable1:
290         .long   __pthread_disable_asynccancel-.Ldisable1b
291 .Lcpop1:
292         .long   __pthread_cleanup_pop-.Lcpop1b
293 .Lmlocki1:
294         .long   __pthread_mutex_lock_internal-.Lmlocki1b
295 .L1g:
296         .long   1000000000
297
298 1:
299         /* Initial locking failed.  */
300         mov     r8, r5
301 #if cond_lock != 0
302         add     #cond_lock, r5
303 #endif
304         mov.l   .Lmwait2, r1
305         bsrf    r1
306          mov    r2, r4
307 .Lmwait2b:
308         bra     2b
309          nop
310
311 3:
312         /* Unlock in loop requires waekup.  */
313         mov     r8, r4
314 #if cond_lock != 0
315         add     #cond_lock, r4
316 #endif
317         mov.l   .Lmwake2, r1
318         bsrf    r1
319          nop
320 .Lmwake2b:
321         bra     4b
322          nop
323
324 5:
325         /* Locking in loop failed.  */
326         mov     r8, r5
327 #if cond_lock != 0
328         add     #cond_lock, r5
329 #endif
330         mov.l   .Lmwait3, r1
331         bsrf    r1
332          mov    r2, r4
333 .Lmwait3b:
334         bra     6b
335          nop
336
337 10:
338         /* Unlock after loop requires waekup.  */
339         mov     r8, r4
340 #if cond_lock != 0
341         add     #cond_lock, r4
342 #endif
343         mov.l   .Lmwake3, r1
344         bsrf    r1
345          nop
346 .Lmwake3b:
347         bra     11b
348          nop
349
350         .align  2
351 .Lmwait2:
352         .long   __lll_mutex_lock_wait-.Lmwait2b
353 .Lmwake2:
354         .long   __lll_mutex_unlock_wake-.Lmwake2b
355 .Lmwait3:
356         .long   __lll_mutex_lock_wait-.Lmwait3b
357 .Lmwake3:
358         .long   __lll_mutex_unlock_wake-.Lmwake3b
359         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
360 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
361                   GLIBC_2_3_2)