Updated to fedora-glibc-20090204T2135
[glibc/history.git] / nptl / sysdeps / unix / sysv / linux / sh / lowlevellock.S
blobc051192cee063ac03eb391923a5f620ef789cc57
1 /* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
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 <pthread-errnos.h>
22 #include <kernel-features.h>
23 #include <lowlevellock.h>
24 #include "lowlevel-atomic.h"
26         .text
28 #ifdef __ASSUME_PRIVATE_FUTEX
29 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
30         mov     #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg; \
31         extu.b  reg, reg
32 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
33         mov     #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg; \
34         extu.b  reg, reg
35 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
36         mov     #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \
37         extu.b  tmp, tmp; \
38         xor     tmp, reg
39 # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
40         mov     #(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), tmp; \
41         extu.b  tmp, tmp; \
42         mov     #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
43         swap.b  tmp2, tmp2; \
44         or      tmp2, tmp; \
45         xor     tmp, reg
46 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
47         mov     #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \
48         extu.b  tmp, tmp; \
49         xor     tmp, reg
50 #else
51 # if FUTEX_WAIT == 0
52 #  define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
53         stc     gbr, tmp        ; \
54         mov.w   99f, reg        ; \
55         add     reg, tmp        ; \
56         bra     98f             ; \
57          mov.l  @tmp, reg       ; \
58 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
59 98:
60 # else
61 #  define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
62         stc     gbr, tmp        ; \
63         mov.w   99f, reg        ; \
64         add     reg, tmp        ; \
65         mov.l   @tmp, reg       ; \
66         bra     98f             ; \
67          mov    #FUTEX_WAIT, tmp ; \
68 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
69 98:     or      tmp, reg
70 # endif
71 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
72         stc     gbr, tmp        ; \
73         mov.w   99f, reg        ; \
74         add     reg, tmp        ; \
75         mov.l   @tmp, reg       ; \
76         bra     98f             ; \
77          mov    #FUTEX_WAKE, tmp ; \
78 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
79 98:     or      tmp, reg
80 # if FUTEX_WAIT == 0
81 #  define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
82         stc     gbr, tmp        ; \
83         mov.w   99f, tmp2       ; \
84         add     tmp2, tmp       ; \
85         mov.l   @tmp, tmp2      ; \
86         bra     98f             ; \
87          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
88 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
89 98:     extu.b  tmp, tmp        ; \
90         xor     tmp, reg        ; \
91         and     tmp2, reg
92 # else
93 #  define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
94         stc     gbr, tmp        ; \
95         mov.w   99f, tmp2       ; \
96         add     tmp2, tmp       ; \
97         mov.l   @tmp, tmp2      ; \
98         bra     98f             ; \
99          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
100 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
101 98:     extu.b  tmp, tmp        ; \
102         xor     tmp, reg        ; \
103         and     tmp2, reg       ; \
104         mov     #FUTEX_WAIT, tmp ; \
105         or      tmp, reg
106 #  define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
107         stc     gbr, tmp        ; \
108         mov.w   99f, tmp2       ; \
109         add     tmp2, tmp       ; \
110         mov.l   @tmp, tmp2      ; \
111         bra     98f             ; \
112          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
113 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
114 98:     extu.b  tmp, tmp        ; \
115         xor     tmp, reg        ; \
116         and     tmp2, reg       ; \
117         mov     #FUTEX_WAIT_BITSET, tmp ; \
118         mov     #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
119         swap.b  tmp2, tmp2; \
120         or      tmp2, tmp; \
121         or      tmp, reg
122 # endif
123 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
124         stc     gbr, tmp        ; \
125         mov.w   99f, tmp2       ; \
126         add     tmp2, tmp       ; \
127         mov.l   @tmp, tmp2      ; \
128         bra     98f             ; \
129          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
130 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
131 98:     extu.b  tmp, tmp        ; \
132         xor     tmp, reg        ; \
133         and     tmp2, reg       ; \
134         mov     #FUTEX_WAKE, tmp ; \
135         or      tmp, reg
136 #endif
138         .globl  __lll_lock_wait_private
139         .type   __lll_lock_wait_private,@function
140         .hidden __lll_lock_wait_private
141         .align  5
142         cfi_startproc
143 __lll_lock_wait_private:
144         mov.l   r8, @-r15
145         cfi_adjust_cfa_offset(4)
146         cfi_rel_offset (r8, 0)
147         mov     r4, r6
148         mov     r5, r8
149         mov     #0, r7          /* No timeout.  */
150         LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
152         mov     #2, r4
153         cmp/eq  r4, r6
154         bf      2f
157         mov     r8, r4
158         mov     #SYS_futex, r3
159         extu.b  r3, r3
160         trapa   #0x14
161         SYSCALL_INST_PAD
164         mov     #2, r6
165         XCHG (r6, @r8, r2)
166         tst     r2, r2
167         bf      1b
169         mov.l   @r15+, r8
170         rts
171          mov    r2, r0
172         cfi_endproc
173         .size   __lll_lock_wait_private,.-__lll_lock_wait_private
175 #ifdef NOT_IN_libc
176         .globl  __lll_lock_wait
177         .type   __lll_lock_wait,@function
178         .hidden __lll_lock_wait
179         .align  5
180         cfi_startproc
181 __lll_lock_wait:
182         mov.l   r9, @-r15
183         cfi_adjust_cfa_offset(4)
184         cfi_rel_offset (r9, 0)
185         mov.l   r8, @-r15
186         cfi_adjust_cfa_offset(4)
187         cfi_rel_offset (r8, 0)
188         mov     r6, r9
189         mov     r4, r6
190         mov     r5, r8
191         mov     #0, r7          /* No timeout.  */
192         mov     r9, r5
193         LOAD_FUTEX_WAIT (r5, r0, r1)
195         mov     #2, r4
196         cmp/eq  r4, r6
197         bf      2f
200         mov     r8, r4
201         mov     #SYS_futex, r3
202         extu.b  r3, r3
203         trapa   #0x14
204         SYSCALL_INST_PAD
207         mov     #2, r6
208         XCHG (r6, @r8, r2)
209         tst     r2, r2
210         bf      1b
212         mov.l   @r15+, r8
213         mov.l   @r15+, r9
214         ret
215          mov    r2, r0
216         cfi_endproc
217         .size   __lll_lock_wait,.-__lll_lock_wait
219         /*      r5  (r8): futex
220                 r7 (r11): flags
221                 r6  (r9): timeout
222                 r4 (r10): futex value
223         */
224         .globl  __lll_timedlock_wait
225         .type   __lll_timedlock_wait,@function
226         .hidden __lll_timedlock_wait
227         .align  5
228         cfi_startproc
229 __lll_timedlock_wait:
230         mov.l   r12, @-r15
231         cfi_adjust_cfa_offset(4)
232         cfi_rel_offset (r12, 0)
234 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
235         mov.l   .Lhave, r1
236 #  ifdef PIC
237         mova    .Lgot, r0
238         mov.l   .Lgot, r12
239         add     r0, r12
240         add     r12, r1
241 #  endif
242         mov.l   @r1, r0
243         tst     r0, r0
244         bt      .Lreltmo
245 # endif
247         mov     r4, r2
248         mov     r5, r4
249         mov     r7, r5
250         mov     r6, r7
251         LOAD_FUTEX_WAIT_ABS (r5, r0, r1)
253         mov     #2, r6
254         cmp/eq  r6, r2
255         bf/s    2f
256          mov    r2, r6
259         mov     #2, r6
260         mov     #-1, r1
261         mov     #SYS_futex, r3
262         extu.b  r3, r3
263         trapa   #0x16
264         SYSCALL_INST_PAD
265         mov     r0, r6
268         XCHG    (r2, @r4, r3)   /* NB:   lock is implied */
270         tst     r3, r3
271         bt/s    3f
272          mov    r6, r0
274         cmp/eq  #-ETIMEDOUT, r0
275         bt      4f
276         cmp/eq  #-EINVAL, r0
277         bf      1b
279         neg     r0, r3
281         mov     r3, r0
282         rts
283          mov.l  @r15+, r12
285         .align  2
286 # ifdef PIC
287 .Lgot:
288         .long   _GLOBAL_OFFSET_TABLE_
289 .Lhave:
290         .long   __have_futex_clock_realtime@GOTOFF
291 # else
292 .Lhave:
293         .long   __have_futex_clock_realtime
294 # endif
296 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
297 .Lreltmo:
298         /* Check for a valid timeout value.  */
299         mov.l   @(4,r6), r1
300         mov.l   .L1g, r0
301         cmp/hs  r0, r1
302         bt      3f
304         mov.l   r11, @-r15
305         cfi_adjust_cfa_offset(4)
306         cfi_rel_offset (r11, 0)
307         mov.l   r10, @-r15
308         cfi_adjust_cfa_offset(4)
309         cfi_rel_offset (r10, 0)
310         mov.l   r9, @-r15
311         cfi_adjust_cfa_offset(4)
312         cfi_rel_offset (r9, 0)
313         mov.l   r8, @-r15
314         cfi_adjust_cfa_offset(4)
315         cfi_rel_offset (r8, 0)
316         mov     r7, r11
317         mov     r4, r10
318         mov     r6, r9
319         mov     r5, r8
321         /* Stack frame for the timespec and timeval structs.  */
322         add     #-8, r15
323         cfi_adjust_cfa_offset(8)
325         mov     #2, r2
326         XCHG (r2, @r8, r3)
328         tst     r3, r3
329         bt      6f
330         
332         /* Get current time.  */
333         mov     r15, r4
334         mov     #0, r5
335         mov     #__NR_gettimeofday, r3
336         trapa   #0x12
337         SYSCALL_INST_PAD
339         /* Compute relative timeout.  */
340         mov.l   @(4,r15), r0
341         mov.w   .L1k, r1
342         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
343         mov.l   @r9, r2
344         mov.l   @(4,r9), r3
345         mov.l   @r15, r0
346         sts     macl, r1
347         sub     r0, r2
348         clrt
349         subc    r1, r3
350         bf      4f
351         mov.l   .L1g, r1
352         add     r1, r3
353         add     #-1, r2
355         cmp/pz  r2
356         bf      2f              /* Time is already up.  */
358         mov.l   r2, @r15        /* Store relative timeout.  */
359         mov.l   r3, @(4,r15)
361         mov     r8, r4
362         mov     r11, r5
363         LOAD_FUTEX_WAIT (r5, r0, r1)
364         mov     r10, r6
365         mov     r15, r7
366         mov     #SYS_futex, r3
367         extu.b  r3, r3
368         trapa   #0x14
369         SYSCALL_INST_PAD
370         mov     r0, r5
372         mov     #2, r2
373         XCHG (r2, @r8, r3)
375         tst     r3, r3
376         bt/s    6f
377          mov    #-ETIMEDOUT, r1
378         cmp/eq  r5, r1
379         bf      1b
381 2:      mov     #ETIMEDOUT, r3
384         mov     r3, r0
385         add     #8, r15
386         mov.l   @r15+, r8
387         mov.l   @r15+, r9
388         mov.l   @r15+, r10
389         mov.l   @r15+, r11
390         rts
391          mov.l  @r15+, r12
394         mov.l   @r15+, r12
395         rts
396          mov    #EINVAL, r0
397 # endif
398         cfi_endproc
400 .L1k:
401         .word   1000
402         .align  2
403 .L1g:
404         .long   1000000000
406         .size   __lll_timedlock_wait,.-__lll_timedlock_wait
407 #endif
409         .globl  __lll_unlock_wake_private
410         .type   __lll_unlock_wake_private,@function
411         .hidden __lll_unlock_wake_private
412         .align  5
413         cfi_startproc
414 __lll_unlock_wake_private:
415         LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
416         mov     #1, r6          /* Wake one thread.  */
417         mov     #0, r7
418         mov.l   r7, @r4         /* Stores 0.  */
419         mov     #SYS_futex, r3
420         extu.b  r3, r3
421         trapa   #0x14
422         SYSCALL_INST_PAD
423         rts
424          nop
425         cfi_endproc
426         .size   __lll_unlock_wake_private,.-__lll_unlock_wake_private
428 #ifdef NOT_IN_libc
429         .globl  __lll_unlock_wake
430         .type   __lll_unlock_wake,@function
431         .hidden __lll_unlock_wake
432         .align  5
433         cfi_startproc
434 __lll_unlock_wake:
435         LOAD_FUTEX_WAKE (r5, r0, r1)
436         mov     #1, r6          /* Wake one thread.  */
437         mov     #0, r7
438         mov.l   r7, @r4         /* Stores 0.  */
439         mov     #SYS_futex, r3
440         extu.b  r3, r3
441         trapa   #0x14
442         SYSCALL_INST_PAD
443         rts
444          nop
445         cfi_endproc
446         .size   __lll_unlock_wake,.-__lll_unlock_wake
448         .globl  __lll_timedwait_tid
449         .type   __lll_timedwait_tid,@function
450         .hidden __lll_timedwait_tid
451         .align  5
452         cfi_startproc
453 __lll_timedwait_tid:
454         mov.l   r9, @-r15
455         cfi_adjust_cfa_offset(4)
456         cfi_rel_offset (r9, 0)
457         mov.l   r8, @-r15
458         cfi_adjust_cfa_offset(4)
459         cfi_rel_offset (r8, 0)
460         mov     r4, r8
461         mov     r5, r9
463         /* Stack frame for the timespec and timeval structs.  */
464         add     #-8, r15
465         cfi_adjust_cfa_offset(8)
468         /* Get current time.  */
469         mov     r15, r4
470         mov     #0, r5
471         mov     #__NR_gettimeofday, r3
472         trapa   #0x12
473         SYSCALL_INST_PAD
475         /* Compute relative timeout.  */
476         mov.l   @(4,r15), r0
477         mov.w   .L1k2, r1
478         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
479         mov.l   @r9, r2
480         mov.l   @(4,r9), r3
481         mov.l   @r15, r0
482         sts     macl, r1
483         sub     r0, r2
484         clrt
485         subc    r1, r3
486         bf      5f
487         mov.l   .L1g2, r1
488         add     r1, r3
489         add     #-1, r2
491         cmp/pz  r2
492         bf      6f              /* Time is already up.  */
494         mov.l   r2, @r15        /* Store relative timeout.  */
495         mov.l   r3, @(4,r15)
497         mov.l   @r8, r2
498         tst     r2, r2
499         bt      4f
501         mov     r8, r4
502         /* XXX The kernel so far uses global futex for the wakeup at
503            all times.  */
504         mov     #0, r5
505         extu.b  r5, r5
506         mov     r2, r6
507         mov     r15, r7
508         mov     #SYS_futex, r3
509         extu.b  r3, r3
510         trapa   #0x14
511         SYSCALL_INST_PAD
513         mov.l   @r8, r2
514         tst     r2, r2
515         bf      1f
517         mov     #0, r0
519         add     #8, r15
520         mov.l   @r15+, r8
521         rts
522          mov.l  @r15+, r9
524         /* Check whether the time expired.  */
525         mov     #-ETIMEDOUT, r1
526         cmp/eq  r0, r1
527         bf      2b
529         bra     3b
530          mov    #ETIMEDOUT, r0
531         cfi_endproc
533 .L1k2:
534         .word   1000
535         .align  2
536 .L1g2:
537         .long   1000000000
538         .size   __lll_timedwait_tid,.-__lll_timedwait_tid
539 #endif