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