aboutsummaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S75
1 files changed, 60 insertions, 15 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
index 29bc1bcf46..7626d7b250 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
@@ -38,7 +38,14 @@
.globl sem_timedwait
.type sem_timedwait,@function
.align 16
+ cfi_startproc
sem_timedwait:
+ /* First check for cancellation. */
+ movl %fs:CANCELHANDLING, %eax
+ andl $0xfffffff9, %eax
+ cmpl $8, %eax
+ je 11f
+
movl (%rdi), %eax
2: testl %eax, %eax
je 1f
@@ -53,18 +60,29 @@ sem_timedwait:
/* Check whether the timeout value is valid. */
1: pushq %r12
+ cfi_adjust_cfa_offset(8)
pushq %r13
- subq $16, %rsp
+ cfi_adjust_cfa_offset(8)
+ pushq %r14
+ cfi_adjust_cfa_offset(8)
+ subq $24, %rsp
+ cfi_adjust_cfa_offset(24)
movq %rdi, %r12
+ cfi_offset(12, -16) /* %r12 */
movq %rsi, %r13
+ cfi_offset(13, -24) /* %r13 */
/* Check for invalid nanosecond field. */
cmpq $1000000000, 8(%r13)
- movl $EINVAL, %eax
+ movl $EINVAL, %r14d
+ cfi_offset(14, -24) /* %r14 */
jae 6f
-7: xorq %rsi, %rsi
+7: call __pthread_enable_asynccancel
+ movl %eax, 16(%rsp)
+
+ xorq %rsi, %rsi
movq %rsp, %rdi
movq $VSYSCALL_ADDR_vgettimeofday, %rax
callq *%rax
@@ -74,14 +92,14 @@ sem_timedwait:
movq $1000, %rdi
mul %rdi /* Milli seconds to nano seconds. */
movq (%r13), %rdi
- movq 8(%r13), %rdi
+ movq 8(%r13), %rsi
subq (%rsp), %rdi
- subq %rax, %rdi
+ subq %rax, %rsi
jns 5f
addq $1000000000, %rsi
decq %rdi
5: testq %rdi, %rdi
- movl $ETIMEDOUT, %eax
+ movl $ETIMEDOUT, %r14d
js 6f /* Time is already up. */
movq %rdi, (%rsp) /* Store relative timeout. */
@@ -93,38 +111,65 @@ sem_timedwait:
movq $SYS_futex, %rax
xorl %edx, %edx
syscall
+ movq %rax, %r14
- testq %rax, %rax
+ movl 16(%rsp), %edi
+ call __pthread_disable_asynccancel
+
+ testq %r14, %r14
je 9f
- cmpq $-EWOULDBLOCK, %rax
+ cmpq $-EWOULDBLOCK, %r14
jne 3f
-9: movl (%rdi), %eax
+9: movl (%r12), %eax
8: testl %eax, %eax
je 7b
leaq -1(%rax), %rcx
LOCK
- cmpxchgl %ecx, (%rdi)
+ cmpxchgl %ecx, (%r12)
jne 8b
xorl %eax, %eax
-10: addq $16, %rsp
+10: addq $24, %rsp
+ cfi_adjust_cfa_offset(-24)
+ popq %r14
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(14)
popq %r13
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(13)
popq %r12
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(12)
retq
-3: negq %rax
+ cfi_adjust_cfa_offset(48)
+ cfi_offset(12, -16) /* %r12 */
+ cfi_offset(13, -24) /* %r13 */
+ cfi_offset(14, -32) /* %r14 */
+3: negq %r14
6:
#if USE___THREAD
movq errno@gottpoff(%rip), %rdx
- movl %eax, %fs:(%rdx)
+ movl %r14d, %fs:(%rdx)
#else
- movl %eax, %edx
callq __errno_location@plt
- movl %edx, (%rax)
+ movl %r14d, (%rax)
#endif
orl $-1, %eax
jmp 10b
+ cfi_adjust_cfa_offset(-48)
+ cfi_restore(14)
+ cfi_restore(13)
+ cfi_restore(12)
+
+11: /* Canceled. */
+ movq $0xffffffffffffffff, %fs:RESULT
+ LOCK
+ orl $0x10, %fs:CANCELHANDLING
+ movq %fs:CLEANUP_JMP_BUF, %rdi
+ jmp __pthread_unwind
+ cfi_endproc
.size sem_timedwait,.-sem_timedwait