sem_timedwait.S 7.5 KB

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