Update copyright notices with scripts/update-copyrights
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_once.S
blob2cbe2fae62c07017566d5f6d2c77ad8504996b6c
1 /* Copyright (C) 2002-2014 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, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
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         cfi_startproc
36 #ifdef SHARED
37         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
38                         DW.ref.__gcc_personality_v0)
39         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
40 #else
41         cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
42         cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
43 #endif
44         testl   $2, (%rdi)
45         jz      1f
46         xorl    %eax, %eax
47         retq
49         /* Preserve the function pointer.  */
50 1:      pushq   %rsi
51         cfi_adjust_cfa_offset(8)
52         xorq    %r10, %r10
54         /* Not yet initialized or initialization in progress.
55            Get the fork generation counter now.  */
56 6:      movl    (%rdi), %eax
58 5:      movl    %eax, %edx
60         testl   $2, %eax
61         jnz     4f
63         andl    $3, %edx
64         orl     __fork_generation(%rip), %edx
65         orl     $1, %edx
67         LOCK
68         cmpxchgl %edx, (%rdi)
69         jnz     5b
71         /* Check whether another thread already runs the initializer.  */
72         testl   $1, %eax
73         jz      3f      /* No -> do it.  */
75         /* Check whether the initializer execution was interrupted
76            by a fork.  */
77         xorl    %edx, %eax
78         testl   $0xfffffffc, %eax
79         jnz     3f      /* Different for generation -> run initializer.  */
81         /* Somebody else got here first.  Wait.  */
82 #ifdef __ASSUME_PRIVATE_FUTEX
83         movl    $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi
84 #else
85 # if FUTEX_WAIT == 0
86         movl    %fs:PRIVATE_FUTEX, %esi
87 # else
88         movl    $FUTEX_WAIT, %esi
89         orl     %fs:PRIVATE_FUTEX, %esi
90 # endif
91 #endif
92         movl    $SYS_futex, %eax
93         syscall
94         jmp     6b
96         /* Preserve the pointer to the control variable.  */
97 3:      pushq   %rdi
98         cfi_adjust_cfa_offset(8)
99         pushq   %rdi
100         cfi_adjust_cfa_offset(8)
102 .LcleanupSTART:
103         callq   *16(%rsp)
104 .LcleanupEND:
106         /* Get the control variable address back.  */
107         popq    %rdi
108         cfi_adjust_cfa_offset(-8)
110         /* Sucessful run of the initializer.  Signal that we are done.  */
111         LOCK
112         incl    (%rdi)
114         addq    $8, %rsp
115         cfi_adjust_cfa_offset(-8)
117         /* Wake up all other threads.  */
118         movl    $0x7fffffff, %edx
119 #ifdef __ASSUME_PRIVATE_FUTEX
120         movl    $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi
121 #else
122         movl    $FUTEX_WAKE, %esi
123         orl     %fs:PRIVATE_FUTEX, %esi
124 #endif
125         movl    $SYS_futex, %eax
126         syscall
128 4:      addq    $8, %rsp
129         cfi_adjust_cfa_offset(-8)
130         xorl    %eax, %eax
131         retq
132         .size   __pthread_once,.-__pthread_once
135 hidden_def (__pthread_once)
136 strong_alias (__pthread_once, pthread_once)
139         .type   clear_once_control,@function
140         .align  16
141 clear_once_control:
142         cfi_adjust_cfa_offset(3 * 8)
143         movq    (%rsp), %rdi
144         movq    %rax, %r8
145         movl    $0, (%rdi)
147         movl    $0x7fffffff, %edx
148 #ifdef __ASSUME_PRIVATE_FUTEX
149         movl    $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi
150 #else
151         movl    $FUTEX_WAKE, %esi
152         orl     %fs:PRIVATE_FUTEX, %esi
153 #endif
154         movl    $SYS_futex, %eax
155         syscall
157         movq    %r8, %rdi
158 .LcallUR:
159         call    _Unwind_Resume@PLT
160         hlt
161 .LENDCODE:
162         cfi_endproc
163         .size   clear_once_control,.-clear_once_control
166         .section .gcc_except_table,"a",@progbits
167 .LexceptSTART:
168         .byte   DW_EH_PE_omit                   # @LPStart format
169         .byte   DW_EH_PE_omit                   # @TType format
170         .byte   DW_EH_PE_uleb128                # call-site format
171         .uleb128 .Lcstend-.Lcstbegin
172 .Lcstbegin:
173         .uleb128 .LcleanupSTART-.LSTARTCODE
174         .uleb128 .LcleanupEND-.LcleanupSTART
175         .uleb128 clear_once_control-.LSTARTCODE
176         .uleb128  0
177         .uleb128 .LcallUR-.LSTARTCODE
178         .uleb128 .LENDCODE-.LcallUR
179         .uleb128 0
180         .uleb128  0
181 .Lcstend:
184 #ifdef SHARED
185         .hidden DW.ref.__gcc_personality_v0
186         .weak   DW.ref.__gcc_personality_v0
187         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
188         .align  LP_SIZE
189         .type   DW.ref.__gcc_personality_v0, @object
190         .size   DW.ref.__gcc_personality_v0, LP_SIZE
191 DW.ref.__gcc_personality_v0:
192         ASM_ADDR __gcc_personality_v0
193 #endif