3.4 PATCH: Support boehm-gc with pthreads on Tru64 UNIX
Boehm, Hans
hans_boehm@hp.com
Wed Jul 23 22:25:00 GMT 2003
I tested a bit more on X86 and IA64. It still looks fine to me.
It's OK with me if you go ahead and check it in (after adding the defined(GC_OSF1_THREADS) check in a couple of places, as we discussed).
I am a bit concerned that we're effectively doing a piecemeal merge of GC 6.2/6.3, when we should be doing the merge once and for all.
Tom - Is this patch OK with you as well? Another possibility might be a full 6.2/6.3 merge, minus the configury changes. I think I could do that semi-manually without too much effort. (I'm less certain I can do it in a way that's consistent with GNU ChangeLog standards, etc.) And it might fix Oyvind's problem, though at most for 3.4.
I think the build changes are relatively independent, and less critical. I needed to update since I couldn't manage to get the old stuff debugged in the standalone distribution. Since the current arrangement is working inside gcc, and there are more experienced auto{make,conf} maintainers around ...
Hans
> -----Original Message-----
> From: Rainer Orth [mailto:ro@TechFak.Uni-Bielefeld.DE]
> Sent: Friday, July 11, 2003 12:30 PM
> To: java-patches@gcc.gnu.org
> Cc: gcc-patches@gcc.gnu.org; Richard Henderson
> Subject: 3.4 PATCH: Support boehm-gc with pthreads on Tru64 UNIX
>
>
> After I got gc6.2 working on Tru64 UNIX with --enable-threads=posix
>
> http://gcc.gnu.org/ml/java/2003-07/msg00162.html
>
> it was relatively easy to backport the necessary changes to
> GCC mainline.
>
> This patch contains
>
> * the changes for gc6.2 from the message above,
>
> * the necessary configure.in support, and
>
> * a couple of straightforward Tru64 UNIX related changes from gc6.2
> pthread_support.c, pthread_stop_world.c,
> include/private/gc_locks.h, and
> include/private/gcconfig.h.
>
> The biggest change is the support for GC_retry_signals: this
> is necessary
> since without it Tru64 UNIX V4.0F seems to loose some restart signals
> (cf. gc6.2 doc/README.environment (GC_RETRY_SIGNALS)) and gctest just
> hangs, though V5.1 works fine without.
>
> There's currently one change I haven't ported over:
>
> include/private/gcconfig.h has:
>
> # ifdef ALPHA
> [...]
> # ifndef LINUX
> # define USE_GENERIC_PUSH_REGS
> /* Gcc and probably the DEC/Compaq compiler spill
> pointers to preserved */
> /* fp registers in some cases when the target is a
> 21264. The assembly */
> /* code doesn't handle that yet, and version
> dependencies make that a */
> /* bit tricky. Do the easy thing for now.
> */
> # endif
>
> I'm not sure this is necessary given this change:
>
> 2001-06-26 Richard Henderson <rth@redhat.com>
>
> * alpha_mach_dep.s: Mark call-saved FP registers.
> * include/private/gcconfig.h (ALPHA): Remove
> USE_GENERIC_PUSH_REGS.
> * configure.in (alpha*): Re-enable alpha_mach_dep.s
> * configure: Rebuild.
>
> Maybe Richard can comment?
>
> Anyway, with this patch both make check in boehm-gc works with
> --enable-threads=posix, and a full bootstrap succeeded on
> alpha-dec-osf4.0f
> and alpha-dec-osf5.1 succeeded.
>
> With a companion patch to libjava (to be submitted shortly),
> libjava test
> results look reasonable with this change. For the moment,
> this shouldn't
> hurt since --enable-threads=posix isn't considered supported
> (or even the
> default) on that platform yet.
>
> Ok for mainline?
>
> Rainer
>
> --------------------------------------------------------------
> ---------------
> Rainer Orth, Faculty of Technology, Bielefeld University
>
>
> Fri Jul 11 20:50:10 2003 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
>
> Backport Tru64 UNIX POSIX threads support from gc6.2.
>
> * configure.in: Handle *-*-osf*.
> * configure: Regenerate.
>
> * include/gc_pthread_redirects.h [!GC_USE_LD_WRAP && GC_PTHREADS
> && !GC_SOLARIS_PTHREADS]: Undef mangled pthreads on
> Tru64 UNIX if
> appropriate.
>
> * include/private/gc_locks.h [THREADS && __GNUC__ && ALPHA]
> (GC_test_and_set): Only use ELF section switching if __ELF__.
> (GC_clear): Define.
>
> * include/private/gcconfig.h [ALPHA && OSF1]: Only define
> MPROTECT_VDB if not GC_OSF1_THREADS.
>
> * linux_threads.c (USE_PTHREAD_SPECIFIC) [GC_OSF1_THREADS &&
> !USE_PTHREAD_SPECIFIC]: Define.
> [!GC_USE_LD_WRAP && _PTHREAD_USE_MANGLED_NAMES_ &&
> !_PTHREAD_USE_PTDNAM_]: Restore original Tru64 UNIX
> definitions if
> appropriate.
> (struct GC_Thread_Rep): New member last_stop_count.
> (GC_stop_count, GC_retry_signals): Define.
> (SIG_THR_RESTART): Use SIGRTMIN if _SIGRTMIN is missing.
> (GC_suspend_handler): Check for duplicate suspend signal.
> Set last_stop_count after suspend.
> (GC_suspend_all): New function, extracted from GC_stop_world.
> (GC_stop_world): Use it.
> Handle GC_retry_signals.
> (GC_thr_init): Set GC_retry_signals from environment.
> [GC_OSF1_THREADS]: Try setting GC_nprocs via sysconf.
>
> Index: configure.in
> ===================================================================
> RCS file: /cvs/gcc/gcc/boehm-gc/configure.in,v
> retrieving revision 1.47
> diff -u -p -r1.47 configure.in
> --- configure.in 28 Apr 2003 20:54:37 -0000 1.47
> +++ configure.in 8 Jul 2003 01:17:29 -0000
> @@ -111,6 +111,17 @@ case "$THREADS" in
> *-*-cygwin*)
> THREADLIBS=
> ;;
> + *-*-osf*)
> + AC_DEFINE(GC_OSF1_THREADS)
> + if test "${enable_parallel_mark}" = yes; then
> + AC_DEFINE(PARALLEL_MARK)
> + AC_DEFINE(THREAD_LOCAL_ALLOC)
> + # May want to enable it in other cases, too.
> + # Measurements havent yet been done.
> + fi
> + INCLUDES="$INCLUDES -pthread"
> + THREADLIBS="-lpthread -lrt"
> + ;;
> esac
> ;;
> win32)
> Index: linux_threads.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/boehm-gc/linux_threads.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 linux_threads.c
> --- linux_threads.c 29 Mar 2002 22:52:12 -0000 1.20
> +++ linux_threads.c 8 Jul 2003 01:17:29 -0000
> @@ -28,11 +28,8 @@
> */
> /*
> * Linux_threads.c now also includes some code to support HPUX and
> - * OSF1 (Compaq Tru64 Unix, really). The OSF1 support is not yet
> - * functional. The OSF1 code is based on Eric Benson's
> - * patch, though that was originally against
> hpux_irix_threads. The code
> - * here is completely untested. With 0.0000001%
> probability, it might
> - * actually work.
> + * OSF1 (Compaq Tru64 Unix, really). The OSF1 support is
> based on Eric Benson's
> + * patch.
> *
> * Eric also suggested an alternate basis for a lock
> implementation in
> * his code:
> @@ -62,6 +59,10 @@
> # define USE_HPUX_TLS
> # endif
>
> +# if defined(GC_OSF1_THREADS) && !defined(USE_PTHREAD_SPECIFIC)
> +# define USE_PTHREAD_SPECIFIC
> +# endif
> +
> # ifdef THREAD_LOCAL_ALLOC
> # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_HPUX_TLS)
> # include "private/specific.h"
> @@ -107,6 +108,12 @@
> # undef pthread_sigmask
> # undef pthread_join
> # undef pthread_detach
> +# if defined(_PTHREAD_USE_MANGLED_NAMES_) &&
> !defined(_PTHREAD_USE_PTDNAM_)
> +/* Restore the original mangled names on Tru64 UNIX. */
> +# define pthread_create __pthread_create
> +# define pthread_join __pthread_join
> +# define pthread_detach __pthread_detach
> +# endif
> #endif
>
>
> @@ -143,6 +150,11 @@ typedef struct GC_Thread_Rep {
> /* guaranteed to be dead, but
> we may */
> /* not yet have registered
> the join.) */
> pthread_t id;
> + /* Extra bookkeeping information the stopping code uses */
> + word last_stop_count; /* GC_last_stop_count value
> when thread */
> + /* last successfully handled a
> suspend */
> + /* signal.
> */
> +
> short flags;
> # define FINISHED 1 /* Thread has exited. */
> # define DETACHED 2 /* Thread is intended to be
> detached. */
> @@ -435,6 +447,14 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
>
> # endif /* !THREAD_LOCAL_ALLOC */
>
> +word GC_stop_count; /* Incremented at the beginning of
> GC_stop_world. */
> +
> +#ifdef GC_OSF1_THREADS
> + GC_bool GC_retry_signals = TRUE;
> +#else
> + GC_bool GC_retry_signals = FALSE;
> +#endif
> +
> /*
> * We use signals to stop threads during GC.
> *
> @@ -449,7 +469,11 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
>
> #ifndef SIG_THR_RESTART
> # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
> -# define SIG_THR_RESTART _SIGRTMIN + 5
> +# ifdef _SIGRTMIN
> +# define SIG_THR_RESTART _SIGRTMIN + 5
> +# else
> +# define SIG_THR_RESTART SIGRTMIN + 5
> +# endif
> # else
> # define SIG_THR_RESTART SIGXCPU
> # endif
> @@ -586,6 +610,7 @@ void GC_suspend_handler(int sig)
> /* guaranteed to be the mark_no correspending to our
> */
> /* suspension, i.e. the marker can't have incremented
> it yet. */
> # endif
> + word my_stop_count = GC_stop_count;
>
> if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler");
>
> @@ -598,6 +623,14 @@ void GC_suspend_handler(int sig)
> /* of a thread which holds the allocation lock in order */
> /* to stop the world. Thus concurrent modification of
> the */
> /* data structure is impossible. */
> + if (me -> last_stop_count == my_stop_count) {
> + /* Duplicate signal. OK if we are retrying. */
> + if (!GC_retry_signals) {
> + WARN("Duplicate suspend signal in thread %lx\n",
> + pthread_self());
> + }
> + return;
> + }
> # ifdef SPARC
> me -> stack_ptr = (ptr_t)GC_save_regs_in_stack();
> # else
> @@ -611,6 +644,7 @@ void GC_suspend_handler(int sig)
> /* thread has been stopped. Note that sem_post() is */
> /* the only async-signal-safe primitive in LinuxThreads. */
> sem_post(&GC_suspend_ack_sem);
> + me -> last_stop_count = my_stop_count;
>
> /* Wait until that thread tells us to restart by sending */
> /* this thread a SIG_THR_RESTART signal. */
> @@ -799,36 +833,31 @@ GC_thread GC_lookup_thread(pthread_t id)
> pthread_t GC_stopping_thread;
> int GC_stopping_pid;
>
> -/* Caller holds allocation lock. */
> -void GC_stop_world()
> +/* We hold the allocation lock. Suspend all threads that
> might */
> +/* still be running. Return the number of suspend signals
> that */
> +/* were sent. */
> +int GC_suspend_all()
> {
> + int n_live_threads = 0;
> + int i;
> + GC_thread p;
> + int result;
> pthread_t my_thread = pthread_self();
> - register int i;
> - register GC_thread p;
> - register int n_live_threads = 0;
> - register int result;
> -
> +
> GC_stopping_thread = my_thread; /* debugging only. */
> GC_stopping_pid = getpid(); /* debugging
> only. */
> - /* Make sure all free list construction has stopped
> before we start. */
> - /* No new construction can start, since free list
> construction is */
> - /* required to acquire and release the GC lock before it
> starts, */
> - /* and we have the lock.
> */
> -# ifdef PARALLEL_MARK
> - GC_acquire_mark_lock();
> - GC_ASSERT(GC_fl_builder_count == 0);
> - /* We should have previously waited for it to become zero. */
> -# endif /* PARALLEL_MARK */
> for (i = 0; i < THREAD_TABLE_SZ; i++) {
> for (p = GC_threads[i]; p != 0; p = p -> next) {
> if (p -> id != my_thread) {
> if (p -> flags & FINISHED) continue;
> + if (p -> last_stop_count == GC_stop_count) continue;
> if (p -> thread_blocked) /* Will wait */ continue;
> n_live_threads++;
> #if DEBUG_THREADS
> - GC_printf1("Sending suspend signal to 0x%x\n", p -> id);
> + GC_printf1("Sending suspend signal to 0x%lx\n", p -> id);
> #endif
> - result = pthread_kill(p -> id, SIG_SUSPEND);
> +
> + result = pthread_kill(p -> id, SIG_SUSPEND);
> switch(result) {
> case ESRCH:
> /* Not really there anymore. Possible? */
> @@ -842,6 +871,59 @@ void GC_stop_world()
> }
> }
> }
> + return n_live_threads;
> +}
> +
> +/* Caller holds allocation lock. */
> +void GC_stop_world()
> +{
> + pthread_t my_thread = pthread_self();
> + register int i;
> + register GC_thread p;
> + register int n_live_threads = 0;
> + register int result;
> +
> + /* Make sure all free list construction has stopped
> before we start. */
> + /* No new construction can start, since free list
> construction is */
> + /* required to acquire and release the GC lock before it
> starts, */
> + /* and we have the lock.
> */
> +# ifdef PARALLEL_MARK
> + GC_acquire_mark_lock();
> + GC_ASSERT(GC_fl_builder_count == 0);
> + /* We should have previously waited for it to become zero. */
> +# endif /* PARALLEL_MARK */
> + ++GC_stop_count;
> + n_live_threads = GC_suspend_all();
> +
> + if (GC_retry_signals) {
> + unsigned long wait_usecs = 0; /* Total wait since
> retry. */
> +# define WAIT_UNIT 3000
> +# define RETRY_INTERVAL 100000
> + for (;;) {
> + int ack_count;
> +
> + sem_getvalue(&GC_suspend_ack_sem, &ack_count);
> + if (ack_count == n_live_threads) break;
> + if (wait_usecs > RETRY_INTERVAL) {
> + int newly_sent = GC_suspend_all();
> +
> +# ifdef CONDPRINT
> + if (GC_print_stats) {
> + GC_printf1("Resent %ld signals after timeout\n",
> + newly_sent);
> + }
> +# endif
> + sem_getvalue(&GC_suspend_ack_sem, &ack_count);
> + if (newly_sent < n_live_threads - ack_count) {
> + WARN("Lost some threads during
> GC_stop_world?!\n",0);
> + n_live_threads = ack_count + newly_sent;
> + }
> + wait_usecs = 0;
> + }
> + usleep(WAIT_UNIT);
> + wait_usecs += WAIT_UNIT;
> + }
> + }
> for (i = 0; i < n_live_threads; i++) {
> if (0 != sem_wait(&GC_suspend_ack_sem))
> ABORT("sem_wait in handler failed");
> @@ -1073,6 +1155,19 @@ void GC_thr_init()
> }
> # endif /* INSTALL_LOOPING_SEGV_HANDLER */
>
> + /* Check for GC_RETRY_SIGNALS. */
> + if (0 != GETENV("GC_RETRY_SIGNALS")) {
> + GC_retry_signals = TRUE;
> + }
> + if (0 != GETENV("GC_NO_RETRY_SIGNALS")) {
> + GC_retry_signals = FALSE;
> + }
> +# ifdef CONDPRINT
> + if (GC_print_stats && GC_retry_signals) {
> + GC_printf0("Will retry suspend signal if
> necessary.\n");
> + }
> +# endif
> +
> /* Add the initial thread, so we can stop it. */
> t = GC_new_thread(pthread_self());
> t -> stack_ptr = (ptr_t)(&dummy);
> @@ -1088,7 +1183,11 @@ void GC_thr_init()
> # if defined(GC_HPUX_THREADS)
> GC_nprocs = pthread_num_processors_np();
> # endif
> -# if defined(GC_OSF1_THREADS) || defined(GC_FREEBSD_THREADS)
> +# if defined(GC_OSF1_THREADS)
> + GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
> + if (GC_nprocs <= 0) GC_nprocs = 1;
> +# endif
> +# if defined(GC_FREEBSD_THREADS)
> GC_nprocs = 1;
> # endif
> # if defined(GC_LINUX_THREADS)
> Index: include/gc_pthread_redirects.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/boehm-gc/include/gc_pthread_redirects.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 gc_pthread_redirects.h
> --- include/gc_pthread_redirects.h 17 Oct 2001 04:55:28
> -0000 1.3
> +++ include/gc_pthread_redirects.h 8 Jul 2003 01:17:30 -0000
> @@ -56,6 +56,15 @@
> int GC_pthread_join(pthread_t thread, void **retval);
> int GC_pthread_detach(pthread_t thread);
>
> +#if defined(_PTHREAD_USE_MANGLED_NAMES_) &&
> !defined(_PTHREAD_USE_PTDNAM_)
> +/* Unless the compiler supports #pragma extern_prefix, the Tru64 UNIX
> + <pthread.h> redefines some POSIX thread functions to use
> mangled names.
> + If so, undef them before redefining. */
> +# undef pthread_create
> +# undef pthread_join
> +# undef pthread_detach
> +#endif
> +
> # define pthread_create GC_pthread_create
> # define pthread_sigmask GC_pthread_sigmask
> # define pthread_join GC_pthread_join
> Index: include/private/gc_locks.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/boehm-gc/include/private/gc_locks.h,v
> retrieving revision 1.8
> diff -u -p -r1.8 gc_locks.h
> --- include/private/gc_locks.h 23 Mar 2003 01:36:22
> -0000 1.8
> +++ include/private/gc_locks.h 8 Jul 2003 01:17:30 -0000
> @@ -174,12 +174,18 @@
> " bne %2,2f\n"
> " xor %0,%3,%0\n"
> " stl_c %0,%1\n"
> +# ifdef __ELF__
> " beq %0,3f\n"
> +# else
> + " beq %0,1b\n"
> +# endif
> " mb\n"
> "2:\n"
> +# ifdef __ELF__
> ".section .text2,\"ax\"\n"
> "3: br 1b\n"
> ".previous"
> +# endif
> :"=&r" (temp), "=m" (*addr),
> "=&r" (oldvalue)
> :"Ir" (1), "m" (*addr)
> :"memory");
> @@ -187,8 +193,11 @@
> return oldvalue;
> }
> # define GC_TEST_AND_SET_DEFINED
> - /* Should probably also define GC_clear, since it
> needs */
> - /* a memory barrier ??
> */
> + inline static void GC_clear(volatile unsigned int *addr) {
> + __asm__ __volatile__("mb" : : : "memory");
> + *(addr) = 0;
> + }
> +# define GC_CLEAR_DEFINED
> # endif /* ALPHA */
> # ifdef ARM32
> inline static int GC_test_and_set(volatile unsigned
> int *addr) {
> Index: include/private/gcconfig.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/boehm-gc/include/private/gcconfig.h,v
> retrieving revision 1.31
> diff -u -p -r1.31 gcconfig.h
> --- include/private/gcconfig.h 16 Apr 2003 18:28:29
> -0000 1.31
> +++ include/private/gcconfig.h 8 Jul 2003 01:17:30 -0000
> @@ -1381,7 +1381,10 @@
> extern int __start[];
> # define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) &
> ~(getpagesize()-1)))
> # define CPP_WORDSZ 64
> -# define MPROTECT_VDB
> +# ifndef GC_OSF1_THREADS
> + /* Unresolved signal issues with threads. */
> +# define MPROTECT_VDB
> +# endif
> # define DYNAMIC_LOADING
> # endif
> # ifdef LINUX
>
More information about the Java-patches
mailing list