pthread_cond_broadcast.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009
  2. Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. #include <sysdep.h>
  17. #include <lowlevellock.h>
  18. #include <lowlevelcond.h>
  19. #include <bits/kernel-features.h>
  20. #include <pthread-pi-defines.h>
  21. #include <pthread-errnos.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. /* Get internal lock. */
  30. movl $1, %esi
  31. xorl %eax, %eax
  32. LOCK
  33. #if cond_lock == 0
  34. cmpxchgl %esi, (%rdi)
  35. #else
  36. cmpxchgl %esi, cond_lock(%rdi)
  37. #endif
  38. jnz 1f
  39. 2: addq $cond_futex, %rdi
  40. movq total_seq-cond_futex(%rdi), %r9
  41. cmpq wakeup_seq-cond_futex(%rdi), %r9
  42. jna 4f
  43. /* Cause all currently waiting threads to recognize they are
  44. woken up. */
  45. movq %r9, wakeup_seq-cond_futex(%rdi)
  46. movq %r9, woken_seq-cond_futex(%rdi)
  47. addq %r9, %r9
  48. movl %r9d, (%rdi)
  49. incl broadcast_seq-cond_futex(%rdi)
  50. /* Get the address of the mutex used. */
  51. movq dep_mutex-cond_futex(%rdi), %r8
  52. /* Unlock. */
  53. LOCK
  54. decl cond_lock-cond_futex(%rdi)
  55. jne 7f
  56. 8: cmpq $-1, %r8
  57. je 9f
  58. /* Do not use requeue for pshared condvars. */
  59. testl $PS_BIT, MUTEX_KIND(%r8)
  60. jne 9f
  61. /* Requeue to a PI mutex if the PI bit is set. */
  62. movl MUTEX_KIND(%r8), %eax
  63. andl $(ROBUST_BIT|PI_BIT), %eax
  64. cmpl $PI_BIT, %eax
  65. je 81f
  66. /* Wake up all threads. */
  67. #ifdef __ASSUME_PRIVATE_FUTEX
  68. movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi
  69. #else
  70. movl %fs:PRIVATE_FUTEX, %esi
  71. orl $FUTEX_CMP_REQUEUE, %esi
  72. #endif
  73. movl $SYS_futex, %eax
  74. movl $1, %edx
  75. movl $0x7fffffff, %r10d
  76. syscall
  77. /* For any kind of error, which mainly is EAGAIN, we try again
  78. with WAKE. The general test also covers running on old
  79. kernels. */
  80. cmpq $-4095, %rax
  81. jae 9f
  82. 10: xorl %eax, %eax
  83. retq
  84. /* Wake up all threads. */
  85. 81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
  86. movl $SYS_futex, %eax
  87. movl $1, %edx
  88. movl $0x7fffffff, %r10d
  89. syscall
  90. /* For any kind of error, which mainly is EAGAIN, we try again
  91. with WAKE. The general test also covers running on old
  92. kernels. */
  93. cmpq $-4095, %rax
  94. jb 10b
  95. jmp 9f
  96. .align 16
  97. /* Unlock. */
  98. 4: LOCK
  99. decl cond_lock-cond_futex(%rdi)
  100. jne 5f
  101. 6: xorl %eax, %eax
  102. retq
  103. /* Initial locking failed. */
  104. 1:
  105. #if cond_lock != 0
  106. addq $cond_lock, %rdi
  107. #endif
  108. cmpq $-1, dep_mutex-cond_lock(%rdi)
  109. movl $LLL_PRIVATE, %eax
  110. movl $LLL_SHARED, %esi
  111. cmovne %eax, %esi
  112. callq __lll_lock_wait
  113. #if cond_lock != 0
  114. subq $cond_lock, %rdi
  115. #endif
  116. jmp 2b
  117. /* Unlock in loop requires wakeup. */
  118. 5: addq $cond_lock-cond_futex, %rdi
  119. cmpq $-1, dep_mutex-cond_lock(%rdi)
  120. movl $LLL_PRIVATE, %eax
  121. movl $LLL_SHARED, %esi
  122. cmovne %eax, %esi
  123. callq __lll_unlock_wake
  124. jmp 6b
  125. /* Unlock in loop requires wakeup. */
  126. 7: addq $cond_lock-cond_futex, %rdi
  127. cmpq $-1, %r8
  128. movl $LLL_PRIVATE, %eax
  129. movl $LLL_SHARED, %esi
  130. cmovne %eax, %esi
  131. callq __lll_unlock_wake
  132. subq $cond_lock-cond_futex, %rdi
  133. jmp 8b
  134. 9: /* The futex requeue functionality is not available. */
  135. cmpq $-1, %r8
  136. movl $0x7fffffff, %edx
  137. #ifdef __ASSUME_PRIVATE_FUTEX
  138. movl $FUTEX_WAKE, %eax
  139. movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
  140. cmove %eax, %esi
  141. #else
  142. movl $0, %eax
  143. movl %fs:PRIVATE_FUTEX, %esi
  144. cmove %eax, %esi
  145. orl $FUTEX_WAKE, %esi
  146. #endif
  147. movl $SYS_futex, %eax
  148. syscall
  149. jmp 10b
  150. .size __pthread_cond_broadcast, .-__pthread_cond_broadcast
  151. weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast)