summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/i386
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2011-11-28 13:38:19 +0100
committerAndreas Schwab <schwab@redhat.com>2011-11-30 11:03:19 +0100
commitc5a0802a682dba23f92d47f0f99775aebfbe2539 (patch)
treef662acd317fdc5195592161d27ed1fd1ad74d0bc /nptl/sysdeps/unix/sysv/linux/i386
parent9d65ea3a9b83ac3961229ba296a7caf90abce68d (diff)
Handle EAGAIN from FUTEX_WAIT_REQUEUE_PI
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S80
1 files changed, 80 insertions, 0 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
index 53970d755f..54590b7b8b 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
@@ -134,6 +134,7 @@ __pthread_cond_wait:
cmpl $PI_BIT, %eax
jne 18f
+90:
movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
movl %ebp, %edx
xorl %esi, %esi
@@ -147,6 +148,9 @@ __pthread_cond_wait:
sete 16(%esp)
je 19f
+ cmpl $-EAGAIN, %eax
+ je 91f
+
/* Normal and PI futexes dont mix. Use normal futex functions only
if the kernel does not support the PI futex functions. */
cmpl $-ENOSYS, %eax
@@ -391,6 +395,78 @@ __pthread_cond_wait:
#endif
call __lll_unlock_wake
jmp 11b
+
+91:
+.LcleanupSTART2:
+ /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to
+ call it again. */
+
+ /* Get internal lock. */
+ movl $1, %edx
+ xorl %eax, %eax
+ LOCK
+#if cond_lock == 0
+ cmpxchgl %edx, (%ebx)
+#else
+ cmpxchgl %edx, cond_lock(%ebx)
+#endif
+ jz 92f
+
+#if cond_lock == 0
+ movl %ebx, %edx
+#else
+ leal cond_lock(%ebx), %edx
+#endif
+#if (LLL_SHARED-LLL_PRIVATE) > 255
+ xorl %ecx, %ecx
+#endif
+ cmpl $-1, dep_mutex(%ebx)
+ setne %cl
+ subl $1, %ecx
+ andl $(LLL_SHARED-LLL_PRIVATE), %ecx
+#if LLL_PRIVATE != 0
+ addl $LLL_PRIVATE, %ecx
+#endif
+ call __lll_lock_wait
+
+92:
+ /* Increment the cond_futex value again, so it can be used as a new
+ expected value. */
+ addl $1, cond_futex(%ebx)
+ movl cond_futex(%ebx), %ebp
+
+ /* Unlock. */
+ LOCK
+#if cond_lock == 0
+ subl $1, (%ebx)
+#else
+ subl $1, cond_lock(%ebx)
+#endif
+ je 93f
+#if cond_lock == 0
+ movl %ebx, %eax
+#else
+ leal cond_lock(%ebx), %eax
+#endif
+#if (LLL_SHARED-LLL_PRIVATE) > 255
+ xorl %ecx, %ecx
+#endif
+ cmpl $-1, dep_mutex(%ebx)
+ setne %cl
+ subl $1, %ecx
+ andl $(LLL_SHARED-LLL_PRIVATE), %ecx
+#if LLL_PRIVATE != 0
+ addl $LLL_PRIVATE, %ecx
+#endif
+ call __lll_unlock_wake
+
+93:
+ /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
+ xorl %ecx, %ecx
+ movl dep_mutex(%ebx), %edi
+ jmp 90b
+.LcleanupEND2:
+
.size __pthread_cond_wait, .-__pthread_cond_wait
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
GLIBC_2_3_2)
@@ -563,6 +639,10 @@ __condvar_w_cleanup:
.long .LcleanupEND-.Lsub_cond_futex
.long __condvar_w_cleanup-.LSTARTCODE
.uleb128 0
+ .long .LcleanupSTART2-.LSTARTCODE
+ .long .LcleanupEND2-.LcleanupSTART2
+ .long __condvar_w_cleanup-.LSTARTCODE
+ .uleb128 0
.long .LcallUR-.LSTARTCODE
.long .LENDCODE-.LcallUR
.long 0