sem_timedwait.S 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /* Copyright (C) 2002, 2003, 2005, 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 <bits/kernel-features.h>
  17. #include <lowlevellock.h>
  18. #include <pthread-errnos.h>
  19. #include <structsem.h>
  20. /* For the calculation see asm/vsyscall.h. */
  21. #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
  22. .text
  23. .globl sem_timedwait
  24. .type sem_timedwait,@function
  25. .align 16
  26. sem_timedwait:
  27. .LSTARTCODE:
  28. cfi_startproc
  29. #if VALUE == 0
  30. movl (%rdi), %eax
  31. #else
  32. movl VALUE(%rdi), %eax
  33. #endif
  34. 2: testl %eax, %eax
  35. je 1f
  36. leaq -1(%rax), %rdx
  37. LOCK
  38. #if VALUE == 0
  39. cmpxchgl %edx, (%rdi)
  40. #else
  41. cmpxchgl %edx, VALUE(%rdi)
  42. #endif
  43. jne 2b
  44. xorl %eax, %eax
  45. retq
  46. /* Check whether the timeout value is valid. */
  47. 1: cmpq $1000000000, 8(%rsi)
  48. jae 6f
  49. #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  50. # ifdef __PIC__
  51. cmpl $0, __have_futex_clock_realtime@GOTOFF(%rip)
  52. # else
  53. cmpl $0, __have_futex_clock_realtime
  54. # endif
  55. je .Lreltmo
  56. #endif
  57. /* This push is only needed to store the sem_t pointer for the
  58. exception handler. */
  59. pushq %rdi
  60. cfi_adjust_cfa_offset(8)
  61. movq %rsi, %r10
  62. LOCK
  63. addq $1, NWAITERS(%rdi)
  64. .LcleanupSTART:
  65. 13: call __pthread_enable_asynccancel
  66. movl %eax, %r8d
  67. #if VALUE != 0
  68. leaq VALUE(%rdi), %rdi
  69. #endif
  70. movl $0xffffffff, %r9d
  71. movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
  72. orl PRIVATE(%rdi), %esi
  73. movl $SYS_futex, %eax
  74. xorl %edx, %edx
  75. syscall
  76. movq %rax, %r9
  77. #if VALUE != 0
  78. leaq -VALUE(%rdi), %rdi
  79. #endif
  80. xchgq %r8, %rdi
  81. call __pthread_disable_asynccancel
  82. .LcleanupEND:
  83. movq %r8, %rdi
  84. testq %r9, %r9
  85. je 11f
  86. cmpq $-EWOULDBLOCK, %r9
  87. jne 3f
  88. 11:
  89. #if VALUE == 0
  90. movl (%rdi), %eax
  91. #else
  92. movl VALUE(%rdi), %eax
  93. #endif
  94. 14: testl %eax, %eax
  95. je 13b
  96. leaq -1(%rax), %rcx
  97. LOCK
  98. #if VALUE == 0
  99. cmpxchgl %ecx, (%rdi)
  100. #else
  101. cmpxchgl %ecx, VALUE(%rdi)
  102. #endif
  103. jne 14b
  104. xorl %eax, %eax
  105. 15: LOCK
  106. subq $1, NWAITERS(%rdi)
  107. leaq 8(%rsp), %rsp
  108. cfi_adjust_cfa_offset(-8)
  109. retq
  110. cfi_adjust_cfa_offset(8)
  111. 3: negq %r9
  112. #if USE___THREAD
  113. movq errno@gottpoff(%rip), %rdx
  114. movl %r9d, %fs:(%rdx)
  115. #else
  116. callq __errno_location@plt
  117. movl %r9d, (%rax)
  118. #endif
  119. orl $-1, %eax
  120. jmp 15b
  121. cfi_adjust_cfa_offset(-8)
  122. 6:
  123. #if USE___THREAD
  124. movq errno@gottpoff(%rip), %rdx
  125. movl $EINVAL, %fs:(%rdx)
  126. #else
  127. callq __errno_location@plt
  128. movl $EINVAL, (%rax)
  129. #endif
  130. orl $-1, %eax
  131. retq
  132. #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  133. .Lreltmo:
  134. pushq %r12
  135. cfi_adjust_cfa_offset(8)
  136. cfi_rel_offset(%r12, 0)
  137. pushq %r13
  138. cfi_adjust_cfa_offset(8)
  139. cfi_rel_offset(%r13, 0)
  140. pushq %r14
  141. cfi_adjust_cfa_offset(8)
  142. cfi_rel_offset(%r14, 0)
  143. #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
  144. # define STACKFRAME 8
  145. #else
  146. # define STACKFRAME 24
  147. #endif
  148. subq $STACKFRAME, %rsp
  149. cfi_adjust_cfa_offset(STACKFRAME)
  150. movq %rdi, %r12
  151. movq %rsi, %r13
  152. LOCK
  153. addq $1, NWAITERS(%r12)
  154. 7: xorl %esi, %esi
  155. movq %rsp, %rdi
  156. movq $VSYSCALL_ADDR_vgettimeofday, %rax
  157. callq *%rax
  158. /* Compute relative timeout. */
  159. movq 8(%rsp), %rax
  160. movl $1000, %edi
  161. mul %rdi /* Milli seconds to nano seconds. */
  162. movq (%r13), %rdi
  163. movq 8(%r13), %rsi
  164. subq (%rsp), %rdi
  165. subq %rax, %rsi
  166. jns 5f
  167. addq $1000000000, %rsi
  168. decq %rdi
  169. 5: testq %rdi, %rdi
  170. movl $ETIMEDOUT, %r14d
  171. js 36f /* Time is already up. */
  172. movq %rdi, (%rsp) /* Store relative timeout. */
  173. movq %rsi, 8(%rsp)
  174. .LcleanupSTART2:
  175. call __pthread_enable_asynccancel
  176. movl %eax, 16(%rsp)
  177. movq %rsp, %r10
  178. # if VALUE == 0
  179. movq %r12, %rdi
  180. # else
  181. leaq VALUE(%r12), %rdi
  182. # endif
  183. # if FUTEX_WAIT == 0
  184. movl PRIVATE(%rdi), %esi
  185. # else
  186. movl $FUTEX_WAIT, %esi
  187. orl PRIVATE(%rdi), %esi
  188. # endif
  189. movl $SYS_futex, %eax
  190. xorl %edx, %edx
  191. syscall
  192. movq %rax, %r14
  193. movl 16(%rsp), %edi
  194. call __pthread_disable_asynccancel
  195. .LcleanupEND2:
  196. testq %r14, %r14
  197. je 9f
  198. cmpq $-EWOULDBLOCK, %r14
  199. jne 33f
  200. 9:
  201. # if VALUE == 0
  202. movl (%r12), %eax
  203. # else
  204. movl VALUE(%r12), %eax
  205. # endif
  206. 8: testl %eax, %eax
  207. je 7b
  208. leaq -1(%rax), %rcx
  209. LOCK
  210. # if VALUE == 0
  211. cmpxchgl %ecx, (%r12)
  212. # else
  213. cmpxchgl %ecx, VALUE(%r12)
  214. # endif
  215. jne 8b
  216. xorl %eax, %eax
  217. 45: LOCK
  218. subq $1, NWAITERS(%r12)
  219. addq $STACKFRAME, %rsp
  220. cfi_adjust_cfa_offset(-STACKFRAME)
  221. popq %r14
  222. cfi_adjust_cfa_offset(-8)
  223. cfi_restore(%r14)
  224. popq %r13
  225. cfi_adjust_cfa_offset(-8)
  226. cfi_restore(%r13)
  227. popq %r12
  228. cfi_adjust_cfa_offset(-8)
  229. cfi_restore(%r12)
  230. retq
  231. cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
  232. cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
  233. cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
  234. cfi_rel_offset(%r14, STACKFRAME)
  235. 33: negq %r14
  236. 36:
  237. #if USE___THREAD
  238. movq errno@gottpoff(%rip), %rdx
  239. movl %r14d, %fs:(%rdx)
  240. #else
  241. callq __errno_location@plt
  242. movl %r14d, (%rax)
  243. #endif
  244. orl $-1, %eax
  245. jmp 45b
  246. #endif
  247. cfi_endproc
  248. .size sem_timedwait,.-sem_timedwait
  249. .type sem_timedwait_cleanup,@function
  250. sem_timedwait_cleanup:
  251. cfi_startproc
  252. cfi_adjust_cfa_offset(8)
  253. movq (%rsp), %rdi
  254. LOCK
  255. subq $1, NWAITERS(%rdi)
  256. movq %rax, %rdi
  257. .LcallUR:
  258. call _Unwind_Resume@PLT
  259. hlt
  260. .LENDCODE:
  261. cfi_endproc
  262. .size sem_timedwait_cleanup,.-sem_timedwait_cleanup
  263. #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  264. .type sem_timedwait_cleanup2,@function
  265. sem_timedwait_cleanup2:
  266. cfi_startproc
  267. cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
  268. cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
  269. cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
  270. cfi_rel_offset(%r14, STACKFRAME)
  271. LOCK
  272. subq $1, NWAITERS(%r12)
  273. movq %rax, %rdi
  274. movq STACKFRAME(%rsp), %r14
  275. movq STACKFRAME+8(%rsp), %r13
  276. movq STACKFRAME+16(%rsp), %r12
  277. .LcallUR2:
  278. call _Unwind_Resume@PLT
  279. hlt
  280. .LENDCODE2:
  281. cfi_endproc
  282. .size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2
  283. #endif
  284. .section .gcc_except_table,"a",@progbits
  285. .LexceptSTART:
  286. .byte DW_EH_PE_omit # @LPStart format
  287. .byte DW_EH_PE_omit # @TType format
  288. .byte DW_EH_PE_uleb128 # call-site format
  289. .uleb128 .Lcstend-.Lcstbegin
  290. .Lcstbegin:
  291. .uleb128 .LcleanupSTART-.LSTARTCODE
  292. .uleb128 .LcleanupEND-.LcleanupSTART
  293. .uleb128 sem_timedwait_cleanup-.LSTARTCODE
  294. .uleb128 0
  295. #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  296. .uleb128 .LcleanupSTART2-.LSTARTCODE
  297. .uleb128 .LcleanupEND2-.LcleanupSTART2
  298. .uleb128 sem_timedwait_cleanup2-.LSTARTCODE
  299. .uleb128 0
  300. #endif
  301. .uleb128 .LcallUR-.LSTARTCODE
  302. .uleb128 .LENDCODE-.LcallUR
  303. .uleb128 0
  304. .uleb128 0
  305. #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
  306. .uleb128 .LcallUR2-.LSTARTCODE
  307. .uleb128 .LENDCODE2-.LcallUR2
  308. .uleb128 0
  309. .uleb128 0
  310. #endif
  311. .Lcstend:
  312. #ifdef SHARED
  313. .hidden DW.ref.__gcc_personality_v0
  314. .weak DW.ref.__gcc_personality_v0
  315. .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
  316. .align 8
  317. .type DW.ref.__gcc_personality_v0, @object
  318. .size DW.ref.__gcc_personality_v0, 8
  319. DW.ref.__gcc_personality_v0:
  320. .quad __gcc_personality_v0
  321. #endif