pthread_cond_broadcast.S 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* Copyright (C) 2002,2003,2004,2006,2007,2009 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <sysdep.h>
  16. #include <lowlevellock.h>
  17. #include <lowlevelcond.h>
  18. #include <bits/kernel-features.h>
  19. #include <pthread-pi-defines.h>
  20. #include <pthread-errnos.h>
  21. #include <tls.h>
  22. .text
  23. /* int pthread_cond_broadcast (pthread_cond_t *cond) */
  24. .globl __pthread_cond_broadcast
  25. .type __pthread_cond_broadcast, @function
  26. .protected __pthread_cond_broadcast
  27. .align 16
  28. __pthread_cond_broadcast:
  29. cfi_startproc
  30. pushl %ebx
  31. cfi_adjust_cfa_offset(4)
  32. cfi_rel_offset(%ebx, 0)
  33. pushl %esi
  34. cfi_adjust_cfa_offset(4)
  35. cfi_rel_offset(%esi, 0)
  36. pushl %edi
  37. cfi_adjust_cfa_offset(4)
  38. cfi_rel_offset(%edi, 0)
  39. pushl %ebp
  40. cfi_adjust_cfa_offset(4)
  41. cfi_rel_offset(%ebp, 0)
  42. cfi_remember_state
  43. movl 20(%esp), %ebx
  44. /* Get internal lock. */
  45. movl $1, %edx
  46. xorl %eax, %eax
  47. LOCK
  48. #if cond_lock == 0
  49. cmpxchgl %edx, (%ebx)
  50. #else
  51. cmpxchgl %edx, cond_lock(%ebx)
  52. #endif
  53. jnz 1f
  54. 2: addl $cond_futex, %ebx
  55. movl total_seq+4-cond_futex(%ebx), %eax
  56. movl total_seq-cond_futex(%ebx), %ebp
  57. cmpl wakeup_seq+4-cond_futex(%ebx), %eax
  58. ja 3f
  59. jb 4f
  60. cmpl wakeup_seq-cond_futex(%ebx), %ebp
  61. jna 4f
  62. /* Cause all currently waiting threads to recognize they are
  63. woken up. */
  64. 3: movl %ebp, wakeup_seq-cond_futex(%ebx)
  65. movl %eax, wakeup_seq-cond_futex+4(%ebx)
  66. movl %ebp, woken_seq-cond_futex(%ebx)
  67. movl %eax, woken_seq-cond_futex+4(%ebx)
  68. addl %ebp, %ebp
  69. addl $1, broadcast_seq-cond_futex(%ebx)
  70. movl %ebp, (%ebx)
  71. /* Get the address of the mutex used. */
  72. movl dep_mutex-cond_futex(%ebx), %edi
  73. /* Unlock. */
  74. LOCK
  75. subl $1, cond_lock-cond_futex(%ebx)
  76. jne 7f
  77. /* Don't use requeue for pshared condvars. */
  78. 8: cmpl $-1, %edi
  79. je 9f
  80. /* Do not use requeue for pshared condvars. */
  81. testl $PS_BIT, MUTEX_KIND(%edi)
  82. jne 9f
  83. /* Requeue to a non-robust PI mutex if the PI bit is set and
  84. the robust bit is not set. */
  85. movl MUTEX_KIND(%edi), %eax
  86. andl $(ROBUST_BIT|PI_BIT), %eax
  87. cmpl $PI_BIT, %eax
  88. je 81f
  89. /* Wake up all threads. */
  90. #ifdef __ASSUME_PRIVATE_FUTEX
  91. movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
  92. #else
  93. movl %gs:PRIVATE_FUTEX, %ecx
  94. orl $FUTEX_CMP_REQUEUE, %ecx
  95. #endif
  96. movl $SYS_futex, %eax
  97. movl $0x7fffffff, %esi
  98. movl $1, %edx
  99. /* Get the address of the futex involved. */
  100. # if MUTEX_FUTEX != 0
  101. addl $MUTEX_FUTEX, %edi
  102. # endif
  103. /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
  104. ENTER_KERNEL */
  105. int $0x80
  106. /* For any kind of error, which mainly is EAGAIN, we try again
  107. with WAKE. The general test also covers running on old
  108. kernels. */
  109. cmpl $0xfffff001, %eax
  110. jae 9f
  111. 6: xorl %eax, %eax
  112. popl %ebp
  113. cfi_adjust_cfa_offset(-4)
  114. cfi_restore(%ebp)
  115. popl %edi
  116. cfi_adjust_cfa_offset(-4)
  117. cfi_restore(%edi)
  118. popl %esi
  119. cfi_adjust_cfa_offset(-4)
  120. cfi_restore(%esi)
  121. popl %ebx
  122. cfi_adjust_cfa_offset(-4)
  123. cfi_restore(%ebx)
  124. ret
  125. cfi_restore_state
  126. 81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
  127. movl $SYS_futex, %eax
  128. movl $0x7fffffff, %esi
  129. movl $1, %edx
  130. /* Get the address of the futex involved. */
  131. # if MUTEX_FUTEX != 0
  132. addl $MUTEX_FUTEX, %edi
  133. # endif
  134. int $0x80
  135. /* For any kind of error, which mainly is EAGAIN, we try again
  136. with WAKE. The general test also covers running on old
  137. kernels. */
  138. cmpl $0xfffff001, %eax
  139. jb 6b
  140. jmp 9f
  141. /* Initial locking failed. */
  142. 1:
  143. #if cond_lock == 0
  144. movl %ebx, %edx
  145. #else
  146. leal cond_lock(%ebx), %edx
  147. #endif
  148. #if (LLL_SHARED-LLL_PRIVATE) > 255
  149. xorl %ecx, %ecx
  150. #endif
  151. cmpl $-1, dep_mutex(%ebx)
  152. setne %cl
  153. subl $1, %ecx
  154. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  155. #if LLL_PRIVATE != 0
  156. addl $LLL_PRIVATE, %ecx
  157. #endif
  158. call __lll_lock_wait
  159. jmp 2b
  160. .align 16
  161. /* Unlock. */
  162. 4: LOCK
  163. subl $1, cond_lock-cond_futex(%ebx)
  164. je 6b
  165. /* Unlock in loop requires wakeup. */
  166. 5: leal cond_lock-cond_futex(%ebx), %eax
  167. #if (LLL_SHARED-LLL_PRIVATE) > 255
  168. xorl %ecx, %ecx
  169. #endif
  170. cmpl $-1, dep_mutex-cond_futex(%ebx)
  171. setne %cl
  172. subl $1, %ecx
  173. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  174. #if LLL_PRIVATE != 0
  175. addl $LLL_PRIVATE, %ecx
  176. #endif
  177. call __lll_unlock_wake
  178. jmp 6b
  179. /* Unlock in loop requires wakeup. */
  180. 7: leal cond_lock-cond_futex(%ebx), %eax
  181. #if (LLL_SHARED-LLL_PRIVATE) > 255
  182. xorl %ecx, %ecx
  183. #endif
  184. cmpl $-1, dep_mutex-cond_futex(%ebx)
  185. setne %cl
  186. subl $1, %ecx
  187. andl $(LLL_SHARED-LLL_PRIVATE), %ecx
  188. #if LLL_PRIVATE != 0
  189. addl $LLL_PRIVATE, %ecx
  190. #endif
  191. call __lll_unlock_wake
  192. jmp 8b
  193. 9: /* The futex requeue functionality is not available. */
  194. movl $0x7fffffff, %edx
  195. #if FUTEX_PRIVATE_FLAG > 255
  196. xorl %ecx, %ecx
  197. #endif
  198. cmpl $-1, dep_mutex-cond_futex(%ebx)
  199. sete %cl
  200. subl $1, %ecx
  201. #ifdef __ASSUME_PRIVATE_FUTEX
  202. andl $FUTEX_PRIVATE_FLAG, %ecx
  203. #else
  204. andl %gs:PRIVATE_FUTEX, %ecx
  205. #endif
  206. addl $FUTEX_WAKE, %ecx
  207. movl $SYS_futex, %eax
  208. ENTER_KERNEL
  209. jmp 6b
  210. cfi_endproc
  211. .size __pthread_cond_broadcast, .-__pthread_cond_broadcast
  212. weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast)