When glibc is configured with --enable-kernel=2.6.38 on x86-64, R15 may be uninitialized in x86_64/pthread_cond_timedwait.S when called from nptl/tst-abstime.c. The backtrace is Breakpoint 5, pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:50 50 pushq %r12 (gdb) bt #0 pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:50 #1 0x0040081d in main () at fixed.c:85 (gdb) and sequence is (gdb) next 53 pushq %r13 (gdb) 56 pushq %r14 (gdb) 59 pushq %r15 (gdb) [Thread 0xf7a42940 (LWP 2393) exited] 67 subq $FRAME_SIZE, %rsp (gdb) 71 cmpq $1000000000, 8(%rdx) (gdb) 72 movl $EINVAL, %eax (gdb) 73 jae 48f (gdb) 93 CMP_LP $-1, dep_mutex(%rdi) (gdb) 96 movq %rdi, 8(%rsp) (gdb) 97 movq %rsi, 16(%rsp) (gdb) 98 movq %rdx, %r13 (gdb) 100 je 22f (gdb) 101 mov %RSI_LP, dep_mutex(%rdi) (gdb) 114 movl $1, %esi (gdb) 115 xorl %eax, %eax (gdb) 116 LOCK (gdb) 122 jnz 31f (gdb) 125 32: movq 16(%rsp), %rdi (gdb) 126 xorl %esi, %esi (gdb) 127 callq __pthread_mutex_unlock_usercnt (gdb) 129 testl %eax, %eax (gdb) 130 jne 46f (gdb) 132 movq 8(%rsp), %rdi (gdb) 133 incq total_seq(%rdi) (gdb) 134 incl cond_futex(%rdi) (gdb) 135 addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) (gdb) 138 movq 8(%rsp), %rdi (gdb) 139 movq wakeup_seq(%rdi), %r9 (gdb) 140 movl broadcast_seq(%rdi), %edx (gdb) 141 movq %r9, 24(%rsp) (gdb) 142 movl %edx, 4(%rsp) (gdb) 144 cmpq $0, (%r13) (gdb) 145 movq $-ETIMEDOUT, %r14 (gdb) 146 js 36f (gdb) 231 36: movl broadcast_seq(%rdi), %edx (gdb) 233 movq woken_seq(%rdi), %rax (gdb) 235 movq wakeup_seq(%rdi), %r9 (gdb) 237 cmpl 4(%rsp), %edx (gdb) 238 jne 53f (gdb) 240 cmpq 24(%rsp), %r9 (gdb) 241 jbe 45f (gdb) 246 45: cmpq $-ETIMEDOUT, %r14 (gdb) 247 jne 38b (gdb) 249 99: incq wakeup_seq(%rdi) (gdb) 250 incl cond_futex(%rdi) (gdb) 251 movl $ETIMEDOUT, %r14d (gdb) 252 jmp 44f (gdb) 258 44: incq woken_seq(%rdi) (gdb) 260 54: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) (gdb) 263 cmpq $0xffffffffffffffff, total_seq(%rdi) (gdb) 264 jne 55f (gdb) 286 55: LOCK (gdb) 292 jne 40f (gdb) 296 41: movq 16(%rsp), %rdi (gdb) Breakpoint 6, pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:297 297 testl %r15d, %r15d (gdb)
This patch diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S index 1caba54..c3cfeec 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -112,6 +112,7 @@ __pthread_cond_timedwait: /* Get internal lock. */ movl $1, %esi + xorl %r15d, %r15d xorl %eax, %eax LOCK #if cond_lock == 0 works for me.
Whose bright idea was it to write a separate version of these functions for each target architecture in asm, rather than just using common C code with underlying asm (or gcc intrinsics) for the atomic memory operations? I'm thinking of opening a bug "Gratuitous asm leads to arch-specific bugs in pthread synchronization primitives" so this and similar bugs can all be marked as a duplicate of it...
I checked in a better patch.