pthread_barrier_wait.S 3.9 KB

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