or1k: syscall: Pass arguments on the stack
[uclibc-ng.git] / libpthread / nptl / sysdeps / unix / sysv / linux / sh / pthread_once.S
blobb03173d82901e8ae1169b457425ffe992ad81c7e
1 /* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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.
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.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
18 #include <unwindbuf.h>
19 #include <sysdep.h>
20 #include <bits/kernel-features.h>
21 #include <lowlevellock.h>
22 #include <tcb-offsets.h>
23 #include "lowlevel-atomic.h"
26         .comm   __fork_generation, 4, 4
28         .text
29         .globl  __pthread_once
30         .type   __pthread_once,@function
31         .protected      __pthread_once
32         .align  5
33         cfi_startproc
34 __pthread_once:
35         mov.l   @r4, r0
36         tst     #2, r0
37         bt      1f
38         rts
39          mov    #0, r0
42         mov.l   r12, @-r15
43         cfi_adjust_cfa_offset (4)
44         cfi_rel_offset (r12, 0)
45         mov.l   r9, @-r15
46         cfi_adjust_cfa_offset (4)
47         cfi_rel_offset (r9, 0)
48         mov.l   r8, @-r15
49         cfi_adjust_cfa_offset (4)
50         cfi_rel_offset (r8, 0)
51         sts.l   pr, @-r15
52         cfi_adjust_cfa_offset (4)
53         cfi_rel_offset (pr, 0)
54         mov     r5, r8
55         mov     r4, r9
57         /* Not yet initialized or initialization in progress.
58            Get the fork generation counter now.  */
60         mov.l   @r4, r1
61         mova    .Lgot, r0
62         mov.l   .Lgot, r12
63         add     r0, r12
66         mov     r1, r0
68         tst     #2, r0
69         bf      4f
71         and     #3, r0
72         mov.l   .Lfgen, r2
73 #ifdef __PIC__
74         add     r12, r2
75 #endif
76         mov.l   @r2, r3
77         or      r3, r0
78         or      #1, r0
79         mov     r0, r3
80         mov     r1, r5
82         CMPXCHG (r5, @r4, r3, r2)
83         bf      5b
85         /* Check whether another thread already runs the initializer.  */
86         mov     r2, r0
87         tst     #1, r0
88         bt      3f      /* No -> do it.  */
90         /* Check whether the initializer execution was interrupted
91            by a fork.  */
92         xor     r3, r0
93         mov     #-4, r1 /* -4 = 0xfffffffc */
94         tst     r1, r0
95         bf      3f      /* Different for generation -> run initializer.  */
97         /* Somebody else got here first.  Wait.  */
98 #ifdef __ASSUME_PRIVATE_FUTEX
99         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5
100         extu.b  r5, r5
101 #else
102         stc     gbr, r1
103         mov.w   .Lpfoff, r2
104         add     r2, r1
105         mov.l   @r1, r5
106 # if FUTEX_WAIT != 0
107         mov     #FUTEX_WAIT, r0
108         or      r0, r5
109 # endif
110 #endif
111         mov     r3, r6
112         mov     #0, r7
113         mov     #SYS_futex, r3
114         extu.b  r3, r3
115         trapa   #0x14
116         SYSCALL_INST_PAD
117         bra     6b
118          nop
120         .align  2
121 .Lgot:
122         .long   _GLOBAL_OFFSET_TABLE_
123 #ifdef __PIC__
124 .Lfgen:
125         .long   __fork_generation@GOTOFF
126 #else
127 .Lfgen:
128         .long   __fork_generation
129 #endif
132         /* Call the initializer function after setting up the
133            cancellation handler.  Note that it is not possible here
134            to use the unwind-based cleanup handling.  This would require
135            that the user-provided function and all the code it calls
136            is compiled with exceptions.  Unfortunately this cannot be
137            guaranteed.  */
138         add     #-UNWINDBUFSIZE, r15
139         cfi_adjust_cfa_offset (UNWINDBUFSIZE)
141         mov.l   .Lsigsetjmp, r1
142         mov     #UWJMPBUF, r4
143         add     r15, r4
144         bsrf    r1
145          mov    #0, r5
146 .Lsigsetjmp0:
147         tst     r0, r0
148         bf      7f
150         mov.l   .Lcpush, r1
151         bsrf    r1
152          mov    r15, r4
153 .Lcpush0:
155         /* Call the user-provided initialization function.  */
156         jsr     @r8
157          nop
159         /* Pop the cleanup handler.  */
160         mov.l   .Lcpop, r1
161         bsrf    r1
162          mov    r15, r4
163 .Lcpop0:
165         add     #UNWINDBUFSIZE, r15
166         cfi_adjust_cfa_offset (-UNWINDBUFSIZE)
168         /* Sucessful run of the initializer.  Signal that we are done.  */
169         INC (@r9, r2)
170         /* Wake up all other threads.  */
171         mov     r9, r4
172 #ifdef __ASSUME_PRIVATE_FUTEX
173         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
174         extu.b  r5, r5
175 #else
176         stc     gbr, r1
177         mov.w   .Lpfoff, r2
178         add     r2, r1
179         mov.l   @r1, r5
180         mov     #FUTEX_WAKE, r0
181         or      r0, r5
182 #endif
183         mov     #-1, r6
184         shlr    r6              /* r6 = 0x7fffffff */
185         mov     #0, r7
186         mov     #SYS_futex, r3
187         extu.b  r3, r3
188         trapa   #0x14
189         SYSCALL_INST_PAD
192         lds.l   @r15+, pr
193         cfi_adjust_cfa_offset (-4)
194         cfi_restore (pr)
195         mov.l   @r15+, r8
196         cfi_adjust_cfa_offset (-4)
197         cfi_restore (r8)
198         mov.l   @r15+, r9
199         cfi_adjust_cfa_offset (-4)
200         cfi_restore (r9)
201         mov.l   @r15+, r12
202         cfi_adjust_cfa_offset (-4)
203         cfi_restore (r12)
204         rts
205          mov    #0, r0
208         /* __sigsetjmp returned for the second time.  */
209         cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
210         cfi_offset (r12, -4)
211         cfi_offset (r9, -8)
212         cfi_offset (r8, -12)
213         cfi_offset (pr, -16)
214         mov     #0, r7
215         mov.l   r7, @r9
216         mov     r9, r4
217 #ifdef __ASSUME_PRIVATE_FUTEX
218         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
219 #else
220         stc     gbr, r1
221         mov.w   .Lpfoff, r2
222         add     r2, r1
223         mov.l   @r1, r5
224         mov     #FUTEX_WAKE, r0
225         or      r0, r5
226 #endif
227         extu.b  r5, r5
228         mov     #-1, r6
229         shlr    r6              /* r6 = 0x7fffffff */
230         mov     #SYS_futex, r3
231         extu.b  r3, r3
232         trapa   #0x14
233         SYSCALL_INST_PAD
235         mov.l   .Lunext, r1
236         bsrf    r1
237          mov    r15, r4
238 .Lunext0:
239         /* NOTREACHED */
240         sleep
241         cfi_endproc
243 #ifndef __ASSUME_PRIVATE_FUTEX
244 .Lpfoff:
245         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
246 #endif
247         .align  2
248 .Lsigsetjmp:
249         .long   __sigsetjmp@PLT-(.Lsigsetjmp0-.)
250 .Lcpush:
251         .long   HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0
252 .Lcpop:
253         .long   HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0
254 .Lunext:
255         .long   HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0
256         .size   __pthread_once,.-__pthread_once
258         .globl  __pthread_once_internal
259 __pthread_once_internal = __pthread_once
261         .globl  pthread_once
262 pthread_once = __pthread_once