$NetBSD: patch-aj,v 1.4 2005/07/31 15:26:58 recht Exp $ --- libgc/pthread_stop_world.c.orig 2005-07-05 20:46:03.000000000 +0200 +++ libgc/pthread_stop_world.c @@ -99,6 +99,7 @@ word GC_stop_count; /* Incremented at th # endif #endif +#if !defined(GC_NETBSD_THREADS) sem_t GC_suspend_ack_sem; static void _GC_suspend_handler(int sig) @@ -208,6 +209,7 @@ static void _GC_restart_handler(int sig) GC_printf1("In GC_restart_handler for 0x%lx\n", pthread_self()); #endif } +#endif /* !GC_NETBSD_THREADS */ # ifdef IA64 # define IF_IA64(x) x @@ -283,12 +285,14 @@ static void pthread_push_all_stacks() ABORT("Collecting from unknown thread."); } +#if !defined(GC_NETBSD_THREADS) void GC_restart_handler(int sig) { int old_errno = errno; _GC_restart_handler (sig); errno = old_errno; } +#endif /* We hold allocation lock. Should do exactly the right thing if the */ /* world is stopped. Should not fail if it isn't. */ @@ -297,6 +301,28 @@ void GC_push_all_stacks() gc_thread_vtable->push_all_stacks(); } +#if defined(GC_NETBSD_THREADS) +/* + * Get the stack start address for the specified address. + */ +int +np_stackinfo(pthread_t p, void **addr) +{ + pthread_attr_t attr; + int ret = -1; + + if (pthread_attr_init(&attr)) + return -1; + + if (!pthread_attr_get_np(p, &attr)) + if (!pthread_attr_getstackaddr(&attr, addr)) + ret = 0; + + pthread_attr_destroy(&attr); + return ret; +} +#endif + /* There seems to be a very rare thread stopping problem. To help us */ /* debug that, we save the ids of the stopping thread. */ pthread_t GC_stopping_thread; @@ -322,6 +348,7 @@ int GC_suspend_all() if (p -> stop_info.last_stop_count == GC_stop_count) continue; if (p -> thread_blocked) /* Will wait */ continue; n_live_threads++; +#if !defined(GC_NETBSD_THREADS) #if DEBUG_THREADS GC_printf1("Sending suspend signal to 0x%lx\n", p -> id); #endif @@ -337,6 +364,23 @@ int GC_suspend_all() default: ABORT("pthread_kill failed"); } +#else + #if DEBUG_THREADS + GC_printf1("Suspending 0x%lx ...\n", p -> id); + #endif + + if(pthread_suspend_np(p -> id) != 0) + GC_printf1("Could not susend thread... 0x%lx\n", p -> id); + + /* Right now, this is not enough. Retreiving the stack base address is not the correct */ + /* info to give to the GC, but since there is no way to get the current stack pointer */ + /* for the suspended thread, base pointer will have to be enough. Mono seems to be */ + /* happy with it so... */ + if(np_stackinfo(p -> id, &(p -> stop_info.stack_ptr)) != 0) + GC_err_printf1("Could not get thread stack address... 0x%lx\n", p -> id); + + n_live_threads--; +#endif /* !GC_NETBSD_THREADS */ } } } @@ -356,6 +400,7 @@ static void pthread_stop_world() n_live_threads = GC_suspend_all(); +#if !defined(GC_NETBSD_THREADS) if (GC_retry_signals) { unsigned long wait_usecs = 0; /* Total wait since retry. */ # define WAIT_UNIT 3000 @@ -393,6 +438,8 @@ static void pthread_stop_world() } } } +#endif /* !GC_NETBSD_THREADS */ + #if DEBUG_THREADS GC_printf1("World stopped from 0x%lx\n", pthread_self()); #endif @@ -439,6 +486,7 @@ static void pthread_start_world() if (p -> flags & FINISHED) continue; if (p -> thread_blocked) continue; n_live_threads++; +#if !defined(GC_NETBSD_THREADS) #if DEBUG_THREADS GC_printf1("Sending restart signal to 0x%lx\n", p -> id); #endif @@ -454,10 +502,18 @@ static void pthread_start_world() default: ABORT("pthread_kill failed"); } +#else + #if DEBUG_THREADS + GC_printf1("Resuming Thread 0x%lx\n", p -> id); + #endif + pthread_resume_np(p -> id); + n_live_threads--; +#endif /* !GC_NETBSD_THREADS */ } } } +#if !defined(GC_NETBSD_THREADS) #if DEBUG_THREADS GC_printf0 ("All threads signaled"); #endif @@ -470,6 +526,7 @@ static void pthread_start_world() } } } +#endif /* !GC_NETBSD_THREADS */ #if DEBUG_THREADS GC_printf0("World started\n"); @@ -482,6 +539,8 @@ void GC_start_world() } static void pthread_stop_init() { + +#if !defined(GC_NETBSD_THREADS) struct sigaction act; if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0) @@ -522,6 +581,16 @@ static void pthread_stop_init() { GC_printf0("Will retry suspend signal if necessary.\n"); } # endif +#else + struct sigaction act; + + act.sa_flags = SA_RESTART; + if (sigfillset(&act.sa_mask) != 0) { + ABORT("sigfillset() failed"); + } + GC_remove_allowed_signals(&act.sa_mask); + +#endif /* !GC_NETBSD_THREADS */ } /* We hold the allocation lock. */