pthread_once.S 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <unwindbuf.h>
  15. #include <sysdep.h>
  16. #include <bits/kernel-features.h>
  17. #include <lowlevellock.h>
  18. #include <tcb-offsets.h>
  19. #include "lowlevel-atomic.h"
  20. .comm __fork_generation, 4, 4
  21. .text
  22. .globl __pthread_once
  23. .type __pthread_once,@function
  24. .protected __pthread_once
  25. .align 5
  26. cfi_startproc
  27. __pthread_once:
  28. mov.l @r4, r0
  29. tst #2, r0
  30. bt 1f
  31. rts
  32. mov #0, r0
  33. 1:
  34. mov.l r12, @-r15
  35. cfi_adjust_cfa_offset (4)
  36. cfi_rel_offset (r12, 0)
  37. mov.l r9, @-r15
  38. cfi_adjust_cfa_offset (4)
  39. cfi_rel_offset (r9, 0)
  40. mov.l r8, @-r15
  41. cfi_adjust_cfa_offset (4)
  42. cfi_rel_offset (r8, 0)
  43. sts.l pr, @-r15
  44. cfi_adjust_cfa_offset (4)
  45. cfi_rel_offset (pr, 0)
  46. mov r5, r8
  47. mov r4, r9
  48. /* Not yet initialized or initialization in progress.
  49. Get the fork generation counter now. */
  50. 6:
  51. mov.l @r4, r1
  52. mova .Lgot, r0
  53. mov.l .Lgot, r12
  54. add r0, r12
  55. 5:
  56. mov r1, r0
  57. tst #2, r0
  58. bf 4f
  59. and #3, r0
  60. mov.l .Lfgen, r2
  61. #ifdef __PIC__
  62. add r12, r2
  63. #endif
  64. mov.l @r2, r3
  65. or r3, r0
  66. or #1, r0
  67. mov r0, r3
  68. mov r1, r5
  69. CMPXCHG (r5, @r4, r3, r2)
  70. bf 5b
  71. /* Check whether another thread already runs the initializer. */
  72. mov r2, r0
  73. tst #1, r0
  74. bt 3f /* No -> do it. */
  75. /* Check whether the initializer execution was interrupted
  76. by a fork. */
  77. xor r3, r0
  78. mov #-4, r1 /* -4 = 0xfffffffc */
  79. tst r1, r0
  80. bf 3f /* Different for generation -> run initializer. */
  81. /* Somebody else got here first. Wait. */
  82. #ifdef __ASSUME_PRIVATE_FUTEX
  83. mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5
  84. extu.b r5, r5
  85. #else
  86. stc gbr, r1
  87. mov.w .Lpfoff, r2
  88. add r2, r1
  89. mov.l @r1, r5
  90. # if FUTEX_WAIT != 0
  91. mov #FUTEX_WAIT, r0
  92. or r0, r5
  93. # endif
  94. #endif
  95. mov r3, r6
  96. mov #0, r7
  97. mov #SYS_futex, r3
  98. extu.b r3, r3
  99. trapa #0x14
  100. SYSCALL_INST_PAD
  101. bra 6b
  102. nop
  103. .align 2
  104. .Lgot:
  105. .long _GLOBAL_OFFSET_TABLE_
  106. #ifdef __PIC__
  107. .Lfgen:
  108. .long __fork_generation@GOTOFF
  109. #else
  110. .Lfgen:
  111. .long __fork_generation
  112. #endif
  113. 3:
  114. /* Call the initializer function after setting up the
  115. cancellation handler. Note that it is not possible here
  116. to use the unwind-based cleanup handling. This would require
  117. that the user-provided function and all the code it calls
  118. is compiled with exceptions. Unfortunately this cannot be
  119. guaranteed. */
  120. add #-UNWINDBUFSIZE, r15
  121. cfi_adjust_cfa_offset (UNWINDBUFSIZE)
  122. mov.l .Lsigsetjmp, r1
  123. mov #UWJMPBUF, r4
  124. add r15, r4
  125. bsrf r1
  126. mov #0, r5
  127. .Lsigsetjmp0:
  128. tst r0, r0
  129. bf 7f
  130. mov.l .Lcpush, r1
  131. bsrf r1
  132. mov r15, r4
  133. .Lcpush0:
  134. /* Call the user-provided initialization function. */
  135. jsr @r8
  136. nop
  137. /* Pop the cleanup handler. */
  138. mov.l .Lcpop, r1
  139. bsrf r1
  140. mov r15, r4
  141. .Lcpop0:
  142. add #UNWINDBUFSIZE, r15
  143. cfi_adjust_cfa_offset (-UNWINDBUFSIZE)
  144. /* Sucessful run of the initializer. Signal that we are done. */
  145. INC (@r9, r2)
  146. /* Wake up all other threads. */
  147. mov r9, r4
  148. #ifdef __ASSUME_PRIVATE_FUTEX
  149. mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
  150. extu.b r5, r5
  151. #else
  152. stc gbr, r1
  153. mov.w .Lpfoff, r2
  154. add r2, r1
  155. mov.l @r1, r5
  156. mov #FUTEX_WAKE, r0
  157. or r0, r5
  158. #endif
  159. mov #-1, r6
  160. shlr r6 /* r6 = 0x7fffffff */
  161. mov #0, r7
  162. mov #SYS_futex, r3
  163. extu.b r3, r3
  164. trapa #0x14
  165. SYSCALL_INST_PAD
  166. 4:
  167. lds.l @r15+, pr
  168. cfi_adjust_cfa_offset (-4)
  169. cfi_restore (pr)
  170. mov.l @r15+, r8
  171. cfi_adjust_cfa_offset (-4)
  172. cfi_restore (r8)
  173. mov.l @r15+, r9
  174. cfi_adjust_cfa_offset (-4)
  175. cfi_restore (r9)
  176. mov.l @r15+, r12
  177. cfi_adjust_cfa_offset (-4)
  178. cfi_restore (r12)
  179. rts
  180. mov #0, r0
  181. 7:
  182. /* __sigsetjmp returned for the second time. */
  183. cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
  184. cfi_offset (r12, -4)
  185. cfi_offset (r9, -8)
  186. cfi_offset (r8, -12)
  187. cfi_offset (pr, -16)
  188. mov #0, r7
  189. mov.l r7, @r9
  190. mov r9, r4
  191. #ifdef __ASSUME_PRIVATE_FUTEX
  192. mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5
  193. #else
  194. stc gbr, r1
  195. mov.w .Lpfoff, r2
  196. add r2, r1
  197. mov.l @r1, r5
  198. mov #FUTEX_WAKE, r0
  199. or r0, r5
  200. #endif
  201. extu.b r5, r5
  202. mov #-1, r6
  203. shlr r6 /* r6 = 0x7fffffff */
  204. mov #SYS_futex, r3
  205. extu.b r3, r3
  206. trapa #0x14
  207. SYSCALL_INST_PAD
  208. mov.l .Lunext, r1
  209. bsrf r1
  210. mov r15, r4
  211. .Lunext0:
  212. /* NOTREACHED */
  213. sleep
  214. cfi_endproc
  215. #ifndef __ASSUME_PRIVATE_FUTEX
  216. .Lpfoff:
  217. .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
  218. #endif
  219. .align 2
  220. .Lsigsetjmp:
  221. .long __sigsetjmp@PLT-(.Lsigsetjmp0-.)
  222. .Lcpush:
  223. .long HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0
  224. .Lcpop:
  225. .long HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0
  226. .Lunext:
  227. .long HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0
  228. .size __pthread_once,.-__pthread_once
  229. .globl __pthread_once_internal
  230. __pthread_once_internal = __pthread_once
  231. .globl pthread_once
  232. pthread_once = __pthread_once