summaryrefslogtreecommitdiff
path: root/pthread_stop_world.c
diff options
context:
space:
mode:
authorhboehm <hboehm>2009-09-26 02:06:51 +0200
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 19:06:48 +0200
commit39cc5f4743cdf84f473507d8cb9ada62e69c81fb (patch)
treeb5f5b888258f81dc3b5f309f66f731474c234b7d /pthread_stop_world.c
parent183c30bb035c5ef2662ffa1da3557d26390c8cdf (diff)
2009-09-25 Hans Boehm <Hans.Boehm@hp.com>
* include/private/gcconfig.h (CANCEL_SAFE, IF_CANCEL): new macros. * include/private/gc_priv.h (DISABLE_CANCEL, RESTORE_CANCEL, ASSERT_CANCEL_DISABLED): New macros. * alloc.c (GC_maybe_gc): Assert cancellation disabled. (GC_collect_a_little_inner,GC_try_to_collect, GC_collect_or_expand): Disable cancellation. (GC_add_to_our_memory): Check for overflow. * misc.c (GC_cancel_disable_count): declare. (GC_init, GC_write): Disable cancellation. (GC_init): Remove redundant GC_is_initialized test. * os_dep.c (GC_repeat_read): Assert cancellation disabled. (GC_get_stack_base): Disable cancellation. * pthread_stop_world.c (GC_suspend_handler_inner): Disable cancellation. * pthread_support.c (GC_mark_thread): Permanently disable cancellation. (GC_wait_for_gc_completion, GC_wait_builder, GC_wait_marker): Assert cancellation disabled. (fork handling): Disable cancellation, fix comment. (GC_pthread_create): Disable cancellation. (GC_unregister_my_thread): Disable cancellation. * Makefile.direct: Document NO_CANCEL_SAFE.
Diffstat (limited to 'pthread_stop_world.c')
-rw-r--r--pthread_stop_world.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index 694a381..08363ff 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -169,11 +169,21 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context)
int dummy;
pthread_t my_thread = pthread_self();
GC_thread me;
+ IF_CANCEL(int cancel_state;)
AO_t my_stop_count = AO_load(&GC_stop_count);
if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler");
+ DISABLE_CANCEL(cancel_state);
+ /* pthread_setcancelstate is not defined to be async-signal-safe. */
+ /* But the glibc version appears to be in the absence of */
+ /* asynchronous cancellation. And since this signal handler */
+ /* to block on sigsuspend, which is both async-signal-safe */
+ /* and a cancellation point, there seems to be no obvious way */
+ /* out of it. In fact, it looks to me like an async-signal-safe */
+ /* cancellation point is inherently a problem, unless there is */
+ /* some way to disable cancellation in the handler. */
# if DEBUG_THREADS
GC_printf("Suspending 0x%x\n", (unsigned)my_thread);
# endif
@@ -188,6 +198,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context)
if (!GC_retry_signals) {
WARN("Duplicate suspend signal in thread %p\n", pthread_self());
}
+ RESTORE_CANCEL(cancel_state);
return;
}
# ifdef SPARC
@@ -230,6 +241,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context)
# if DEBUG_THREADS
GC_printf("Continuing 0x%x\n", (unsigned)my_thread);
# endif
+ RESTORE_CANCEL(cancel_state);
}
STATIC void GC_restart_handler(int sig)