summaryrefslogtreecommitdiff
path: root/boehm-gc/irix_threads.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@cygnus.com>1999-11-01 23:15:51 +0000
committerTom Tromey <tromey@gcc.gnu.org>1999-11-01 23:15:51 +0000
commit20bbd3cd53a80ddafa56a5d21337aae0c24f94ca (patch)
tree9c24ba1ebabff472b9caddbff07ef957dbf2c24c /boehm-gc/irix_threads.c
parentc05ddfa745d68f6d9db1a7d0992650a41986d376 (diff)
downloadgcc-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.c66
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);
}