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