pthread_once.S 5.9 KB

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