2.5-18.1
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_once.S
blob9db55169138cedf0907e03b8c55254c4bf55fc24
1 /* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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 #ifndef UP
21 # define LOCK lock
22 #else
23 # define LOCK
24 #endif
26 #define SYS_futex       202
27 #define FUTEX_WAKE      1
29         .comm   __fork_generation, 4, 4
31         .text
34         .globl  __pthread_once
35         .type   __pthread_once,@function
36         .align  16
37 __pthread_once:
38 .LSTARTCODE:
39         testl   $2, (%rdi)
40         jz      1f
41         xorl    %eax, %eax
42         retq
44         /* Preserve the function pointer.  */
45 1:      pushq   %rsi
46 .Lpush_rsi:
47         xorq    %r10, %r10
49         /* Not yet initialized or initialization in progress.
50            Get the fork generation counter now.  */
51 6:      movl    (%rdi), %eax
53 5:      movl    %eax, %edx
55         testl   $2, %eax
56         jnz     4f
58         andl    $3, %edx
59         orl     __fork_generation(%rip), %edx
60         orl     $1, %edx
62         LOCK
63         cmpxchgl %edx, (%rdi)
64         jnz     5b
66         /* Check whether another thread already runs the initializer.  */
67         testl   $1, %eax
68         jz      3f      /* No -> do it.  */
70         /* Check whether the initializer execution was interrupted
71            by a fork.  */
72         xorl    %edx, %eax
73         testl   $0xfffffffc, %eax
74         jnz     3f      /* Different for generation -> run initializer.  */
76         /* Somebody else got here first.  Wait.  */
77 #if FUTEX_WAIT == 0
78         xorl    %esi, %esi
79 #else
80         movl    $FUTEX_WAIT, %esi
81 #endif
82         movl    $SYS_futex, %eax
83         syscall
84         jmp     6b
86         /* Preserve the pointer to the control variable.  */
87 3:      pushq   %rdi
88 .Lpush_rdi:
89         pushq   %rdi
90 .Lpush_rdi2:
92 .LcleanupSTART:
93         callq   *16(%rsp)
94 .LcleanupEND:
96         /* Get the control variable address back.  */
97         popq    %rdi
98 .Lpop_rdi:
100         /* Sucessful run of the initializer.  Signal that we are done.  */
101         LOCK
102         incl    (%rdi)
104         addq    $8, %rsp
105 .Ladd1:
107         /* Wake up all other threads.  */
108         movl    $0x7fffffff, %edx
109         movl    $FUTEX_WAKE, %esi
110         movl    $SYS_futex, %eax
111         syscall
113 4:      addq    $8, %rsp
114 .Ladd2:
115         xorl    %eax, %eax
116         retq
118         .size   __pthread_once,.-__pthread_once
121         .globl  __pthread_once_internal
122 __pthread_once_internal = __pthread_once
124         .globl  pthread_once
125 pthread_once = __pthread_once
128         .type   clear_once_control,@function
129         .align  16
130 clear_once_control:
131         movq    (%rsp), %rdi
132         movq    %rax, %r8
133         movl    $0, (%rdi)
135         movl    $0x7fffffff, %edx
136         movl    $FUTEX_WAKE, %esi
137         movl    $SYS_futex, %eax
138         syscall
140         movq    %r8, %rdi
141 .LcallUR:
142         call    _Unwind_Resume@PLT
143         hlt
144 .LENDCODE:
145         .size   clear_once_control,.-clear_once_control
148         .section .gcc_except_table,"a",@progbits
149 .LexceptSTART:
150         .byte   0xff                            # @LPStart format (omit)
151         .byte   0xff                            # @TType format (omit)
152         .byte   0x01                            # call-site format
153                                                 # DW_EH_PE_uleb128
154         .uleb128 .Lcstend-.Lcstbegin
155 .Lcstbegin:
156         .uleb128 .LcleanupSTART-.LSTARTCODE
157         .uleb128 .LcleanupEND-.LcleanupSTART
158         .uleb128 clear_once_control-.LSTARTCODE
159         .uleb128  0
160         .uleb128 .LcallUR-.LSTARTCODE
161         .uleb128 .LENDCODE-.LcallUR
162         .uleb128 0
163         .uleb128  0
164 .Lcstend:
167         .section .eh_frame,"a",@progbits
168 .LSTARTFRAME:
169         .long   .LENDCIE-.LSTARTCIE             # Length of the CIE.
170 .LSTARTCIE:
171         .long   0                               # CIE ID.
172         .byte   1                               # Version number.
173 #ifdef SHARED
174         .string "zPLR"                          # NUL-terminated augmentation
175                                                 # string.
176 #else
177         .string "zPL"                           # NUL-terminated augmentation
178                                                 # string.
179 #endif
180         .uleb128 1                              # Code alignment factor.
181         .sleb128 -8                             # Data alignment factor.
182         .byte   16                              # Return address register
183                                                 # column.
184 #ifdef SHARED
185         .uleb128 7                              # Augmentation value length.
186         .byte   0x9b                            # Personality: DW_EH_PE_pcrel
187                                                 # + DW_EH_PE_sdata4
188                                                 # + DW_EH_PE_indirect
189         .long   DW.ref.__gcc_personality_v0-.
190         .byte   0x1b                            # LSDA Encoding: DW_EH_PE_pcrel
191                                                 # + DW_EH_PE_sdata4.
192         .byte   0x1b                            # FDE Encoding: DW_EH_PE_pcrel
193                                                 # + DW_EH_PE_sdata4.
194 #else
195         .uleb128 10                             # Augmentation value length.
196         .byte   0x0                             # Personality: absolute
197         .quad   __gcc_personality_v0
198         .byte   0x0                             # LSDA Encoding: absolute
199 #endif
200         .byte 0x0c                              # DW_CFA_def_cfa
201         .uleb128 7
202         .uleb128 8
203         .byte   0x90                            # DW_CFA_offset, column 0x10
204         .uleb128 1
205         .align 8
206 .LENDCIE:
208         .long   .LENDFDE-.LSTARTFDE             # Length of the FDE.
209 .LSTARTFDE:
210         .long   .LSTARTFDE-.LSTARTFRAME         # CIE pointer.
211 #ifdef SHARED
212         .long   .LSTARTCODE-.                   # PC-relative start address
213                                                 # of the code.
214         .long   .LENDCODE-.LSTARTCODE           # Length of the code.
215         .uleb128 4                              # Augmentation size
216         .long   .LexceptSTART-.
217 #else
218         .quad   .LSTARTCODE                     # Start address of the code.
219         .quad   .LENDCODE-.LSTARTCODE           # Length of the code.
220         .uleb128 8                              # Augmentation size
221         .quad   .LexceptSTART
222 #endif
223         .byte   4                               # DW_CFA_advance_loc4
224         .long   .Lpush_rsi-.LSTARTCODE
225         .byte   14                              # DW_CFA_def_cfa_offset
226         .uleb128 16
227         .byte   4                               # DW_CFA_advance_loc4
228         .long   .Lpush_rdi-.Lpush_rsi
229         .byte   14                              # DW_CFA_def_cfa_offset
230         .uleb128 24
231         .byte   4                               # DW_CFA_advance_loc4
232         .long   .Lpush_rdi2-.Lpush_rdi
233         .byte   14                              # DW_CFA_def_cfa_offset
234         .uleb128 32
235         .byte   4                               # DW_CFA_advance_loc4
236         .long   .Lpop_rdi-.Lpush_rdi2
237         .byte   14                              # DW_CFA_def_cfa_offset
238         .uleb128 24
239         .byte   4                               # DW_CFA_advance_loc4
240         .long   .Ladd1-.Lpop_rdi
241         .byte   14                              # DW_CFA_def_cfa_offset
242         .uleb128 16
243         .byte   4                               # DW_CFA_advance_loc4
244         .long   .Ladd2-.Ladd1
245         .byte   14                              # DW_CFA_def_cfa_offset
246         .uleb128 8
247         .byte   4                               # DW_CFA_advance_loc4
248         .long   clear_once_control-.Ladd2
249         .byte   14                              # DW_CFA_def_cfa_offset
250         .uleb128 32
251 #if 0
252         .byte   4                               # DW_CFA_advance_loc4
253         .long   .Lpop_rdi3-clear_once_control
254         .byte   14                              # DW_CFA_def_cfa_offset
255         .uleb128 16
256 #endif
257         .align  8
258 .LENDFDE:
261 #ifdef SHARED
262         .hidden DW.ref.__gcc_personality_v0
263         .weak   DW.ref.__gcc_personality_v0
264         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
265         .align  8
266         .type   DW.ref.__gcc_personality_v0, @object
267         .size   DW.ref.__gcc_personality_v0, 8
268 DW.ref.__gcc_personality_v0:
269         .quad   __gcc_personality_v0
270 #endif