diff options
author | Andreas Schwab <schwab@redhat.com> | 2011-11-28 13:38:19 +0100 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2011-11-30 11:03:19 +0100 |
commit | c5a0802a682dba23f92d47f0f99775aebfbe2539 (patch) | |
tree | f662acd317fdc5195592161d27ed1fd1ad74d0bc /nptl/sysdeps/unix/sysv/linux/x86_64 | |
parent | 9d65ea3a9b83ac3961229ba296a7caf90abce68d (diff) | |
download | glibc-c5a0802a682dba23f92d47f0f99775aebfbe2539.tar glibc-c5a0802a682dba23f92d47f0f99775aebfbe2539.tar.gz glibc-c5a0802a682dba23f92d47f0f99775aebfbe2539.tar.bz2 glibc-c5a0802a682dba23f92d47f0f99775aebfbe2539.zip |
Handle EAGAIN from FUTEX_WAIT_REQUEUE_PI
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/x86_64')
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S index 7535baa786..d837d158a4 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -23,6 +23,7 @@ #include <lowlevelcond.h> #include <tcb-offsets.h> #include <pthread-pi-defines.h> +#include <pthread-errnos.h> #include <kernel-features.h> @@ -133,11 +134,14 @@ __pthread_cond_wait: cmpl $PI_BIT, %eax jne 61f +90: movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi movl $SYS_futex, %eax syscall movl $1, %r8d + cmpq $-EAGAIN, %rax + je 91f #ifdef __ASSUME_REQUEUE_PI jmp 62f #else @@ -324,6 +328,70 @@ __pthread_cond_wait: 13: movq %r10, %rax jmp 14b + +91: +.LcleanupSTART2: + /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to + call it again. */ + movq 8(%rsp), %rdi + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jz 92f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif +92: + /* Increment the cond_futex value again, so it can be used as a new + expected value. */ + incl cond_futex(%rdi) + movl cond_futex(%rdi), %edx + + /* Release internal lock. */ + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jz 93f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + /* The call preserves %rdx. */ + callq __lll_unlock_wake +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif +93: + /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */ + xorq %r10, %r10 + movq dep_mutex(%rdi), %r8 + leaq cond_futex(%rdi), %rdi + jmp 90b +.LcleanupEND2: + .size __pthread_cond_wait, .-__pthread_cond_wait versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, GLIBC_2_3_2) @@ -476,11 +544,15 @@ __condvar_cleanup1: .uleb128 .LcleanupSTART-.LSTARTCODE .uleb128 .LcleanupEND-.LcleanupSTART .uleb128 __condvar_cleanup1-.LSTARTCODE - .uleb128 0 + .uleb128 0 + .uleb128 .LcleanupSTART2-.LSTARTCODE + .uleb128 .LcleanupEND2-.LcleanupSTART2 + .uleb128 __condvar_cleanup1-.LSTARTCODE + .uleb128 0 .uleb128 .LcallUR-.LSTARTCODE .uleb128 .LENDCODE-.LcallUR .uleb128 0 - .uleb128 0 + .uleb128 0 .Lcstend: |