This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[BZ 5240][PATCH] Pthread hang where there are still waiters when mutex is in "unlocked" state.
- From: "Ryan S. Arnold" <rsa at us dot ibm dot com>
- To: libc-alpha at sources dot redhat dot com, Tom Kalla <KALLATOM at de dot ibm dot com>, Andreas Arnez <arnez at vnet dot ibm dot com>
- Date: Thu, 01 Nov 2007 13:45:49 -0500
- Subject: [BZ 5240][PATCH] Pthread hang where there are still waiters when mutex is in "unlocked" state.
- Reply-to: rsa at us dot ibm dot com
Per the problem description in bugzilla 5240:
"A customer identified a potential race condition in
nptl/sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait)
which causes waiting threads not to be woken up under certain circumstances."
http://sources.redhat.com/bugzilla/show_bug.cgi?id=5240
We (IBM) have come up with a patch that solves the problem but I'm not
sure this is the proper solution.
I'd appreciate it if someone on an architecture other than PowerPC or
i386 would run the test case and report their results.
I looked at the x86 assembler version of lowlevellock.S and from what I
can see it doesn't do anything different than the default lowlevellock.c
code but the bug isn't manifest on i386 hardware per my tests.
If someone with proper i386 asm skills could verify I'd appreciate it.
Ryan S. Arnold
IBM Linux Technology Center
Linux Toolchain Development
2007-11-01 Ryan S. Arnold <rsa@us.ibm.com>
* nptl/sysdeps/unix/sysv/linux/lowlevellock.c
(__lll_timedlock_wait) Wake before returning timeout.
--- glibc-2.7/nptl/sysdeps/unix/sysv/linux/lowlevellock.c 2007-08-14 14:59:34.000000000 -0500
+++ glibc-2.7.new/nptl/sysdeps/unix/sysv/linux/lowlevellock.c 2007-11-01 12:25:49.000000000 -0500
@@ -76,12 +76,16 @@
--rt.tv_sec;
}
+ int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
/* Already timed out? */
if (rt.tv_sec < 0)
- return ETIMEDOUT;
+ {
+ if (oldval == 0)
+ lll_futex_wake (futex, 1, private);
+ return ETIMEDOUT;
+ }
/* Wait. */
- int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_timed_wait (futex, 2, &rt, private);
}