pthread_barrier_wait.S 4.3 KB

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