summaryrefslogtreecommitdiff
path: root/pthread_stop_world.c
diff options
context:
space:
mode:
authorivmai <ivmai>2009-10-20 23:27:25 +0200
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 19:06:51 +0200
commitc4e4721f491632c2039cece14400f353794273f4 (patch)
tree81ea0ea761bfcdc92d55a67d28fc0f83659cf9dd /pthread_stop_world.c
parentf2127b50f72ad5449c24f1e0bd4b3d4ca88185d8 (diff)
2009-10-20 Ivan Maidanski <ivmai@mail.ru> (really mostly OpenBSD contributors)
* configure.ac (openbsd): Define GC_OPENBSD_THREADS. * configure.ac: Add AM_CONDITIONAL(OPENBSD_THREADS). * configure.ac: Add sparc-openbsd case. * doc/README.macros (GC_NETBSD_THREADS, GC_OPENBSD_THREADS): Document. * tests/test.c (main): Handle OpenBSD case. * extra/threadlibs.c: Add the copyright header; expand all tabs to spaces; remove trailing spaces at EOLn. * include/private/pthread_stop_world.h: Ditto. * extra/threadlibs.c (main): Replace K&R-style function definition with the ANSI C one. * extra/threadlibs.c (main): Handle GC_OPENBSD_THREADS case. * dyn_load.c (OPENBSD): Recognize (similar to NETBSD). * include/gc_config_macros.h (GC_SOLARIS_THREADS): Recognize; define it for OpenBSD. * include/gc_pthread_redirects.h (GC_pthread_sigmask, pthread_sigmask): Don't declare and redefine for OpenBSD. * include/private/gcconfig.h: Handle OpenBSD (on arm, sh, i386, amd64, powerpc). * mach_dep.c (NO_GETCONTEXT): Ditto. * include/private/pthread_stop_world.h (thread_stop_info): Don't define last_stop_count field if OpenBSD. * misc.c (GC_init_dyld): Add declaration (if NetBSD). * misc.c (GC_init): Don't call GC_init_netbsd_elf() for OpenBSD. * os_dep.c (GC_init_netbsd_elf): Don't define for OpenBSD. * os_dep.c (old_segv_act, GC_jmp_buf_openbsd): New static variable (only if OpenBSD). * os_dep.c (GC_fault_handler_openbsd, GC_find_limit_openbsd, GC_skip_hole_openbsd): New static function (only if OpenBSD). * os_dep.c (GC_get_stack_base, GC_get_main_stack_base, GC_register_data_segments): Define specially for OpenBSD case. * os_dep.c (GC_fault_handler_lock): Initialize to AO_TS_INITIALIZER (instead of 0). * pthread_support.c (GC_allocate_lock): Ditto. * pthread_stop_world.c (NSIG, GC_print_sig_mask, GC_remove_allowed_signals, suspend_handler_mask, GC_stop_count, GC_world_is_stopped, GC_retry_signals, SIG_THR_RESTART, GC_suspend_ack_sem, GC_suspend_handler_inner, GC_suspend_handler, GC_restart_handler): Don't define and use if OpenBSD. * pthread_stop_world.c (GC_suspend_all, GC_stop_world, GC_start_world): Handle OpenBSD case. * pthread_stop_world.c (GC_stop_init): Define as empty if OpenBSD. * pthread_support.c (pthread_sigmask): Don't undefine the macro and don't define the wrapper function if OpenBSD. * pthread_support.c (GC_thr_init): Handle OpenBSD case. * configure: Regenerate. * include/private/config.h.in: Ditto.
Diffstat (limited to 'pthread_stop_world.c')
-rw-r--r--pthread_stop_world.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index 865b436..f5f35f6 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -20,6 +20,8 @@
#if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) && \
!defined(GC_DARWIN_THREADS)
+#ifndef GC_OPENBSD_THREADS
+
#include <signal.h>
#include <semaphore.h>
#include <errno.h>
@@ -268,6 +270,8 @@ STATIC void GC_restart_handler(int sig)
# endif
}
+#endif /* !GC_OPENBSD_THREADS */
+
void GC_thr_init(void);
# ifdef IA64
@@ -357,7 +361,9 @@ STATIC int GC_suspend_all(void)
int n_live_threads = 0;
int i;
GC_thread p;
- int result;
+# ifndef GC_OPENBSD_THREADS
+ int result;
+# endif
pthread_t my_thread = pthread_self();
# ifdef DEBUG_THREADS
@@ -368,16 +374,29 @@ STATIC int GC_suspend_all(void)
for (p = GC_threads[i]; p != 0; p = p -> next) {
if (!THREAD_EQUAL(p -> id, my_thread)) {
if (p -> flags & FINISHED) continue;
- if (p -> stop_info.last_stop_count == GC_stop_count) continue;
if (p -> thread_blocked) /* Will wait */ continue;
- n_live_threads++;
+# ifndef GC_OPENBSD_THREADS
+ if (p -> stop_info.last_stop_count == GC_stop_count) continue;
+ n_live_threads++;
+# endif
# ifdef DEBUG_THREADS
GC_printf("Sending suspend signal to 0x%x\n",
(unsigned)(p -> id));
# endif
- result = pthread_kill(p -> id, SIG_SUSPEND);
- switch(result) {
+# ifdef GC_OPENBSD_THREADS
+ if (pthread_suspend_np(p -> id) != 0)
+ ABORT("pthread_suspend_np failed");
+ /* This will only work for userland pthreads. It will */
+ /* fail badly on rthreads. Perhaps we should consider */
+ /* a pthread_sp_np() function that returns the stack */
+ /* pointer for a suspended thread and implement in both */
+ /* pthreads and rthreads. */
+ p -> stop_info.stack_ptr =
+ *(ptr_t *)((char *)p -> id + UTHREAD_SP_OFFSET);
+# else
+ result = pthread_kill(p -> id, SIG_SUSPEND);
+ switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
n_live_threads--;
@@ -386,7 +405,8 @@ STATIC int GC_suspend_all(void)
break;
default:
ABORT("pthread_kill failed");
- }
+ }
+# endif
}
}
}
@@ -396,8 +416,10 @@ STATIC int GC_suspend_all(void)
void GC_stop_world(void)
{
int i;
- int n_live_threads;
- int code;
+# ifndef GC_OPENBSD_THREADS
+ int n_live_threads;
+ int code;
+# endif
GC_ASSERT(I_HOLD_LOCK());
# ifdef DEBUG_THREADS
@@ -415,6 +437,10 @@ void GC_stop_world(void)
/* We should have previously waited for it to become zero. */
}
# endif /* PARALLEL_MARK */
+
+# ifdef GC_OPENBSD_THREADS
+ (void)GC_suspend_all();
+# else
AO_store(&GC_stop_count, GC_stop_count+1);
/* Only concurrent reads are possible. */
AO_store_release(&GC_world_is_stopped, TRUE);
@@ -459,6 +485,8 @@ void GC_stop_world(void)
ABORT("sem_wait for handler failed");
}
}
+# endif
+
# ifdef PARALLEL_MARK
if (GC_parallel)
GC_release_mark_lock();
@@ -476,8 +504,10 @@ void GC_start_world(void)
pthread_t my_thread = pthread_self();
register int i;
register GC_thread p;
- register int n_live_threads = 0;
- register int result;
+# ifndef GC_OPENBSD_THREADS
+ register int n_live_threads = 0;
+ register int result;
+# endif
# ifdef GC_NETBSD_THREADS_WORKAROUND
int code;
# endif
@@ -486,18 +516,26 @@ void GC_start_world(void)
GC_printf("World starting\n");
# endif
- AO_store(&GC_world_is_stopped, FALSE);
+# ifndef GC_OPENBSD_THREADS
+ AO_store(&GC_world_is_stopped, FALSE);
+# endif
for (i = 0; i < THREAD_TABLE_SZ; i++) {
for (p = GC_threads[i]; p != 0; p = p -> next) {
if (!THREAD_EQUAL(p -> id, my_thread)) {
if (p -> flags & FINISHED) continue;
if (p -> thread_blocked) continue;
- n_live_threads++;
+# ifndef GC_OPENBSD_THREADS
+ n_live_threads++;
+# endif
# ifdef DEBUG_THREADS
GC_printf("Sending restart signal to 0x%x\n",
(unsigned)(p -> id));
# endif
+# ifdef GC_OPENBSD_THREADS
+ if (pthread_resume_np(p -> id) != 0)
+ ABORT("pthread_kill failed");
+# else
result = pthread_kill(p -> id, SIG_THR_RESTART);
switch(result) {
case ESRCH:
@@ -509,6 +547,7 @@ void GC_start_world(void)
default:
ABORT("pthread_kill failed");
}
+# endif
}
}
}
@@ -528,6 +567,7 @@ void GC_start_world(void)
void GC_stop_init(void)
{
+# ifndef GC_OPENBSD_THREADS
struct sigaction act;
if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
@@ -581,6 +621,7 @@ void GC_stop_init(void)
if (GC_print_stats && GC_retry_signals) {
GC_log_printf("Will retry suspend signal if necessary.\n");
}
+# endif /* !GC_OPENBSD_THREADS */
}
#endif