Hi. Because of the absence of the sparc32-linux specific version of this file, `nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c' is fetched when building `libc-lowlevellock.o{,s}'. The latter contains just . . . #include "lowlevellock.c" which leads to `nptl/sysdeps/unix/sysv/linux/lowlevellock.c' being actually compiled instead of `nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c'. As a consequence a futex can be accessed in a non-atomic way when using libc's internal locks, e.g. when performing output to the same stream from different threads. For example, when the following test is run on a V8 host, this typically leads to a deadlock when all threads are waiting for a futex to become free and there is no one to release it. This happens particularly soon when it's executed this way at a multi-CPU host: $ ./test.sparc32 5 > /dev/null $ cat test.c #include <pthread.h> #include <stdio.h> #include <stdlib.h> void * handler (void *arg) { for (;;) printf ("Thread #%ld\n", (long) arg); return NULL; } int main (int argc, char **argv) { size_t i; size_t nthreads = (size_t) atoi (argv[1]); pthread_t *threads = (pthread_t *) malloc (nthreads * sizeof (pthread_t)); for (i = 0; i < nthreads; i++) pthread_create (&threads[i], NULL, handler, (void *) i); for (i = 0; i < nthreads; i++) pthread_join (threads[i], NULL); free (threads); return 0; }
(1) I've added Dave Miller (Sparc maintainer) to the CC. (2) Please follow "What to put in a report": http://www.gnu.org/software/libc/bugs.html (3) No architecture needs to provide libc-lowlevellock.c. The normal sysdep override mechanism should have selected the sparc32 version of lowlevellock.c *unless* your configure options failed to cause the selection of sparc32. Given that you have not provided a full report we don't know why sparc32 was not selected. Please include the full log of running `./configure ...` since that will contain which sysdep directories were selected and in what override order. Thanks.
(In reply to comment #1) . . . > (3) . . . The normal sysdep > override mechanism should have selected the sparc32 version of lowlevellock.c > *unless* your configure options failed to cause the selection of sparc32. . . . . . And it actually did when compiling lowlevellock.o{,s}, however `#include "lowlevellock.c"' in the generic version of libc-lowlevellock.c causes the generic version of lowlevellock.c to be included (because they are in the same directory) rather than the sparc32 one. If you still need a full configure log, I'll provide it a bit later.
(In reply to comment #2) > (In reply to comment #1) > . . . > > (3) . . . The normal sysdep > > override mechanism should have selected the sparc32 version of lowlevellock.c > > *unless* your configure options failed to cause the selection of sparc32. . . > . . . > And it actually did when compiling lowlevellock.o{,s}, however `#include > "lowlevellock.c"' in the generic version of libc-lowlevellock.c causes the > generic version of lowlevellock.c to be included (because they are in the same > directory) rather than the sparc32 one. > > If you still need a full configure log, I'll provide it a bit later. No, that makes more sense to me. I see HPPA has it's own version of libc-lowlevellock.c probably because of this issue. I also think ARM might suffer the same problem, it has a lowlevellock.c but no overriding libc-lowlevellock.c like HPPA. OK, confirmed, on ARM we are also using the *default* lowlevellock.c e.g. ~~~ nptl/libc-lowlevellock.os: file format elf32-littlearm Disassembly of section .text: 00000000 <__lll_lock_wait_private>: __lll_lock_wait_private(): /opt/codesourcery/arm-verifone-linux-gnueabi/src/glibc/nptl/../nptl/sysdeps/unix/sysv/linux/lowlevellock.c:29 0: e92d40f0 push {r4, r5, r6, r7, lr} ~~~ OK, some big-picture questions. Dave, Why does sparc have a custom version of lowlevellock.c? Why do any architectures? The custom versions all seem vaguely similar to the generic linux version. If architectures *do* need to override the generic lowlevellock.c without overriding libc-lowlevellock.c then I think the right solution would be to make libc-lowlevellock.c use `#include <lowlevellock.c>` such that the sysdep include mechanism includes the right file. Il'ya, Would you mind testing that change?
Sparc needs a custom lowlevellock.c on 32-bit sparc because we have a situation where we don't know if we have the proper atomic instructions available or not. For example, if we don't have the v9 compare-and-swap available we use spinlocks instead. And for futexes we use a special 24-bit atomic, which embeds the spinlock in the remaining 8-bits. That's what all of those atomic_compare_and_exchange_val_24_acq etc. routines are all about. I'll just add the necessary sparc32/libc-lowlevellock.c file to fix this, thanks for the report.
Joseph, It looks like ARM also needs a libc-lowlevellock.c? Could you please review?
I think we should use #include <> in the generic libc-lowlevellock.c rather than accumulating copies.
That's what I ended up doing in the end.