From 20bbd3cd53a80ddafa56a5d21337aae0c24f94ca Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 1 Nov 1999 23:15:51 +0000 Subject: Merged GC 5.0alpha4 with local changes, plus: * Makefile.in: Rebuilt. * Makefile.am (gctest_LDADD): Added THREADLIB. (TESTS): New macro. * configure: Rebuilt. * configure.in (INCLUDES): New subst. From-SVN: r30332 --- boehm-gc/irix_threads.c | 66 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'boehm-gc/irix_threads.c') diff --git a/boehm-gc/irix_threads.c b/boehm-gc/irix_threads.c index f45c463..5efca21 100644 --- a/boehm-gc/irix_threads.c +++ b/boehm-gc/irix_threads.c @@ -25,6 +25,7 @@ # include "gc_priv.h" # include +# include # include # include # include @@ -411,6 +412,7 @@ void GC_thr_init() GC_thread t; struct sigaction act; + if (GC_thr_initialized) return; GC_thr_initialized = TRUE; GC_min_stack_sz = HBLKSIZE; GC_page_sz = sysconf(_SC_PAGESIZE); @@ -445,9 +447,14 @@ int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) struct start_info { void *(*start_routine)(void *); void *arg; + word flags; + ptr_t stack; + size_t stack_size; + sem_t registered; /* 1 ==> in our thread table, but */ + /* parent hasn't yet noticed. */ }; -void GC_thread_exit_proc(void *dummy) +void GC_thread_exit_proc(void *arg) { GC_thread me; @@ -472,6 +479,9 @@ int GC_pthread_join(pthread_t thread, void **retval) /* cant have been recycled by pthreads. */ UNLOCK(); result = pthread_join(thread, retval); + /* Some versions of the Irix pthreads library can erroneously */ + /* return EINTR when the call succeeds. */ + if (EINTR == result) result = 0; LOCK(); /* Here the pthread thread id may have been recycled. */ GC_delete_gc_thread(thread, thread_gc_id); @@ -484,12 +494,34 @@ void * GC_start_routine(void * arg) struct start_info * si = arg; void * result; GC_thread me; - + pthread_t my_pthread; + void *(*start)(void *); + void *start_arg; + + my_pthread = pthread_self(); + /* If a GC occurs before the thread is registered, that GC will */ + /* ignore this thread. That's fine, since it will block trying to */ + /* acquire the allocation lock, and won't yet hold interesting */ + /* pointers. */ LOCK(); - me = GC_lookup_thread(pthread_self()); + /* We register the thread here instead of in the parent, so that */ + /* we don't need to hold the allocation lock during pthread_create. */ + /* Holding the allocation lock there would make REDIRECT_MALLOC */ + /* impossible. It probably still doesn't work, but we're a little */ + /* closer ... */ + /* This unfortunately means that we have to be careful the parent */ + /* doesn't try to do a pthread_join before we're registered. */ + me = GC_new_thread(my_pthread); + me -> flags = si -> flags; + me -> stack = si -> stack; + me -> stack_size = si -> stack_size; + me -> stack_ptr = (ptr_t)si -> stack + si -> stack_size - sizeof(word); UNLOCK(); + start = si -> start_routine; + start_arg = si -> arg; + sem_post(&(si -> registered)); pthread_cleanup_push(GC_thread_exit_proc, 0); - result = (*(si -> start_routine))(si -> arg); + result = (*start)(start_arg); me -> status = result; me -> flags |= FINISHED; pthread_cleanup_pop(1); @@ -506,15 +538,17 @@ GC_pthread_create(pthread_t *new_thread, { int result; GC_thread t; - pthread_t my_new_thread; void * stack; size_t stacksize; pthread_attr_t new_attr; int detachstate; word my_flags = 0; struct start_info * si = GC_malloc(sizeof(struct start_info)); + /* This is otherwise saved only in an area mmapped by the thread */ + /* library, which isn't visible to the collector. */ if (0 == si) return(ENOMEM); + sem_init(&(si -> registered), 0, 0); si -> start_routine = start_routine; si -> arg = arg; LOCK(); @@ -540,20 +574,20 @@ GC_pthread_create(pthread_t *new_thread, my_flags |= CLIENT_OWNS_STACK; } if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED; - result = pthread_create(&my_new_thread, &new_attr, GC_start_routine, si); - /* No GC can start until the thread is registered, since we hold */ - /* the allocation lock. */ - if (0 == result) { - t = GC_new_thread(my_new_thread); - t -> flags = my_flags; - t -> stack = stack; - t -> stack_size = stacksize; - t -> stack_ptr = (ptr_t)stack + stacksize - sizeof(word); - if (0 != new_thread) *new_thread = my_new_thread; - } else if (!(my_flags & CLIENT_OWNS_STACK)) { + si -> flags = my_flags; + si -> stack = stack; + si -> stack_size = stacksize; + result = pthread_create(new_thread, &new_attr, GC_start_routine, si); + if (0 == new_thread && !(my_flags & CLIENT_OWNS_STACK)) { GC_stack_free(stack, stacksize); } UNLOCK(); + /* Wait until child has been added to the thread table. */ + /* This also ensures that we hold onto si until the child is done */ + /* with it. Thus it doesn't matter whether it is otherwise */ + /* visible to the collector. */ + if (0 != sem_wait(&(si -> registered))) ABORT("sem_wait failed"); + sem_destroy(&(si -> registered)); /* pthread_attr_destroy(&new_attr); */ return(result); } -- cgit v1.1