pthread_cond_signal.S 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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 <sysdep.h>
  15. #include <lowlevellock.h>
  16. #include <lowlevelcond.h>
  17. #include <bits/kernel-features.h>
  18. #include <pthread-errnos.h>
  19. #include <tcb-offsets.h>
  20. #include "lowlevel-atomic.h"
  21. .text
  22. /* int pthread_cond_signal (pthread_cond_t *cond) */
  23. .globl __pthread_cond_signal
  24. .type __pthread_cond_signal, @function
  25. .protected __pthread_cond_signal
  26. .align 5
  27. __pthread_cond_signal:
  28. mov.l r8, @-r15
  29. sts.l pr, @-r15
  30. mov r4, r8
  31. /* Get internal lock. */
  32. mov #0, r3
  33. mov #1, r4
  34. #if cond_lock != 0
  35. CMPXCHG (r3, @(cond_lock,r8), r4, r2)
  36. #else
  37. CMPXCHG (r3, @r8, r4, r2)
  38. #endif
  39. bf 1f
  40. 2:
  41. mov.l @(total_seq+4,r8),r0
  42. mov.l @(total_seq,r8),r1
  43. mov.l @(wakeup_seq+4,r8), r2
  44. cmp/hi r2, r0
  45. bt 3f
  46. cmp/hi r0, r2
  47. bt 4f
  48. mov.l @(wakeup_seq,r8), r2
  49. cmp/hi r2, r1
  50. bf 4f
  51. 3:
  52. /* Bump the wakeup number. */
  53. mov #1, r2
  54. mov #0, r3
  55. clrt
  56. mov.l @(wakeup_seq,r8),r0
  57. mov.l @(wakeup_seq+4,r8),r1
  58. addc r2, r0
  59. addc r3, r1
  60. mov.l r0,@(wakeup_seq,r8)
  61. mov.l r1,@(wakeup_seq+4,r8)
  62. mov.l @(cond_futex,r8),r0
  63. add r2, r0
  64. mov.l r0,@(cond_futex,r8)
  65. /* Wake up one thread. */
  66. mov r8, r4
  67. add #cond_futex, r4
  68. mov.l @(dep_mutex,r8), r0
  69. cmp/eq #-1, r0
  70. bt/s 99f
  71. mov #FUTEX_WAKE_OP, r5
  72. #ifdef __ASSUME_PRIVATE_FUTEX
  73. mov #(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), r5
  74. extu.b r5, r5
  75. #else
  76. stc gbr, r1
  77. mov.w .Lpfoff, r2
  78. add r2, r1
  79. mov.l @r1, r5
  80. mov #FUTEX_WAKE_OP, r0
  81. or r0, r5
  82. #endif
  83. 99:
  84. mov #1, r6
  85. mov #0, r7
  86. mov r8, r0
  87. add #cond_lock, r0
  88. mov.l .Lfutexop, r1
  89. mov #SYS_futex, r3
  90. extu.b r3, r3
  91. trapa #0x14
  92. SYSCALL_INST_PAD
  93. /* For any kind of error, we try again with WAKE.
  94. The general test also covers running on old kernels. */
  95. mov r0, r1
  96. mov #-12, r2
  97. shad r2, r1
  98. not r1, r1
  99. tst r1, r1
  100. bt 7f
  101. 6:
  102. mov #0, r0
  103. lds.l @r15+, pr
  104. rts
  105. mov.l @r15+, r8
  106. #ifndef __ASSUME_PRIVATE_FUTEX
  107. .Lpfoff:
  108. .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
  109. #endif
  110. .align 2
  111. .Lfutexop:
  112. .long FUTEX_OP_CLEAR_WAKE_IF_GT_ONE
  113. 7:
  114. /* r5 should be either FUTEX_WAKE_OP or
  115. FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */
  116. mov #(FUTEX_WAKE ^ FUTEX_WAKE_OP), r0
  117. xor r0, r5
  118. trapa #0x14
  119. SYSCALL_INST_PAD
  120. 4:
  121. /* Unlock. */
  122. #if cond_lock != 0
  123. DEC (@(cond_lock,r8), r2)
  124. #else
  125. DEC (@r8, r2)
  126. #endif
  127. tst r2, r2
  128. bt 6b
  129. 5:
  130. /* Unlock in loop requires wakeup. */
  131. mov r8, r4
  132. #if cond_lock != 0
  133. add #cond_lock, r4
  134. #endif
  135. mov.l @(dep_mutex,r8), r0
  136. cmp/eq #-1, r0
  137. bf/s 99f
  138. mov #LLL_PRIVATE, r5
  139. mov #LLL_SHARED, r5
  140. 99:
  141. mov.l .Lwake4, r1
  142. bsrf r1
  143. extu.b r5, r5
  144. .Lwake4b:
  145. bra 6b
  146. nop
  147. 1:
  148. /* Initial locking failed. */
  149. mov r8, r5
  150. #if cond_lock != 0
  151. add #cond_lock, r5
  152. #endif
  153. mov.l @(dep_mutex,r8), r0
  154. cmp/eq #-1, r0
  155. bf/s 99f
  156. mov #LLL_PRIVATE, r6
  157. mov #LLL_SHARED, r6
  158. 99:
  159. extu.b r6, r6
  160. mov.l .Lwait4, r1
  161. bsrf r1
  162. mov r2, r4
  163. .Lwait4b:
  164. bra 2b
  165. nop
  166. .align 2
  167. .Lwait4:
  168. .long __lll_lock_wait-.Lwait4b
  169. .Lwake4:
  170. .long __lll_unlock_wake-.Lwake4b
  171. .size __pthread_cond_signal, .-__pthread_cond_signal
  172. weak_alias (__pthread_cond_signal, pthread_cond_signal)