lowlevelrobustlock.S 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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 <pthread-errnos.h>
  18. #include <lowlevellock.h>
  19. #include <lowlevelrobustlock.h>
  20. #include <bits/kernel-features.h>
  21. .text
  22. #define FUTEX_WAITERS 0x80000000
  23. #define FUTEX_OWNER_DIED 0x40000000
  24. #ifdef __ASSUME_PRIVATE_FUTEX
  25. # define LOAD_FUTEX_WAIT(reg) \
  26. xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
  27. # define LOAD_FUTEX_WAIT_ABS(reg) \
  28. xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
  29. #else
  30. # if FUTEX_WAIT == 0
  31. # define LOAD_FUTEX_WAIT(reg) \
  32. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  33. andl %fs:PRIVATE_FUTEX, reg
  34. # else
  35. # define LOAD_FUTEX_WAIT(reg) \
  36. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  37. andl %fs:PRIVATE_FUTEX, reg ; \
  38. orl $FUTEX_WAIT, reg
  39. # endif
  40. # define LOAD_FUTEX_WAIT_ABS(reg) \
  41. xorl $FUTEX_PRIVATE_FLAG, reg ; \
  42. andl %fs:PRIVATE_FUTEX, reg ; \
  43. orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
  44. #endif
  45. /* For the calculation see asm/vsyscall.h. */
  46. #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
  47. .globl __lll_robust_lock_wait
  48. .type __lll_robust_lock_wait,@function
  49. .hidden __lll_robust_lock_wait
  50. .align 16
  51. __lll_robust_lock_wait:
  52. cfi_startproc
  53. pushq %r10
  54. cfi_adjust_cfa_offset(8)
  55. pushq %rdx
  56. cfi_adjust_cfa_offset(8)
  57. cfi_offset(%r10, -16)
  58. cfi_offset(%rdx, -24)
  59. xorq %r10, %r10 /* No timeout. */
  60. LOAD_FUTEX_WAIT (%esi)
  61. 4: movl %eax, %edx
  62. orl $FUTEX_WAITERS, %edx
  63. testl $FUTEX_OWNER_DIED, %eax
  64. jnz 3f
  65. cmpl %edx, %eax
  66. je 1f
  67. LOCK
  68. cmpxchgl %edx, (%rdi)
  69. jnz 2f
  70. 1: movl $SYS_futex, %eax
  71. syscall
  72. movl (%rdi), %eax
  73. 2: testl %eax, %eax
  74. jne 4b
  75. movl %fs:TID, %edx
  76. orl $FUTEX_WAITERS, %edx
  77. LOCK
  78. cmpxchgl %edx, (%rdi)
  79. jnz 4b
  80. /* NB: %rax == 0 */
  81. 3: popq %rdx
  82. cfi_adjust_cfa_offset(-8)
  83. cfi_restore(%rdx)
  84. popq %r10
  85. cfi_adjust_cfa_offset(-8)
  86. cfi_restore(%r10)
  87. retq
  88. cfi_endproc
  89. .size __lll_robust_lock_wait,.-__lll_robust_lock_wait
  90. .globl __lll_robust_timedlock_wait
  91. .type __lll_robust_timedlock_wait,@function
  92. .hidden __lll_robust_timedlock_wait
  93. .align 16
  94. __lll_robust_timedlock_wait:
  95. cfi_startproc
  96. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  97. # ifdef __PIC__
  98. cmpl $0, __have_futex_clock_realtime@GOTOFF(%rip)
  99. # else
  100. cmpl $0, __have_futex_clock_realtime
  101. # endif
  102. je .Lreltmo
  103. # endif
  104. pushq %r9
  105. cfi_adjust_cfa_offset(8)
  106. cfi_rel_offset(%r9, 0)
  107. movq %rdx, %r10
  108. movl $0xffffffff, %r9d
  109. LOAD_FUTEX_WAIT_ABS (%esi)
  110. 1: testl $FUTEX_OWNER_DIED, %eax
  111. jnz 3f
  112. movl %eax, %edx
  113. orl $FUTEX_WAITERS, %edx
  114. cmpl %eax, %edx
  115. je 5f
  116. LOCK
  117. cmpxchgl %edx, (%rdi)
  118. movq $0, %rcx /* Must use mov to avoid changing cc. */
  119. jnz 6f
  120. 5: movl $SYS_futex, %eax
  121. syscall
  122. movl %eax, %ecx
  123. movl (%rdi), %eax
  124. 6: testl %eax, %eax
  125. jne 2f
  126. movl %fs:TID, %edx
  127. orl $FUTEX_WAITERS, %edx
  128. LOCK
  129. cmpxchgl %edx, (%rdi)
  130. jnz 2f
  131. 3: popq %r9
  132. cfi_adjust_cfa_offset(-8)
  133. cfi_restore(%r9)
  134. retq
  135. cfi_adjust_cfa_offset(8)
  136. cfi_rel_offset(%r9, 0)
  137. /* Check whether the time expired. */
  138. 2: cmpl $-ETIMEDOUT, %ecx
  139. je 4f
  140. cmpl $-EINVAL, %ecx
  141. jne 1b
  142. 4: movl %ecx, %eax
  143. negl %eax
  144. jmp 3b
  145. cfi_adjust_cfa_offset(-8)
  146. cfi_restore(%r9)
  147. # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  148. .Lreltmo:
  149. /* Check for a valid timeout value. */
  150. cmpq $1000000000, 8(%rdx)
  151. jae 3f
  152. pushq %r8
  153. cfi_adjust_cfa_offset(8)
  154. pushq %r9
  155. cfi_adjust_cfa_offset(8)
  156. pushq %r12
  157. cfi_adjust_cfa_offset(8)
  158. pushq %r13
  159. cfi_adjust_cfa_offset(8)
  160. cfi_offset(%r8, -16)
  161. cfi_offset(%r9, -24)
  162. cfi_offset(%r12, -32)
  163. cfi_offset(%r13, -40)
  164. pushq %rsi
  165. cfi_adjust_cfa_offset(8)
  166. /* Stack frame for the timespec and timeval structs. */
  167. subq $32, %rsp
  168. cfi_adjust_cfa_offset(32)
  169. movq %rdi, %r12
  170. movq %rdx, %r13
  171. 1: movq %rax, 16(%rsp)
  172. /* Get current time. */
  173. movq %rsp, %rdi
  174. xorl %esi, %esi
  175. movq $VSYSCALL_ADDR_vgettimeofday, %rax
  176. /* This is a regular function call, all caller-save registers
  177. might be clobbered. */
  178. callq *%rax
  179. /* Compute relative timeout. */
  180. movq 8(%rsp), %rax
  181. movl $1000, %edi
  182. mul %rdi /* Milli seconds to nano seconds. */
  183. movq (%r13), %rdi
  184. movq 8(%r13), %rsi
  185. subq (%rsp), %rdi
  186. subq %rax, %rsi
  187. jns 4f
  188. addq $1000000000, %rsi
  189. decq %rdi
  190. 4: testq %rdi, %rdi
  191. js 8f /* Time is already up. */
  192. /* Futex call. */
  193. movq %rdi, (%rsp) /* Store relative timeout. */
  194. movq %rsi, 8(%rsp)
  195. movq 16(%rsp), %rdx
  196. movl %edx, %eax
  197. orl $FUTEX_WAITERS, %edx
  198. testl $FUTEX_OWNER_DIED, %eax
  199. jnz 6f
  200. cmpl %eax, %edx
  201. je 2f
  202. LOCK
  203. cmpxchgl %edx, (%r12)
  204. movq $0, %rcx /* Must use mov to avoid changing cc. */
  205. jnz 5f
  206. 2: movq %rsp, %r10
  207. movl 32(%rsp), %esi
  208. LOAD_FUTEX_WAIT (%esi)
  209. movq %r12, %rdi
  210. movl $SYS_futex, %eax
  211. syscall
  212. movq %rax, %rcx
  213. movl (%r12), %eax
  214. 5: testl %eax, %eax
  215. jne 7f
  216. movl %fs:TID, %edx
  217. orl $FUTEX_WAITERS, %edx
  218. LOCK
  219. cmpxchgl %edx, (%r12)
  220. jnz 7f
  221. 6: addq $40, %rsp
  222. cfi_adjust_cfa_offset(-40)
  223. popq %r13
  224. cfi_adjust_cfa_offset(-8)
  225. cfi_restore(%r13)
  226. popq %r12
  227. cfi_adjust_cfa_offset(-8)
  228. cfi_restore(%r12)
  229. popq %r9
  230. cfi_adjust_cfa_offset(-8)
  231. cfi_restore(%r9)
  232. popq %r8
  233. cfi_adjust_cfa_offset(-8)
  234. cfi_restore(%r8)
  235. retq
  236. 3: movl $EINVAL, %eax
  237. retq
  238. cfi_adjust_cfa_offset(72)
  239. cfi_offset(%r8, -16)
  240. cfi_offset(%r9, -24)
  241. cfi_offset(%r12, -32)
  242. cfi_offset(%r13, -40)
  243. /* Check whether the time expired. */
  244. 7: cmpl $-ETIMEDOUT, %ecx
  245. jne 1b
  246. 8: movl $ETIMEDOUT, %eax
  247. jmp 6b
  248. #endif
  249. cfi_endproc
  250. .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait