pthread_barrier_wait.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* Copyright (C) 2003, 2004, 2007, 2008 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 <sysdep.h>
  15. #include <lowlevellock.h>
  16. #include <lowlevelbarrier.h>
  17. #include "lowlevel-atomic.h"
  18. .text
  19. .globl pthread_barrier_wait
  20. .type pthread_barrier_wait,@function
  21. .align 5
  22. pthread_barrier_wait:
  23. mov.l r9, @-r15
  24. mov.l r8, @-r15
  25. sts.l pr, @-r15
  26. mov r4, r8
  27. /* Get the mutex. */
  28. mov #0, r3
  29. mov #1, r4
  30. CMPXCHG (r3, @(MUTEX,r8), r4, r2)
  31. bf 1f
  32. /* One less waiter. If this was the last one needed wake
  33. everybody. */
  34. 2:
  35. mov.l @(LEFT,r8), r0
  36. add #-1, r0
  37. mov.l r0, @(LEFT,r8)
  38. tst r0, r0
  39. bt 3f
  40. /* There are more threads to come. */
  41. mov.l @(CURR_EVENT,r8), r6
  42. /* Release the mutex. */
  43. DEC (@(MUTEX,r8), r2)
  44. tst r2, r2
  45. bf 6f
  46. 7:
  47. /* Wait for the remaining threads. The call will return immediately
  48. if the CURR_EVENT memory has meanwhile been changed. */
  49. mov r8, r4
  50. #if CURR_EVENT != 0
  51. add #CURR_EVENT, r4
  52. #endif
  53. #if FUTEX_WAIT == 0
  54. mov.l @(PRIVATE,r8), r5
  55. #else
  56. mov #FUTEX_WAIT, r5
  57. mov.l @(PRIVATE,r8), r0
  58. or r0, r5
  59. #endif
  60. mov #0, r7
  61. 8:
  62. mov #SYS_futex, r3
  63. extu.b r3, r3
  64. trapa #0x14
  65. SYSCALL_INST_PAD
  66. /* Don't return on spurious wakeups. The syscall does not change
  67. any register except r0 so there is no need to reload any of
  68. them. */
  69. mov.l @(CURR_EVENT,r8), r0
  70. cmp/eq r0, r6
  71. bt 8b
  72. /* Increment LEFT. If this brings the count back to the
  73. initial count unlock the object. */
  74. mov #1, r3
  75. mov.l @(INIT_COUNT,r8), r4
  76. XADD (r3, @(LEFT,r8), r2, r5)
  77. add #-1, r4
  78. cmp/eq r2, r4
  79. bf 10f
  80. /* Release the mutex. We cannot release the lock before
  81. waking the waiting threads since otherwise a new thread might
  82. arrive and gets waken up, too. */
  83. DEC (@(MUTEX,r8), r2)
  84. tst r2, r2
  85. bf 9f
  86. 10:
  87. mov #0, r0 /* != PTHREAD_BARRIER_SERIAL_THREAD */
  88. lds.l @r15+, pr
  89. mov.l @r15+, r8
  90. rts
  91. mov.l @r15+, r9
  92. 3:
  93. /* The necessary number of threads arrived. */
  94. mov.l @(CURR_EVENT,r8), r1
  95. add #1, r1
  96. mov.l r1, @(CURR_EVENT,r8)
  97. /* Wake up all waiters. The count is a signed number in the kernel
  98. so 0x7fffffff is the highest value. */
  99. mov.l .Lall, r6
  100. mov r8, r4
  101. #if CURR_EVENT != 0
  102. add #CURR_EVENT, r4
  103. #endif
  104. mov #0, r7
  105. mov #FUTEX_WAKE, r5
  106. mov.l @(PRIVATE,r8), r0
  107. or r0, r5
  108. mov #SYS_futex, r3
  109. extu.b r3, r3
  110. trapa #0x14
  111. SYSCALL_INST_PAD
  112. /* Increment LEFT. If this brings the count back to the
  113. initial count unlock the object. */
  114. mov #1, r3
  115. mov.l @(INIT_COUNT,r8), r4
  116. XADD (r3, @(LEFT,r8), r2, r5)
  117. add #-1, r4
  118. cmp/eq r2, r4
  119. bf 5f
  120. /* Release the mutex. */
  121. DEC (@(MUTEX,r8), r2)
  122. tst r2, r2
  123. bf 4f
  124. 5:
  125. mov #-1, r0 /* == PTHREAD_BARRIER_SERIAL_THREAD */
  126. lds.l @r15+, pr
  127. mov.l @r15+, r8
  128. rts
  129. mov.l @r15+, r9
  130. 1:
  131. mov.l @(PRIVATE,r8), r6
  132. mov #LLL_SHARED, r0
  133. extu.b r0, r0
  134. xor r0, r6
  135. mov r2, r4
  136. mov r8, r5
  137. mov.l .Lwait0, r1
  138. bsrf r1
  139. add #MUTEX, r5
  140. .Lwait0b:
  141. bra 2b
  142. nop
  143. 4:
  144. mov.l @(PRIVATE,r8), r5
  145. mov #LLL_SHARED, r0
  146. extu.b r0, r0
  147. xor r0, r5
  148. mov r8, r4
  149. mov.l .Lwake0, r1
  150. bsrf r1
  151. add #MUTEX, r4
  152. .Lwake0b:
  153. bra 5b
  154. nop
  155. 6:
  156. mov r6, r9
  157. mov.l @(PRIVATE,r8), r5
  158. mov #LLL_SHARED, r0
  159. extu.b r0, r0
  160. xor r0, r5
  161. mov r8, r4
  162. mov.l .Lwake1, r1
  163. bsrf r1
  164. add #MUTEX, r4
  165. .Lwake1b:
  166. bra 7b
  167. mov r9, r6
  168. 9:
  169. mov r6, r9
  170. mov.l @(PRIVATE,r8), r5
  171. mov #LLL_SHARED, r0
  172. extu.b r0, r0
  173. xor r0, r5
  174. mov r8, r4
  175. mov.l .Lwake2, r1
  176. bsrf r1
  177. add #MUTEX, r4
  178. .Lwake2b:
  179. bra 10b
  180. mov r9, r6
  181. .align 2
  182. .Lall:
  183. .long 0x7fffffff
  184. .Lwait0:
  185. .long __lll_lock_wait-.Lwait0b
  186. .Lwake0:
  187. .long __lll_unlock_wake-.Lwake0b
  188. .Lwake1:
  189. .long __lll_unlock_wake-.Lwake1b
  190. .Lwake2:
  191. .long __lll_unlock_wake-.Lwake2b
  192. .size pthread_barrier_wait,.-pthread_barrier_wait