2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / lowlevellock.S
blobd8279173d73d87d5e8858faf97ccd841e1a719c5
1 /* Copyright (C) 2003, 2004, 2005, 2007, 2008
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_WAKE(reg,tmp,tmp2) \
40         mov     #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \
41         extu.b  tmp, tmp; \
42         xor     tmp, reg
43 #else
44 # if FUTEX_WAIT == 0
45 #  define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
46         stc     gbr, tmp        ; \
47         mov.w   99f, reg        ; \
48         add     reg, tmp        ; \
49         bra     98f             ; \
50          mov.l  @tmp, reg       ; \
51 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
52 98:
53 # else
54 #  define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
55         stc     gbr, tmp        ; \
56         mov.w   99f, reg        ; \
57         add     reg, tmp        ; \
58         mov.l   @tmp, reg       ; \
59         bra     98f             ; \
60          mov    #FUTEX_WAIT, tmp ; \
61 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
62 98:     or      tmp, reg
63 # endif
64 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
65         stc     gbr, tmp        ; \
66         mov.w   99f, reg        ; \
67         add     reg, tmp        ; \
68         mov.l   @tmp, reg       ; \
69         bra     98f             ; \
70          mov    #FUTEX_WAKE, tmp ; \
71 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
72 98:     or      tmp, reg
73 # if FUTEX_WAIT == 0
74 #  define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
75         stc     gbr, tmp        ; \
76         mov.w   99f, tmp2       ; \
77         add     tmp2, tmp       ; \
78         mov.l   @tmp, tmp2      ; \
79         bra     98f             ; \
80          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
81 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
82 98:     extu.b  tmp, tmp        ; \
83         xor     tmp, reg        ; \
84         and     tmp2, reg
85 # else
86 #  define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
87         stc     gbr, tmp        ; \
88         mov.w   99f, tmp2       ; \
89         add     tmp2, tmp       ; \
90         mov.l   @tmp, tmp2      ; \
91         bra     98f             ; \
92          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
93 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
94 98:     extu.b  tmp, tmp        ; \
95         xor     tmp, reg        ; \
96         and     tmp2, reg       ; \
97         mov     #FUTEX_WAIT, tmp ; \
98         or      tmp, reg
99 # endif
100 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
101         stc     gbr, tmp        ; \
102         mov.w   99f, tmp2       ; \
103         add     tmp2, tmp       ; \
104         mov.l   @tmp, tmp2      ; \
105         bra     98f             ; \
106          mov    #FUTEX_PRIVATE_FLAG, tmp ; \
107 99:     .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
108 98:     extu.b  tmp, tmp        ; \
109         xor     tmp, reg        ; \
110         and     tmp2, reg       ; \
111         mov     #FUTEX_WAKE, tmp ; \
112         or      tmp, reg
113 #endif
115         .globl  __lll_lock_wait_private
116         .type   __lll_lock_wait_private,@function
117         .hidden __lll_lock_wait_private
118         .align  5
119         cfi_startproc
120 __lll_lock_wait_private:
121         mov.l   r8, @-r15
122         cfi_adjust_cfa_offset(4)
123         cfi_rel_offset (r8, 0)
124         mov     r4, r6
125         mov     r5, r8
126         mov     #0, r7          /* No timeout.  */
127         LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
129         mov     #2, r4
130         cmp/eq  r4, r6
131         bf      2f
134         mov     r8, r4
135         mov     #SYS_futex, r3
136         extu.b  r3, r3
137         trapa   #0x14
138         SYSCALL_INST_PAD
141         mov     #2, r6
142         XCHG (r6, @r8, r2)
143         tst     r2, r2
144         bf      1b
146         mov.l   @r15+, r8
147         rts
148          mov    r2, r0
149         cfi_endproc
150         .size   __lll_lock_wait_private,.-__lll_lock_wait_private
152 #ifdef NOT_IN_libc
153         .globl  __lll_lock_wait
154         .type   __lll_lock_wait,@function
155         .hidden __lll_lock_wait
156         .align  5
157         cfi_startproc
158 __lll_lock_wait:
159         mov.l   r9, @-r15
160         cfi_adjust_cfa_offset(4)
161         cfi_rel_offset (r9, 0)
162         mov.l   r8, @-r15
163         cfi_adjust_cfa_offset(4)
164         cfi_rel_offset (r8, 0)
165         mov     r6, r9
166         mov     r4, r6
167         mov     r5, r8
168         mov     #0, r7          /* No timeout.  */
169         mov     r9, r5
170         LOAD_FUTEX_WAIT (r5, r0, r1)
172         mov     #2, r4
173         cmp/eq  r4, r6
174         bf      2f
177         mov     r8, r4
178         mov     #SYS_futex, r3
179         extu.b  r3, r3
180         trapa   #0x14
181         SYSCALL_INST_PAD
184         mov     #2, r6
185         XCHG (r6, @r8, r2)
186         tst     r2, r2
187         bf      1b
189         mov.l   @r15+, r8
190         mov.l   @r15+, r9
191         ret
192          mov    r2, r0
193         cfi_endproc
194         .size   __lll_lock_wait,.-__lll_lock_wait
196         .globl  __lll_timedlock_wait
197         .type   __lll_timedlock_wait,@function
198         .hidden __lll_timedlock_wait
199         .align  5
200         cfi_startproc
201 __lll_timedlock_wait:
202         /* Check for a valid timeout value.  */
203         mov.l   @(4,r6), r1
204         mov.l   .L1g, r0
205         cmp/hs  r0, r1
206         bt      3f
208         mov.l   r11, @-r15
209         cfi_adjust_cfa_offset(4)
210         cfi_rel_offset (r11, 0)
211         mov.l   r10, @-r15
212         cfi_adjust_cfa_offset(4)
213         cfi_rel_offset (r10, 0)
214         mov.l   r9, @-r15
215         cfi_adjust_cfa_offset(4)
216         cfi_rel_offset (r9, 0)
217         mov.l   r8, @-r15
218         cfi_adjust_cfa_offset(4)
219         cfi_rel_offset (r8, 0)
220         mov     r7, r11
221         mov     r4, r10
222         mov     r6, r9
223         mov     r5, r8
225         /* Stack frame for the timespec and timeval structs.  */
226         add     #-8, r15
227         cfi_adjust_cfa_offset(8)
229         mov     #2, r2
230         XCHG (r2, @r8, r3)
232         tst     r3, r3
233         bt      6f
234         
236         /* Get current time.  */
237         mov     r15, r4
238         mov     #0, r5
239         mov     #__NR_gettimeofday, r3
240         trapa   #0x12
241         SYSCALL_INST_PAD
243         /* Compute relative timeout.  */
244         mov.l   @(4,r15), r0
245         mov.w   .L1k, r1
246         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
247         mov.l   @r9, r2
248         mov.l   @(4,r9), r3
249         mov.l   @r15, r0
250         sts     macl, r1
251         sub     r0, r2
252         clrt
253         subc    r1, r3
254         bf      4f
255         mov.l   .L1g, r1
256         add     r1, r3
257         add     #-1, r2
259         cmp/pz  r2
260         bf      2f              /* Time is already up.  */
262         mov.l   r2, @r15        /* Store relative timeout.  */
263         mov.l   r3, @(4,r15)
265         mov     r8, r4
266         mov     r11, r5
267         LOAD_FUTEX_WAIT (r5, r0, r1)
268         mov     r10, r6
269         mov     r15, r7
270         mov     #SYS_futex, r3
271         extu.b  r3, r3
272         trapa   #0x14
273         SYSCALL_INST_PAD
274         mov     r0, r5
276         mov     #2, r2
277         XCHG (r2, @r8, r3)
279         tst     r3, r3
280         bt/s    6f
281          mov    #-ETIMEDOUT, r1
282         cmp/eq  r5, r1
283         bf      1b
285 2:      mov     #ETIMEDOUT, r3
288         mov     r3, r0
289         add     #8, r15
290         mov.l   @r15+, r8
291         mov.l   @r15+, r9
292         mov.l   @r15+, r10
293         rts
294          mov.l  @r15+, r11
297         rts
298          mov    #EINVAL, r0
299         cfi_endproc
301 .L1k:
302         .word   1000
303         .align  2
304 .L1g:
305         .long   1000000000
307         .size   __lll_timedlock_wait,.-__lll_timedlock_wait
308 #endif
310         .globl  __lll_unlock_wake_private
311         .type   __lll_unlock_wake_private,@function
312         .hidden __lll_unlock_wake_private
313         .align  5
314         cfi_startproc
315 __lll_unlock_wake_private:
316         LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
317         mov     #1, r6          /* Wake one thread.  */
318         mov     #0, r7
319         mov.l   r7, @r4         /* Stores 0.  */
320         mov     #SYS_futex, r3
321         extu.b  r3, r3
322         trapa   #0x14
323         SYSCALL_INST_PAD
324         rts
325          nop
326         cfi_endproc
327         .size   __lll_unlock_wake_private,.-__lll_unlock_wake_private
329 #ifdef NOT_IN_libc
330         .globl  __lll_unlock_wake
331         .type   __lll_unlock_wake,@function
332         .hidden __lll_unlock_wake
333         .align  5
334         cfi_startproc
335 __lll_unlock_wake:
336         LOAD_FUTEX_WAKE (r5, r0, r1)
337         mov     #1, r6          /* Wake one thread.  */
338         mov     #0, r7
339         mov.l   r7, @r4         /* Stores 0.  */
340         mov     #SYS_futex, r3
341         extu.b  r3, r3
342         trapa   #0x14
343         SYSCALL_INST_PAD
344         rts
345          nop
346         cfi_endproc
347         .size   __lll_unlock_wake,.-__lll_unlock_wake
349         .globl  __lll_timedwait_tid
350         .type   __lll_timedwait_tid,@function
351         .hidden __lll_timedwait_tid
352         .align  5
353         cfi_startproc
354 __lll_timedwait_tid:
355         mov.l   r9, @-r15
356         cfi_adjust_cfa_offset(4)
357         cfi_rel_offset (r9, 0)
358         mov.l   r8, @-r15
359         cfi_adjust_cfa_offset(4)
360         cfi_rel_offset (r8, 0)
361         mov     r4, r8
362         mov     r5, r9
364         /* Stack frame for the timespec and timeval structs.  */
365         add     #-8, r15
366         cfi_adjust_cfa_offset(8)
369         /* Get current time.  */
370         mov     r15, r4
371         mov     #0, r5
372         mov     #__NR_gettimeofday, r3
373         trapa   #0x12
374         SYSCALL_INST_PAD
376         /* Compute relative timeout.  */
377         mov.l   @(4,r15), r0
378         mov.w   .L1k2, r1
379         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
380         mov.l   @r9, r2
381         mov.l   @(4,r9), r3
382         mov.l   @r15, r0
383         sts     macl, r1
384         sub     r0, r2
385         clrt
386         subc    r1, r3
387         bf      5f
388         mov.l   .L1g2, r1
389         add     r1, r3
390         add     #-1, r2
392         cmp/pz  r2
393         bf      6f              /* Time is already up.  */
395         mov.l   r2, @r15        /* Store relative timeout.  */
396         mov.l   r3, @(4,r15)
398         mov.l   @r8, r2
399         tst     r2, r2
400         bt      4f
402         mov     r8, r4
403         /* XXX The kernel so far uses global futex for the wakeup at
404            all times.  */
405         mov     #0, r5
406         extu.b  r5, r5
407         mov     r2, r6
408         mov     r15, r7
409         mov     #SYS_futex, r3
410         extu.b  r3, r3
411         trapa   #0x14
412         SYSCALL_INST_PAD
414         mov.l   @r8, r2
415         tst     r2, r2
416         bf      1f
418         mov     #0, r0
420         add     #8, r15
421         mov.l   @r15+, r8
422         rts
423          mov.l  @r15+, r9
425         /* Check whether the time expired.  */
426         mov     #-ETIMEDOUT, r1
427         cmp/eq  r0, r1
428         bf      2b
430         bra     3b
431          mov    #ETIMEDOUT, r0
432         cfi_endproc
434 .L1k2:
435         .word   1000
436         .align  2
437 .L1g2:
438         .long   1000000000
439         .size   __lll_timedwait_tid,.-__lll_timedwait_tid
440 #endif