This is the mail archive of the
libc-ports@sources.redhat.com
mailing list for the libc-ports project.
RE: Robust mutex problem on MIPS.
- From: "Kaz Kylheku" <kaz at zeugmasystems dot com>
- To: <libc-ports at sourceware dot org>
- Cc: <libc-alpha at sources dot redhat dot com>
- Date: Fri, 25 May 2007 11:52:42 -0700
- Subject: RE: Robust mutex problem on MIPS.
Earlier today, I wrote:
> In the deadlock situation, the futex has somehow taken on the value
> 0x80000000 (the FUTEX_WAITERS value).
In fact, this appears to be an arch-indpendent bug in the low-level
robust lock routine.
(Haven't looked at the latest CVS, just 2.5: maybe I'm fixing something
that's already fixed!)
I'm trying a fix right now in
nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
Basically, it's possible for the futex to be zero when the routine is
entered, since on another processor, the lock could just have been
released.
The caller will then flip the lock to ``oldval | FUTEX_WAITERS'', which
is just FUTEX_WAITERS.
But at the bottom of the loop, the compare swap operation tries to
acquire the lock from a 0 value. Both threads execute that loop and are
hosed.
Index: glibc/glibc-2.5/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
===================================================================
---
glibc.orig/glibc-2.5/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
2006-03-01 16:25:10.000000000 -0800
+++ glibc/glibc-1.5/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
2007-05-26 15:45:45.504886376 -0700
@@ -36,11 +36,15 @@
return oldval;
int newval = oldval | FUTEX_WAITERS;
- if (oldval != newval
- && atomic_compare_and_exchange_bool_acq (futex, newval,
oldval))
- continue;
- lll_futex_wait (futex, newval);
+ /* Do not switch an unowned lock to FUTEX_WAITERS! */
+ if (newval != FUTEX_WAITERS) {
+ if (oldval != newval
+ && atomic_compare_and_exchange_bool_acq (futex, newval,
oldval))
+ continue;
+
+ lll_futex_wait (futex, newval);
+ }
}
while ((oldval = atomic_compare_and_exchange_val_acq (futex,
tid |
FUTEX_WAITERS,