Updated to fedora-glibc-20041102T1153
[glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_once.S
blob02af56b4c791a0ca0eaa95fa3b268cd05ebe1e10
1 /* Copyright (C) 2003, 2004 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 "lowlevel-atomic.h"
23 #define SYS_futex       240
24 #define FUTEX_WAIT      0
25 #define FUTEX_WAKE      1
27         .comm   __fork_generation, 4, 4
29         .text
30         .globl  __pthread_once
31         .type   __pthread_once,@function
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         mov     #FUTEX_WAIT, r5
99         mov     r3, r6
100         mov     #0, r7
101         mov     #SYS_futex, r3
102         extu.b  r3, r3
103         trapa   #0x14
104         SYSCALL_INST_PAD
105         bra     6b
106          nop
108         .align  2
109 .Lgot:
110         .long   _GLOBAL_OFFSET_TABLE_
111 #ifdef PIC
112 .Lfgen: 
113         .long   __fork_generation@GOTOFF
114 #else
115 .Lfgen: 
116         .long   __fork_generation
117 #endif
120         /* Call the initializer function after setting up the
121            cancellation handler.  Note that it is not possible here
122            to use the unwind-based cleanup handling.  This would require
123            that the user-provided function and all the code it calls
124            is compiled with exceptions.  Unfortunately this cannot be
125            guaranteed.  */
126         add     #-UNWINDBUFSIZE, r15
127         cfi_adjust_cfa_offset (UNWINDBUFSIZE)
129         mov.l   .Lsigsetjmp, r1
130         mov     #UWJMPBUF, r4
131         add     r15, r4
132         bsrf    r1
133          mov    #0, r5
134 .Lsigsetjmp0:
135         tst     r0, r0
136         bf      7f
138         mov.l   .Lcpush, r1
139         bsrf    r1
140          mov    r15, r4
141 .Lcpush0:
143         /* Call the user-provided initialization function.  */
144         jsr     @r8
145          nop
147         /* Pop the cleanup handler.  */
148         mov.l   .Lcpop, r1
149         bsrf    r1
150          mov    r15, r4
151 .Lcpop0:
153         add     #UNWINDBUFSIZE, r15
154         cfi_adjust_cfa_offset (-UNWINDBUFSIZE)
156         /* Sucessful run of the initializer.  Signal that we are done.  */
157         INC (@r9, r2)
158         /* Wake up all other threads.  */
159         mov     r9, r4
160         mov     #FUTEX_WAKE, r5
161         mov     #-1, r6
162         shlr    r6              /* r6 = 0x7fffffff */
163         mov     #0, r7
164         mov     #SYS_futex, r3
165         extu.b  r3, r3
166         trapa   #0x14
167         SYSCALL_INST_PAD
170         lds.l   @r15+, pr
171         cfi_adjust_cfa_offset (-4)
172         cfi_restore (pr)
173         mov.l   @r15+, r8
174         cfi_adjust_cfa_offset (-4)
175         cfi_restore (r8)
176         mov.l   @r15+, r9
177         cfi_adjust_cfa_offset (-4)
178         cfi_restore (r9)
179         mov.l   @r15+, r12
180         cfi_adjust_cfa_offset (-4)
181         cfi_restore (r12)
182         rts
183          mov    #0, r0
186         /* __sigsetjmp returned for the second time.  */
187         cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
188         cfi_offset (r12, -4)
189         cfi_offset (r9, -8)
190         cfi_offset (r8, -12)
191         cfi_offset (pr, -16)
192         mov     #0, r7
193         mov.l   r7, @r9
194         mov     r9, r4
195         mov     #FUTEX_WAKE, r5
196         mov     #-1, r6
197         shlr    r6              /* r6 = 0x7fffffff */
198         mov     #SYS_futex, r3
199         extu.b  r3, r3
200         trapa   #0x14
201         SYSCALL_INST_PAD
203         mov.l   .Lunext, r1
204         bsrf    r1
205          mov    r15, r4
206 .Lunext0:
207         /* NOTREACHED */
208         sleep
209         cfi_endproc
211         .align  2
212 .Lsigsetjmp:
213         .long   __sigsetjmp@PLT-(.Lsigsetjmp0-.)
214 .Lcpush:
215         .long   HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0
216 .Lcpop:
217         .long   HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0
218 .Lunext:
219         .long   HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0
220         .size   __pthread_once,.-__pthread_once
222         .globl  __pthread_once_internal
223 __pthread_once_internal = __pthread_once
225         .globl  pthread_once
226 pthread_once = __pthread_once
229         .type   clear_once_control,@function
230         .align  5
231 clear_once_control:
232         mov     #0, r0
233         mov.l   r0, @r4
235         mov     #FUTEX_WAKE, r5
236         mov     #-1, r6
237         shlr    r6              /* r6 = 0x7fffffff */
238         mov     #0, r7
239         mov     #SYS_futex, r3
240         extu.b  r3, r3
241         trapa   #0x14
242         SYSCALL_INST_PAD
244         rts
245          nop
246         .size   clear_once_control,.-clear_once_control