lowlevellock.S 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* Copyright (C) 2002, 2003, 2004, 2005 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, write to the Free
  14. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA. */
  16. #include <sysdep.h>
  17. #include <pthread-errnos.h>
  18. .text
  19. #ifndef LOCK
  20. # ifdef UP
  21. # define LOCK
  22. # else
  23. # define LOCK lock
  24. # endif
  25. #endif
  26. #define FUTEX_WAIT 0
  27. #define FUTEX_WAKE 1
  28. /* For the calculation see asm/vsyscall.h. */
  29. #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
  30. .globl __lll_mutex_lock_wait
  31. .type __lll_mutex_lock_wait,@function
  32. .hidden __lll_mutex_lock_wait
  33. .align 16
  34. __lll_mutex_lock_wait:
  35. pushq %r10
  36. pushq %rdx
  37. xorq %r10, %r10 /* No timeout. */
  38. movl $2, %edx
  39. #if FUTEX_WAIT == 0
  40. xorl %esi, %esi
  41. #else
  42. movl $FUTEX_WAIT, %esi
  43. #endif
  44. cmpl %edx, %eax /* NB: %edx == 2 */
  45. jne 2f
  46. 1: movl $SYS_futex, %eax
  47. syscall
  48. 2: movl %edx, %eax
  49. xchgl %eax, (%rdi) /* NB: lock is implied */
  50. testl %eax, %eax
  51. jnz 1b
  52. popq %rdx
  53. popq %r10
  54. retq
  55. .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
  56. #ifdef NOT_IN_libc
  57. .globl __lll_mutex_timedlock_wait
  58. .type __lll_mutex_timedlock_wait,@function
  59. .hidden __lll_mutex_timedlock_wait
  60. .align 16
  61. __lll_mutex_timedlock_wait:
  62. /* Check for a valid timeout value. */
  63. cmpq $1000000000, 8(%rdx)
  64. jae 3f
  65. pushq %r8
  66. pushq %r9
  67. pushq %r12
  68. pushq %r13
  69. pushq %r14
  70. /* Stack frame for the timespec and timeval structs. */
  71. subq $16, %rsp
  72. movq %rdi, %r12
  73. movq %rdx, %r13
  74. 1:
  75. /* Get current time. */
  76. movq %rsp, %rdi
  77. xorl %esi, %esi
  78. movq $VSYSCALL_ADDR_vgettimeofday, %rax
  79. /* This is a regular function call, all caller-save registers
  80. might be clobbered. */
  81. callq *%rax
  82. /* Compute relative timeout. */
  83. movq 8(%rsp), %rax
  84. movl $1000, %edi
  85. mul %rdi /* Milli seconds to nano seconds. */
  86. movq (%r13), %rdi
  87. movq 8(%r13), %rsi
  88. subq (%rsp), %rdi
  89. subq %rax, %rsi
  90. jns 4f
  91. addq $1000000000, %rsi
  92. decq %rdi
  93. 4: testq %rdi, %rdi
  94. js 5f /* Time is already up. */
  95. /* Futex call. */
  96. movq %rdi, (%rsp) /* Store relative timeout. */
  97. movq %rsi, 8(%rsp)
  98. movl $1, %eax
  99. movl $2, %edx
  100. LOCK
  101. cmpxchgl %edx, (%r12)
  102. testl %eax, %eax
  103. je 8f
  104. movq %rsp, %r10
  105. #if FUTEX_WAIT == 0
  106. xorl %esi, %esi
  107. #else
  108. movl $FUTEX_WAIT, %esi
  109. #endif
  110. movq %r12, %rdi
  111. movl $SYS_futex, %eax
  112. syscall
  113. movq %rax, %rcx
  114. 8: /* NB: %edx == 2 */
  115. xorl %eax, %eax
  116. LOCK
  117. cmpxchgl %edx, (%rdi)
  118. jnz 7f
  119. 6: addq $16, %rsp
  120. popq %r14
  121. popq %r13
  122. popq %r12
  123. popq %r9
  124. popq %r8
  125. retq
  126. /* Check whether the time expired. */
  127. 7: cmpq $-ETIMEDOUT, %rcx
  128. je 5f
  129. /* Make sure the current holder knows we are going to sleep. */
  130. movl %edx, %eax
  131. xchgl %eax, (%rdi)
  132. testl %eax, %eax
  133. jz 6b
  134. jmp 1b
  135. 3: movl $EINVAL, %eax
  136. retq
  137. 5: movl $ETIMEDOUT, %eax
  138. jmp 6b
  139. .size __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
  140. #endif
  141. #ifdef NOT_IN_libc
  142. .globl lll_unlock_wake_cb
  143. .type lll_unlock_wake_cb,@function
  144. .hidden lll_unlock_wake_cb
  145. .align 16
  146. lll_unlock_wake_cb:
  147. pushq %rsi
  148. pushq %rdx
  149. LOCK
  150. addl $1, (%rdi)
  151. jng 1f
  152. popq %rdx
  153. popq %rsi
  154. retq
  155. .size lll_unlock_wake_cb,.-lll_unlock_wake_cb
  156. #endif
  157. .globl __lll_mutex_unlock_wake
  158. .type __lll_mutex_unlock_wake,@function
  159. .hidden __lll_mutex_unlock_wake
  160. .align 16
  161. __lll_mutex_unlock_wake:
  162. pushq %rsi
  163. pushq %rdx
  164. movl $0, (%rdi)
  165. movl $FUTEX_WAKE, %esi
  166. movl $1, %edx /* Wake one thread. */
  167. movl $SYS_futex, %eax
  168. syscall
  169. popq %rdx
  170. popq %rsi
  171. retq
  172. .size __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
  173. #ifdef NOT_IN_libc
  174. .globl __lll_timedwait_tid
  175. .type __lll_timedwait_tid,@function
  176. .hidden __lll_timedwait_tid
  177. .align 16
  178. __lll_timedwait_tid:
  179. pushq %r12
  180. pushq %r13
  181. movq %rdi, %r12
  182. movq %rsi, %r13
  183. subq $16, %rsp
  184. /* Get current time. */
  185. 2: movq %rsp, %rdi
  186. xorl %esi, %esi
  187. movq $VSYSCALL_ADDR_vgettimeofday, %rax
  188. callq *%rax
  189. /* Compute relative timeout. */
  190. movq 8(%rsp), %rax
  191. movl $1000, %edi
  192. mul %rdi /* Milli seconds to nano seconds. */
  193. movq (%r13), %rdi
  194. movq 8(%r13), %rsi
  195. subq (%rsp), %rdi
  196. subq %rax, %rsi
  197. jns 5f
  198. addq $1000000000, %rsi
  199. decq %rdi
  200. 5: testq %rdi, %rdi
  201. js 6f /* Time is already up. */
  202. movq %rdi, (%rsp) /* Store relative timeout. */
  203. movq %rsi, 8(%rsp)
  204. movl (%r12), %edx
  205. testl %edx, %edx
  206. jz 4f
  207. movq %rsp, %r10
  208. #if FUTEX_WAIT == 0
  209. xorl %esi, %esi
  210. #else
  211. movl $FUTEX_WAIT, %esi
  212. #endif
  213. movq %r12, %rdi
  214. movl $SYS_futex, %eax
  215. syscall
  216. cmpl $0, (%rdi)
  217. jne 1f
  218. 4: xorl %eax, %eax
  219. 8: addq $16, %rsp
  220. popq %r13
  221. popq %r12
  222. retq
  223. 1: cmpq $-ETIMEDOUT, %rax
  224. jne 2b
  225. 6: movl $ETIMEDOUT, %eax
  226. jmp 8b
  227. .size __lll_timedwait_tid,.-__lll_timedwait_tid
  228. #endif