lowlevellock.S 5.2 KB

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