1/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. 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 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20#include <bits/kernel-features.h> 21#include <tcb-offsets.h> 22#include <lowlevellock.h> 23 24 25 .comm __fork_generation, 4, 4 26 27 .text 28 29 30 .globl __pthread_once 31 .type __pthread_once,@function 32 .protected __pthread_once 33 .align 16 34__pthread_once: 35.LSTARTCODE: 36 cfi_startproc 37 testl $2, (%rdi) 38 jz 1f 39 xorl %eax, %eax 40 retq 41 42 /* Preserve the function pointer. */ 431: pushq %rsi 44 cfi_adjust_cfa_offset(8) 45 xorq %r10, %r10 46 47 /* Not yet initialized or initialization in progress. 48 Get the fork generation counter now. */ 496: movl (%rdi), %eax 50 515: movl %eax, %edx 52 53 testl $2, %eax 54 jnz 4f 55 56 andl $3, %edx 57 orl __fork_generation(%rip), %edx 58 orl $1, %edx 59 60 LOCK 61 cmpxchgl %edx, (%rdi) 62 jnz 5b 63 64 /* Check whether another thread already runs the initializer. */ 65 testl $1, %eax 66 jz 3f /* No -> do it. */ 67 68 /* Check whether the initializer execution was interrupted 69 by a fork. */ 70 xorl %edx, %eax 71 testl $0xfffffffc, %eax 72 jnz 3f /* Different for generation -> run initializer. */ 73 74 /* Somebody else got here first. Wait. */ 75#ifdef __ASSUME_PRIVATE_FUTEX 76 movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi 77#else 78# if FUTEX_WAIT == 0 79 movl %fs:PRIVATE_FUTEX, %esi 80# else 81 movl $FUTEX_WAIT, %esi 82 orl %fs:PRIVATE_FUTEX, %esi 83# endif 84#endif 85 movl $SYS_futex, %eax 86 syscall 87 jmp 6b 88 89 /* Preserve the pointer to the control variable. */ 903: pushq %rdi 91 cfi_adjust_cfa_offset(8) 92 pushq %rdi 93 cfi_adjust_cfa_offset(8) 94 95.LcleanupSTART: 96 callq *16(%rsp) 97.LcleanupEND: 98 99 /* Get the control variable address back. */ 100 popq %rdi 101 cfi_adjust_cfa_offset(-8) 102 103 /* Sucessful run of the initializer. Signal that we are done. */ 104 LOCK 105 incl (%rdi) 106 107 addq $8, %rsp 108 cfi_adjust_cfa_offset(-8) 109 110 /* Wake up all other threads. */ 111 movl $0x7fffffff, %edx 112#ifdef __ASSUME_PRIVATE_FUTEX 113 movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi 114#else 115 movl $FUTEX_WAKE, %esi 116 orl %fs:PRIVATE_FUTEX, %esi 117#endif 118 movl $SYS_futex, %eax 119 syscall 120 1214: addq $8, %rsp 122 cfi_adjust_cfa_offset(-8) 123 xorl %eax, %eax 124 retq 125 .size __pthread_once,.-__pthread_once 126 127 128 .globl __pthread_once_internal 129__pthread_once_internal = __pthread_once 130 131 .globl pthread_once 132pthread_once = __pthread_once 133 134 135 .type clear_once_control,@function 136 .align 16 137clear_once_control: 138 cfi_adjust_cfa_offset(3 * 8) 139 movq (%rsp), %rdi 140 movq %rax, %r8 141 movl $0, (%rdi) 142 143 movl $0x7fffffff, %edx 144#ifdef __ASSUME_PRIVATE_FUTEX 145 movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi 146#else 147 movl $FUTEX_WAKE, %esi 148 orl %fs:PRIVATE_FUTEX, %esi 149#endif 150 movl $SYS_futex, %eax 151 syscall 152 153 movq %r8, %rdi 154.LcallUR: 155 call _Unwind_Resume@PLT 156 hlt 157.LENDCODE: 158 cfi_endproc 159 .size clear_once_control,.-clear_once_control 160 161 162 .section .gcc_except_table,"a",@progbits 163.LexceptSTART: 164 .byte DW_EH_PE_omit # @LPStart format 165 .byte DW_EH_PE_omit # @TType format 166 .byte DW_EH_PE_uleb128 # call-site format 167 .uleb128 .Lcstend-.Lcstbegin 168.Lcstbegin: 169 .uleb128 .LcleanupSTART-.LSTARTCODE 170 .uleb128 .LcleanupEND-.LcleanupSTART 171 .uleb128 clear_once_control-.LSTARTCODE 172 .uleb128 0 173 .uleb128 .LcallUR-.LSTARTCODE 174 .uleb128 .LENDCODE-.LcallUR 175 .uleb128 0 176 .uleb128 0 177.Lcstend: 178 179 180#ifdef SHARED 181 .hidden DW.ref.__gcc_personality_v0 182 .weak DW.ref.__gcc_personality_v0 183 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits 184 .align 8 185 .type DW.ref.__gcc_personality_v0, @object 186 .size DW.ref.__gcc_personality_v0, 8 187DW.ref.__gcc_personality_v0: 188 .quad __gcc_personality_v0 189#endif 190