Hi,

Bug #28468 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28468)
causes a crash of nearly every valid program that parallelizes a loop
through OMP when OMP_NUM_THREADS > 1.

The affected systems are probably all Linux/x86 systems on which a glibc
with LinuxThreads and without TLS is installed, and on which binutils
with __thread support were installed afterwards.

The typical gdb stack trace is like this:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16386 (LWP 4985)]
gomp_iter_dynamic_next (pstart=0xbf7ffa94, pend=0xbf7ffa98) at 
../../../gcc-4.2-20061031/libgomp/iter.c:189
189       start = ws->next;
(gdb) where
#0  gomp_iter_dynamic_next (pstart=0xbf7ffa94, pend=0xbf7ffa98) at 
../../../gcc-4.2-20061031/libgomp/iter.c:189
#1  0x4001ca78 in gomp_loop_dynamic_next (istart=0xbf7ffa94, iend=0xbf7ffa98) 
at ../../../gcc-4.2-20061031/libgomp/loop.c:248
#2  0x080486ed in main.omp_fn.0 ()
#3  0x4001de5d in gomp_thread_start (xdata=0xbfffe580) at 
../../../gcc-4.2-20061031/libgomp/team.c:108
#4  0x4003bfe6 in pthread_start_thread (arg=0xbf7ffbe0) at manager.c:310
#5  0x4003c07f in pthread_start_thread_event (arg=0xbf7ffbe0) at manager.c:334
#6  0x4014e0aa in clone () from /lib/libc.so.6

What happens is that gomp_thread () returns a pointer to a memory area that
consistents entirely of zeroes.

The gomp_thread() definition in libgomp.h:227 is used, making an access to
%gs:0. This is wrong, because the libc in use does not support this %gs stuff.

So, the reason is that HAVE_TLS was defined although only binutils and gcc,
but not glibc, support TLS.

After I changed the GCC_CHECK_TLS macro to also test for libc support of
__thread, rebuilt libcomp/configure, ran "config.status --recheck" and
rebuilt and reinstalled libgomp, the crash went away.

Here is the fix. It tests whether __thread actually works, not only whether
it is syntactically valid for the compiler. I have already submitted
copyright assignment papers for GCC.


2006-11-07  Bruno Haible  <[EMAIL PROTECTED]>

        * config/tls.m4 (GCC_CHECK_TLS): Also check whether the libc supports
        TLS via __thread.

*** config/tls.m4       2006-09-19 03:48:06.000000000 +0200
--- config/tls.m4.new   2006-11-08 01:47:33.000000000 +0100
***************
*** 11,17 ****
        LDFLAGS="-static $LDFLAGS"
        AC_RUN_IFELSE([__thread int a; int b; int main() { return a = b; }],
                    [have_tls=yes], [have_tls=no], [])
!       LDFLAGS="$save_LDFLAGS"],
        [have_tls=no],
        [AC_COMPILE_IFELSE([__thread int foo;], [have_tls=yes], [have_tls=no])]
      )])
--- 11,53 ----
        LDFLAGS="-static $LDFLAGS"
        AC_RUN_IFELSE([__thread int a; int b; int main() { return a = b; }],
                    [have_tls=yes], [have_tls=no], [])
!       LDFLAGS="$save_LDFLAGS"
!       if test $have_tls = yes; then
!         dnl So far, the binutils and the compiler support TLS.
!         dnl Also check whether the libc supports TLS, i.e. whether a variable
!         dnl with __thread linkage has a different address in different 
threads.
!         save_LDFLAGS="$LDFLAGS"
!         LDFLAGS="-lpthread $LDFLAGS"
!         AC_RUN_IFELSE([
!           #include <pthread.h>
! 
!           __thread int a;
!           int *mainthread_a;
!           int *subthread_a;
! 
!           void *subthread_func(void *arg)
!           {
!             subthread_a = &a;
!             return 0;
!           }
! 
!           int main()
!           {
!             pthread_t subthread;
!             void *subthread_retval;
! 
!             mainthread_a = &a;
! 
!             if (pthread_create (&subthread, NULL, subthread_func, 0) != 0)
!               return 2;
!             if (pthread_join (subthread, &subthread_retval) != 0)
!               return 3;
! 
!             return (mainthread_a == subthread_a);
!           }],
!           [have_tls=yes], [have_tls=no], [])
!         LDFLAGS="$save_LDFLAGS"
!       fi],
        [have_tls=no],
        [AC_COMPILE_IFELSE([__thread int foo;], [have_tls=yes], [have_tls=no])]
      )])

Reply via email to