2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_once.S
blob0830cab2466623231f11d9686c793151670c70e7
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, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
19 #include <unwindbuf.h>
20 #include <sysdep.h>
21 #include <kernel-features.h>
22 #include <lowlevellock.h>
23 #include "lowlevel-atomic.h"
26         .comm   __fork_generation, 4, 4
28         .text
29         .globl  __pthread_once
30         .type   __pthread_once,@function
31         .align  5
32         cfi_startproc
33 __pthread_once:
34         mov.l   @r4, r0
35         tst     #2, r0
36         bt      1f
37         rts
38          mov    #0, r0
41         mov.l   r12, @-r15
42         cfi_adjust_cfa_offset (4)
43         cfi_rel_offset (r12, 0)
44         mov.l   r9, @-r15
45         cfi_adjust_cfa_offset (4)
46         cfi_rel_offset (r9, 0)
47         mov.l   r8, @-r15
48         cfi_adjust_cfa_offset (4)
49         cfi_rel_offset (r8, 0)
50         sts.l   pr, @-r15
51         cfi_adjust_cfa_offset (4)
52         cfi_rel_offset (pr, 0)
53         mov     r5, r8
54         mov     r4, r9
56         /* Not yet initialized or initialization in progress.
57            Get the fork generation counter now.  */
59         mov.l   @r4, r1
60         mova    .Lgot, r0
61         mov.l   .Lgot, r12
62         add     r0, r12
65         mov     r1, r0
67         tst     #2, r0
68         bf      4f
70         and     #3, r0
71         mov.l   .Lfgen, r2
72 #ifdef PIC
73         add     r12, r2
74 #endif
75         mov.l   @r2, r3
76         or      r3, r0  
77         or      #1, r0
78         mov     r0, r3
79         mov     r1, r5
81         CMPXCHG (r5, @r4, r3, r2)
82         bf      5b
84         /* Check whether another thread already runs the initializer.  */
85         mov     r2, r0
86         tst     #1, r0
87         bt      3f      /* No -> do it.  */
89         /* Check whether the initializer execution was interrupted
90            by a fork.  */
91         xor     r3, r0
92         mov     #-4, r1 /* -4 = 0xfffffffc */
93         tst     r1, r0
94         bf      3f      /* Different for generation -> run initializer.  */
96         /* Somebody else got here first.  Wait.  */
97 #ifdef __ASSUME_PRIVATE_FUTEX
98         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5
99         extu.b  r5, r5
100 #else
101         stc     gbr, r1
102         mov.w   .Lpfoff, r2
103         add     r2, r1
104         mov.l   @r1, r5
105 # if FUTEX_WAIT != 0
106         mov     #FUTEX_WAIT, r0
107         or      r0, r5
108 # endif
109 #endif
110         mov     r3, r6
111         mov     #0, r7
112         mov     #SYS_futex, r3
113         extu.b  r3, r3
114         trapa   #0x14
115         SYSCALL_INST_PAD
116         bra     6b
117          nop
119         .align  2
120 .Lgot:
121         .long   _GLOBAL_OFFSET_TABLE_
122 #ifdef PIC
123 .Lfgen: 
124         .long   __fork_generation@GOTOFF
125 #else
126 .Lfgen: 
127         .long   __fork_generation
128 #endif
131         /* Call the initializer function after setting up the
132            cancellation handler.  Note that it is not possible here
133            to use the unwind-based cleanup handling.  This would require
134            that the user-provided function and all the code it calls
135            is compiled with exceptions.  Unfortunately this cannot be
136            guaranteed.  */
137         add     #-UNWINDBUFSIZE, r15
138         cfi_adjust_cfa_offset (UNWINDBUFSIZE)
140         mov.l   .Lsigsetjmp, r1
141         mov     #UWJMPBUF, r4
142         add     r15, r4
143         bsrf    r1
144          mov    #0, r5
145 .Lsigsetjmp0:
146         tst     r0, r0
147         bf      7f
149         mov.l   .Lcpush, r1
150         bsrf    r1
151          mov    r15, r4
152 .Lcpush0:
154         /* Call the user-provided initialization function.  */
155         jsr     @r8
156          nop
158         /* Pop the cleanup handler.  */
159         mov.l   .Lcpop, r1
160         bsrf    r1
161          mov    r15, r4
162 .Lcpop0:
164         add     #UNWINDBUFSIZE, r15
165         cfi_adjust_cfa_offset (-UNWINDBUFSIZE)
167         /* Sucessful run of the initializer.  Signal that we are done.  */
168         INC (@r9, r2)
169         /* Wake up all other threads.  */
170         mov     r9, r4
171 #ifdef __ASSUME_PRIVATE_FUTEX
172         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
173         extu.b  r5, r5
174 #else
175         stc     gbr, r1
176         mov.w   .Lpfoff, r2
177         add     r2, r1
178         mov.l   @r1, r5
179         mov     #FUTEX_WAKE, r0
180         or      r0, r5
181 #endif
182         mov     #-1, r6
183         shlr    r6              /* r6 = 0x7fffffff */
184         mov     #0, r7
185         mov     #SYS_futex, r3
186         extu.b  r3, r3
187         trapa   #0x14
188         SYSCALL_INST_PAD
191         lds.l   @r15+, pr
192         cfi_adjust_cfa_offset (-4)
193         cfi_restore (pr)
194         mov.l   @r15+, r8
195         cfi_adjust_cfa_offset (-4)
196         cfi_restore (r8)
197         mov.l   @r15+, r9
198         cfi_adjust_cfa_offset (-4)
199         cfi_restore (r9)
200         mov.l   @r15+, r12
201         cfi_adjust_cfa_offset (-4)
202         cfi_restore (r12)
203         rts
204          mov    #0, r0
207         /* __sigsetjmp returned for the second time.  */
208         cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
209         cfi_offset (r12, -4)
210         cfi_offset (r9, -8)
211         cfi_offset (r8, -12)
212         cfi_offset (pr, -16)
213         mov     #0, r7
214         mov.l   r7, @r9
215         mov     r9, r4
216 #ifdef __ASSUME_PRIVATE_FUTEX
217         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
218 #else
219         stc     gbr, r1
220         mov.w   .Lpfoff, r2
221         add     r2, r1
222         mov.l   @r1, r5
223         mov     #FUTEX_WAKE, r0
224         or      r0, r5
225 #endif
226         extu.b  r5, r5
227         mov     #-1, r6
228         shlr    r6              /* r6 = 0x7fffffff */
229         mov     #SYS_futex, r3
230         extu.b  r3, r3
231         trapa   #0x14
232         SYSCALL_INST_PAD
234         mov.l   .Lunext, r1
235         bsrf    r1
236          mov    r15, r4
237 .Lunext0:
238         /* NOTREACHED */
239         sleep
240         cfi_endproc
242 #ifndef __ASSUME_PRIVATE_FUTEX
243 .Lpfoff:
244         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
245 #endif
246         .align  2
247 .Lsigsetjmp:
248         .long   __sigsetjmp@PLT-(.Lsigsetjmp0-.)
249 .Lcpush:
250         .long   HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0
251 .Lcpop:
252         .long   HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0
253 .Lunext:
254         .long   HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0
255         .size   __pthread_once,.-__pthread_once
257         .globl  __pthread_once_internal
258 __pthread_once_internal = __pthread_once
260         .globl  pthread_once
261 pthread_once = __pthread_once