sem_timedwait.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* Copyright (C) 2002, 2003, 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 <shlib-compat.h>
  18. #include <pthread-errnos.h>
  19. #ifndef UP
  20. # define LOCK lock
  21. #else
  22. # define
  23. #endif
  24. #define SYS_futex 202
  25. /* For the calculation see asm/vsyscall.h. */
  26. #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
  27. .text
  28. .globl sem_timedwait
  29. .type sem_timedwait,@function
  30. .align 16
  31. cfi_startproc
  32. sem_timedwait:
  33. /* First check for cancellation. */
  34. movl %fs:CANCELHANDLING, %eax
  35. andl $0xfffffff9, %eax
  36. cmpl $8, %eax
  37. je 11f
  38. movl (%rdi), %eax
  39. 2: testl %eax, %eax
  40. je 1f
  41. leaq -1(%rax), %rdx
  42. LOCK
  43. cmpxchgl %edx, (%rdi)
  44. jne 2b
  45. xorl %eax, %eax
  46. retq
  47. /* Check whether the timeout value is valid. */
  48. 1: pushq %r12
  49. cfi_adjust_cfa_offset(8)
  50. pushq %r13
  51. cfi_adjust_cfa_offset(8)
  52. pushq %r14
  53. cfi_adjust_cfa_offset(8)
  54. subq $24, %rsp
  55. cfi_adjust_cfa_offset(24)
  56. movq %rdi, %r12
  57. cfi_offset(12, -16) /* %r12 */
  58. movq %rsi, %r13
  59. cfi_offset(13, -24) /* %r13 */
  60. /* Check for invalid nanosecond field. */
  61. cmpq $1000000000, 8(%r13)
  62. movl $EINVAL, %r14d
  63. cfi_offset(14, -24) /* %r14 */
  64. jae 6f
  65. 7: call __pthread_enable_asynccancel
  66. movl %eax, 16(%rsp)
  67. xorl %esi, %esi
  68. movq %rsp, %rdi
  69. movq $VSYSCALL_ADDR_vgettimeofday, %rax
  70. callq *%rax
  71. /* Compute relative timeout. */
  72. movq 8(%rsp), %rax
  73. movl $1000, %edi
  74. mul %rdi /* Milli seconds to nano seconds. */
  75. movq (%r13), %rdi
  76. movq 8(%r13), %rsi
  77. subq (%rsp), %rdi
  78. subq %rax, %rsi
  79. jns 5f
  80. addq $1000000000, %rsi
  81. decq %rdi
  82. 5: testq %rdi, %rdi
  83. movl $ETIMEDOUT, %r14d
  84. js 6f /* Time is already up. */
  85. movq %rdi, (%rsp) /* Store relative timeout. */
  86. movq %rsi, 8(%rsp)
  87. movq %rsp, %r10
  88. movq %r12, %rdi
  89. xorl %esi, %esi
  90. movl $SYS_futex, %eax
  91. xorl %edx, %edx
  92. syscall
  93. movq %rax, %r14
  94. movl 16(%rsp), %edi
  95. call __pthread_disable_asynccancel
  96. testq %r14, %r14
  97. je 9f
  98. cmpq $-EWOULDBLOCK, %r14
  99. jne 3f
  100. 9: movl (%r12), %eax
  101. 8: testl %eax, %eax
  102. je 7b
  103. leaq -1(%rax), %rcx
  104. LOCK
  105. cmpxchgl %ecx, (%r12)
  106. jne 8b
  107. xorl %eax, %eax
  108. 10: addq $24, %rsp
  109. cfi_adjust_cfa_offset(-24)
  110. popq %r14
  111. cfi_adjust_cfa_offset(-8)
  112. cfi_restore(14)
  113. popq %r13
  114. cfi_adjust_cfa_offset(-8)
  115. cfi_restore(13)
  116. popq %r12
  117. cfi_adjust_cfa_offset(-8)
  118. cfi_restore(12)
  119. retq
  120. cfi_adjust_cfa_offset(48)
  121. cfi_offset(12, -16) /* %r12 */
  122. cfi_offset(13, -24) /* %r13 */
  123. cfi_offset(14, -32) /* %r14 */
  124. 3: negq %r14
  125. 6:
  126. #if USE___THREAD
  127. movq errno@gottpoff(%rip), %rdx
  128. movl %r14d, %fs:(%rdx)
  129. #else
  130. callq __errno_location@plt
  131. movl %r14d, (%rax)
  132. #endif
  133. orl $-1, %eax
  134. jmp 10b
  135. cfi_adjust_cfa_offset(-48)
  136. cfi_restore(14)
  137. cfi_restore(13)
  138. cfi_restore(12)
  139. 11: /* Canceled. */
  140. movq $0xffffffffffffffff, %fs:RESULT
  141. LOCK
  142. orl $0x10, %fs:CANCELHANDLING
  143. movq %fs:CLEANUP_JMP_BUF, %rdi
  144. jmp HIDDEN_JUMPTARGET (__pthread_unwind)
  145. cfi_endproc
  146. .size sem_timedwait,.-sem_timedwait