diff options
author | Tom Tromey <tromey@cygnus.com> | 1999-11-01 23:15:51 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 1999-11-01 23:15:51 +0000 |
commit | 20bbd3cd53a80ddafa56a5d21337aae0c24f94ca (patch) | |
tree | 9c24ba1ebabff472b9caddbff07ef957dbf2c24c /boehm-gc/irix_threads.c | |
parent | c05ddfa745d68f6d9db1a7d0992650a41986d376 (diff) | |
download | gcc-20bbd3cd53a80ddafa56a5d21337aae0c24f94ca.tar.gz |
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
Diffstat (limited to 'boehm-gc/irix_threads.c')
-rw-r--r-- | boehm-gc/irix_threads.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/boehm-gc/irix_threads.c b/boehm-gc/irix_threads.c index f45c4631c6e..5efca211034 100644 --- a/boehm-gc/irix_threads.c +++ b/boehm-gc/irix_threads.c @@ -25,6 +25,7 @@ # include "gc_priv.h" # include <pthread.h> +# include <semaphore.h> # include <time.h> # include <errno.h> # include <unistd.h> @@ -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); } |