sem_timedwait.S 7.2 KB

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