pthread_once.S 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA. */
  16. #include <sysdep.h>
  17. #ifndef UP
  18. # define LOCK lock
  19. #else
  20. # define LOCK
  21. #endif
  22. #define FUTEX_WAIT 0
  23. #define FUTEX_WAKE 1
  24. .comm __fork_generation, 4, 4
  25. .text
  26. .globl __pthread_once
  27. .type __pthread_once,@function
  28. .align 16
  29. __pthread_once:
  30. .LSTARTCODE:
  31. testl $2, (%rdi)
  32. jz 1f
  33. xorl %eax, %eax
  34. retq
  35. /* Preserve the function pointer. */
  36. 1: pushq %rsi
  37. .Lpush_rsi:
  38. xorq %r10, %r10
  39. /* Not yet initialized or initialization in progress.
  40. Get the fork generation counter now. */
  41. 6: movl (%rdi), %eax
  42. 5: movl %eax, %edx
  43. testl $2, %eax
  44. jnz 4f
  45. andl $3, %edx
  46. orl __fork_generation(%rip), %edx
  47. orl $1, %edx
  48. LOCK
  49. cmpxchgl %edx, (%rdi)
  50. jnz 5b
  51. /* Check whether another thread already runs the initializer. */
  52. testl $1, %eax
  53. jz 3f /* No -> do it. */
  54. /* Check whether the initializer execution was interrupted
  55. by a fork. */
  56. xorl %edx, %eax
  57. testl $0xfffffffc, %eax
  58. jnz 3f /* Different for generation -> run initializer. */
  59. /* Somebody else got here first. Wait. */
  60. #if FUTEX_WAIT == 0
  61. xorl %esi, %esi
  62. #else
  63. movl $FUTEX_WAIT, %esi
  64. #endif
  65. movl $SYS_futex, %eax
  66. syscall
  67. jmp 6b
  68. /* Preserve the pointer to the control variable. */
  69. 3: pushq %rdi
  70. .Lpush_rdi:
  71. .LcleanupSTART:
  72. callq *8(%rsp)
  73. .LcleanupEND:
  74. /* Get the control variable address back. */
  75. popq %rdi
  76. .Lpop_rdi:
  77. /* Sucessful run of the initializer. Signal that we are done. */
  78. LOCK
  79. incl (%rdi)
  80. /* Wake up all other threads. */
  81. movl $0x7fffffff, %edx
  82. movl $FUTEX_WAKE, %esi
  83. movl $SYS_futex, %eax
  84. syscall
  85. 4: addq $8, %rsp
  86. .Ladd:
  87. xorl %eax, %eax
  88. retq
  89. .size __pthread_once,.-__pthread_once
  90. .globl __pthread_once_internal
  91. __pthread_once_internal = __pthread_once
  92. .globl pthread_once
  93. pthread_once = __pthread_once
  94. .type clear_once_control,@function
  95. .align 16
  96. clear_once_control:
  97. movq (%rsp), %rdi
  98. movq %rax, %r8
  99. movl $0, (%rdi)
  100. movl $0x7fffffff, %edx
  101. movl $FUTEX_WAKE, %esi
  102. movl $SYS_futex, %eax
  103. syscall
  104. movq %r8, %rdi
  105. .LcallUR:
  106. call _Unwind_Resume@PLT
  107. hlt
  108. .LENDCODE:
  109. .size clear_once_control,.-clear_once_control
  110. .section .gcc_except_table,"a",@progbits
  111. .LexceptSTART:
  112. .byte 0xff # @LPStart format (omit)
  113. .byte 0xff # @TType format (omit)
  114. .byte 0x01 # call-site format
  115. # DW_EH_PE_uleb128
  116. .uleb128 .Lcstend-.Lcstbegin
  117. .Lcstbegin:
  118. .uleb128 .LcleanupSTART-.LSTARTCODE
  119. .uleb128 .LcleanupEND-.LcleanupSTART
  120. .uleb128 clear_once_control-.LSTARTCODE
  121. .uleb128 0
  122. .uleb128 .LcallUR-.LSTARTCODE
  123. .uleb128 .LENDCODE-.LcallUR
  124. .uleb128 0
  125. .uleb128 0
  126. .Lcstend:
  127. .section .eh_frame,"a",@progbits
  128. .LSTARTFRAME:
  129. .long .LENDCIE-.LSTARTCIE # Length of the CIE.
  130. .LSTARTCIE:
  131. .long 0 # CIE ID.
  132. .byte 1 # Version number.
  133. #ifdef SHARED
  134. .string "zPLR" # NUL-terminated augmentation
  135. # string.
  136. #else
  137. .string "zPL" # NUL-terminated augmentation
  138. # string.
  139. #endif
  140. .uleb128 1 # Code alignment factor.
  141. .sleb128 -8 # Data alignment factor.
  142. .byte 16 # Return address register
  143. # column.
  144. #ifdef SHARED
  145. .uleb128 7 # Augmentation value length.
  146. .byte 0x9b # Personality: DW_EH_PE_pcrel
  147. # + DW_EH_PE_sdata4
  148. # + DW_EH_PE_indirect
  149. .long DW.ref.__gcc_personality_v0-.
  150. .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
  151. # + DW_EH_PE_sdata4.
  152. .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
  153. # + DW_EH_PE_sdata4.
  154. #else
  155. .uleb128 10 # Augmentation value length.
  156. .byte 0x0 # Personality: absolute
  157. .quad __gcc_personality_v0
  158. .byte 0x0 # LSDA Encoding: absolute
  159. #endif
  160. .byte 0x0c # DW_CFA_def_cfa
  161. .uleb128 7
  162. .uleb128 8
  163. .byte 0x90 # DW_CFA_offset, column 0x10
  164. .uleb128 1
  165. .align 8
  166. .LENDCIE:
  167. .long .LENDFDE-.LSTARTFDE # Length of the FDE.
  168. .LSTARTFDE:
  169. .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
  170. #ifdef SHARED
  171. .long .LSTARTCODE-. # PC-relative start address
  172. # of the code.
  173. .long .LENDCODE-.LSTARTCODE # Length of the code.
  174. .uleb128 4 # Augmentation size
  175. .long .LexceptSTART-.
  176. #else
  177. .quad .LSTARTCODE # Start address of the code.
  178. .quad .LENDCODE-.LSTARTCODE # Length of the code.
  179. .uleb128 8 # Augmentation size
  180. .quad .LexceptSTART
  181. #endif
  182. .byte 4 # DW_CFA_advance_loc4
  183. .long .Lpush_rsi-.LSTARTCODE
  184. .byte 14 # DW_CFA_def_cfa_offset
  185. .uleb128 16
  186. .byte 4 # DW_CFA_advance_loc4
  187. .long .Lpush_rdi-.Lpush_rsi
  188. .byte 14 # DW_CFA_def_cfa_offset
  189. .uleb128 24
  190. .byte 4 # DW_CFA_advance_loc4
  191. .long .Lpop_rdi-.Lpush_rdi
  192. .byte 14 # DW_CFA_def_cfa_offset
  193. .uleb128 16
  194. .byte 4 # DW_CFA_advance_loc4
  195. .long .Ladd-.Lpop_rdi
  196. .byte 14 # DW_CFA_def_cfa_offset
  197. .uleb128 8
  198. .byte 4 # DW_CFA_advance_loc4
  199. .long clear_once_control-.Ladd
  200. .byte 14 # DW_CFA_def_cfa_offset
  201. .uleb128 24
  202. #if 0
  203. .byte 4 # DW_CFA_advance_loc4
  204. .long .Lpop_rdi2-clear_once_control
  205. .byte 14 # DW_CFA_def_cfa_offset
  206. .uleb128 16
  207. #endif
  208. .align 8
  209. .LENDFDE:
  210. #ifdef SHARED
  211. .hidden DW.ref.__gcc_personality_v0
  212. .weak DW.ref.__gcc_personality_v0
  213. .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
  214. .align 8
  215. .type DW.ref.__gcc_personality_v0, @object
  216. .size DW.ref.__gcc_personality_v0, 8
  217. DW.ref.__gcc_personality_v0:
  218. .quad __gcc_personality_v0
  219. #endif