]>
Commit | Line | Data |
---|---|---|
d4697bc9 | 1 | /* Copyright (C) 2002-2014 Free Software Foundation, Inc. |
654dff90 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
4 | ||
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. | |
9 | ||
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. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
654dff90 | 18 | |
63601ccd | 19 | #include <sysdep.h> |
5a8075b1 UD |
20 | #include <kernel-features.h> |
21 | #include <tcb-offsets.h> | |
e51deae7 | 22 | #include <lowlevellock.h> |
5a8075b1 | 23 | |
654dff90 UD |
24 | |
25 | .comm __fork_generation, 4, 4 | |
26 | ||
27 | .text | |
28 | ||
29 | ||
30 | .globl __pthread_once | |
31 | .type __pthread_once,@function | |
32 | .align 16 | |
33 | __pthread_once: | |
3b985826 | 34 | .LSTARTCODE: |
63601ccd UD |
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 | |
654dff90 UD |
44 | testl $2, (%rdi) |
45 | jz 1f | |
46 | xorl %eax, %eax | |
c2e5e085 | 47 | retq |
654dff90 | 48 | |
c2e5e085 UD |
49 | /* Preserve the function pointer. */ |
50 | 1: pushq %rsi | |
63601ccd | 51 | cfi_adjust_cfa_offset(8) |
c2e5e085 | 52 | xorq %r10, %r10 |
654dff90 UD |
53 | |
54 | /* Not yet initialized or initialization in progress. | |
55 | Get the fork generation counter now. */ | |
56 | 6: movl (%rdi), %eax | |
57 | ||
c2e5e085 | 58 | 5: movl %eax, %edx |
654dff90 UD |
59 | |
60 | testl $2, %eax | |
c2e5e085 | 61 | jnz 4f |
654dff90 UD |
62 | |
63 | andl $3, %edx | |
64 | orl __fork_generation(%rip), %edx | |
65 | orl $1, %edx | |
66 | ||
67 | LOCK | |
68 | cmpxchgl %edx, (%rdi) | |
69 | jnz 5b | |
70 | ||
71 | /* Check whether another thread already runs the initializer. */ | |
72 | testl $1, %eax | |
73 | jz 3f /* No -> do it. */ | |
74 | ||
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. */ | |
80 | ||
81 | /* Somebody else got here first. Wait. */ | |
5a8075b1 UD |
82 | #ifdef __ASSUME_PRIVATE_FUTEX |
83 | movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi | |
ee618985 | 84 | #else |
5a8075b1 UD |
85 | # if FUTEX_WAIT == 0 |
86 | movl %fs:PRIVATE_FUTEX, %esi | |
87 | # else | |
ee618985 | 88 | movl $FUTEX_WAIT, %esi |
5a8075b1 UD |
89 | orl %fs:PRIVATE_FUTEX, %esi |
90 | # endif | |
ee618985 UD |
91 | #endif |
92 | movl $SYS_futex, %eax | |
654dff90 UD |
93 | syscall |
94 | jmp 6b | |
95 | ||
96 | /* Preserve the pointer to the control variable. */ | |
97 | 3: pushq %rdi | |
63601ccd | 98 | cfi_adjust_cfa_offset(8) |
f9126cc2 | 99 | pushq %rdi |
63601ccd | 100 | cfi_adjust_cfa_offset(8) |
654dff90 | 101 | |
3b985826 | 102 | .LcleanupSTART: |
f9126cc2 | 103 | callq *16(%rsp) |
3b985826 | 104 | .LcleanupEND: |
654dff90 UD |
105 | |
106 | /* Get the control variable address back. */ | |
107 | popq %rdi | |
63601ccd | 108 | cfi_adjust_cfa_offset(-8) |
654dff90 UD |
109 | |
110 | /* Sucessful run of the initializer. Signal that we are done. */ | |
111 | LOCK | |
112 | incl (%rdi) | |
113 | ||
f9126cc2 | 114 | addq $8, %rsp |
63601ccd | 115 | cfi_adjust_cfa_offset(-8) |
f9126cc2 | 116 | |
654dff90 UD |
117 | /* Wake up all other threads. */ |
118 | movl $0x7fffffff, %edx | |
5a8075b1 UD |
119 | #ifdef __ASSUME_PRIVATE_FUTEX |
120 | movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi | |
121 | #else | |
654dff90 | 122 | movl $FUTEX_WAKE, %esi |
5a8075b1 UD |
123 | orl %fs:PRIVATE_FUTEX, %esi |
124 | #endif | |
ee618985 | 125 | movl $SYS_futex, %eax |
654dff90 UD |
126 | syscall |
127 | ||
8b4a0b2f | 128 | 4: addq $8, %rsp |
63601ccd | 129 | cfi_adjust_cfa_offset(-8) |
ee618985 | 130 | xorl %eax, %eax |
c2e5e085 | 131 | retq |
654dff90 UD |
132 | .size __pthread_once,.-__pthread_once |
133 | ||
7588880f | 134 | |
4d17e683 AS |
135 | hidden_def (__pthread_once) |
136 | strong_alias (__pthread_once, pthread_once) | |
654dff90 UD |
137 | |
138 | ||
139 | .type clear_once_control,@function | |
140 | .align 16 | |
141 | clear_once_control: | |
63601ccd | 142 | cfi_adjust_cfa_offset(3 * 8) |
3b985826 UD |
143 | movq (%rsp), %rdi |
144 | movq %rax, %r8 | |
654dff90 UD |
145 | movl $0, (%rdi) |
146 | ||
654dff90 | 147 | movl $0x7fffffff, %edx |
5a8075b1 UD |
148 | #ifdef __ASSUME_PRIVATE_FUTEX |
149 | movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi | |
150 | #else | |
ee618985 | 151 | movl $FUTEX_WAKE, %esi |
5a8075b1 UD |
152 | orl %fs:PRIVATE_FUTEX, %esi |
153 | #endif | |
ee618985 | 154 | movl $SYS_futex, %eax |
654dff90 UD |
155 | syscall |
156 | ||
3b985826 UD |
157 | movq %r8, %rdi |
158 | .LcallUR: | |
159 | call _Unwind_Resume@PLT | |
160 | hlt | |
161 | .LENDCODE: | |
63601ccd | 162 | cfi_endproc |
654dff90 | 163 | .size clear_once_control,.-clear_once_control |
3b985826 UD |
164 | |
165 | ||
166 | .section .gcc_except_table,"a",@progbits | |
167 | .LexceptSTART: | |
63601ccd UD |
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 | |
3b985826 UD |
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: | |
182 | ||
183 | ||
3b985826 UD |
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 | |
6cae4b26 | 188 | .align LP_SIZE |
3b985826 | 189 | .type DW.ref.__gcc_personality_v0, @object |
6cae4b26 | 190 | .size DW.ref.__gcc_personality_v0, LP_SIZE |
3b985826 | 191 | DW.ref.__gcc_personality_v0: |
6cae4b26 | 192 | ASM_ADDR __gcc_personality_v0 |
3b985826 | 193 | #endif |