From 1d33d240c6f1385157c7d71f681911f7387ddf32 Mon Sep 17 00:00:00 2001 From: Gabor Melis Date: Mon, 16 Feb 2009 21:42:05 +0000 Subject: [PATCH] 1.0.25.28: always use SIG_RESUME_FROM_GC The other mechanism relied on real time signals which made it freeze when the sysystem wide real time signal queue got full on Linux. A full queue spells trouble for other processes using rt signals. All platforms are changed to use SIGUSR1 and SIGUSR2 for SIG_STOP_FOR_GC and SIG_RESUME_FROM_GC. Check that SIG_RESUME_FROM_GC is never signalled without a corresponding sigwait. --- src/runtime/bsd-os.c | 4 +--- src/runtime/interrupt.c | 30 +++++++++++------------------- src/runtime/interrupt.h | 1 + src/runtime/linux-os.c | 2 ++ src/runtime/linux-os.h | 4 ++-- src/runtime/sunos-os.c | 2 ++ src/runtime/sunos-os.h | 4 ++-- src/runtime/thread.c | 8 -------- src/runtime/win32-os.h | 1 + version.lisp-expr | 2 +- 10 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index e31048a..c5e3e4e 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -257,10 +257,8 @@ os_install_interrupt_handlers(void) interrupt_thread_handler); undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC, sig_stop_for_gc_handler); -#ifdef SIG_RESUME_FROM_GC undoably_install_low_level_interrupt_handler(SIG_RESUME_FROM_GC, - sig_stop_for_gc_handler); -#endif + sig_resume_from_gc_handler); #endif SHOW("leaving os_install_interrupt_handlers()"); } diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 9e4bfff..cdd7b24 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -105,25 +105,18 @@ sigaddset_deferrable(sigset_t *s) sigaddset(s, SIGPROF); sigaddset(s, SIGWINCH); -#if !((defined(LISP_FEATURE_DARWIN) || defined(LISP_FEATURE_FREEBSD)) && defined(LISP_FEATURE_SB_THREAD)) - sigaddset(s, SIGUSR1); - sigaddset(s, SIGUSR2); -#endif - #ifdef LISP_FEATURE_SB_THREAD sigaddset(s, SIG_INTERRUPT_THREAD); #endif } void -sigaddset_blockable(sigset_t *s) +sigaddset_blockable(sigset_t *sigset) { - sigaddset_deferrable(s); + sigaddset_deferrable(sigset); #ifdef LISP_FEATURE_SB_THREAD -#ifdef SIG_RESUME_FROM_GC - sigaddset(s, SIG_RESUME_FROM_GC); -#endif - sigaddset(s, SIG_STOP_FOR_GC); + sigaddset(sigset,SIG_RESUME_FROM_GC); + sigaddset(sigset,SIG_STOP_FOR_GC); #endif } @@ -876,23 +869,15 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context) FSHOW_SIGNAL((stderr,"suspended\n")); sigemptyset(&ss); -#if defined(SIG_RESUME_FROM_GC) sigaddset(&ss,SIG_RESUME_FROM_GC); -#else - sigaddset(&ss,SIG_STOP_FOR_GC); -#endif /* It is possible to get SIGCONT (and probably other non-blockable * signals) here. */ -#ifdef SIG_RESUME_FROM_GC { int sigret; do { sigwait(&ss, &sigret); } while (sigret != SIG_RESUME_FROM_GC); } -#else - while (sigwaitinfo(&ss,0) != SIG_STOP_FOR_GC); -#endif FSHOW_SIGNAL((stderr,"resumed\n")); if(thread->state!=STATE_RUNNING) { @@ -902,6 +887,13 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context) undo_fake_foreign_function_call(context); } + +void +sig_resume_from_gc_handler(int signal, siginfo_t *info, void *void_context) +{ + lose("SIG_RESUME_FROM_GC handler called."); +} + #endif void diff --git a/src/runtime/interrupt.h b/src/runtime/interrupt.h index 210579b..36b9720 100644 --- a/src/runtime/interrupt.h +++ b/src/runtime/interrupt.h @@ -103,6 +103,7 @@ extern void do_pending_interrupt(void); #ifdef LISP_FEATURE_SB_THREAD extern void interrupt_thread_handler(int, siginfo_t*, void*); extern void sig_stop_for_gc_handler(int, siginfo_t*, void*); +extern void sig_resume_from_gc_handler(int, siginfo_t*, void*); #endif typedef void (*interrupt_handler_t)(int, siginfo_t *, void *); extern void undoably_install_low_level_interrupt_handler ( diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 4a3f994..8bd86f1 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -422,6 +422,8 @@ os_install_interrupt_handlers(void) interrupt_thread_handler); undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC, sig_stop_for_gc_handler); + undoably_install_low_level_interrupt_handler(SIG_RESUME_FROM_GC, + sig_resume_from_gc_handler); #endif } diff --git a/src/runtime/linux-os.h b/src/runtime/linux-os.h index cfeaed4..8b74848 100644 --- a/src/runtime/linux-os.h +++ b/src/runtime/linux-os.h @@ -40,5 +40,5 @@ typedef int os_vm_prot_t; #define SIG_MEMORY_FAULT SIGSEGV #define SIG_INTERRUPT_THREAD (SIGRTMIN) -#define SIG_STOP_FOR_GC (SIGRTMIN+1) - +#define SIG_STOP_FOR_GC (SIGUSR1) +#define SIG_RESUME_FROM_GC (SIGUSR2) diff --git a/src/runtime/sunos-os.c b/src/runtime/sunos-os.c index 8d8bb28..bf8e4ec 100644 --- a/src/runtime/sunos-os.c +++ b/src/runtime/sunos-os.c @@ -238,6 +238,8 @@ os_install_interrupt_handlers() interrupt_thread_handler); undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC, sig_stop_for_gc_handler); + undoably_install_low_level_interrupt_handler(SIG_RESUME_FROM_GC, + sig_resume_from_gc_handler); #endif } diff --git a/src/runtime/sunos-os.h b/src/runtime/sunos-os.h index 95212e2..6720c31 100644 --- a/src/runtime/sunos-os.h +++ b/src/runtime/sunos-os.h @@ -33,8 +33,8 @@ typedef int os_vm_prot_t; #define SIG_MEMORY_FAULT SIGSEGV #define SIG_INTERRUPT_THREAD (SIGRTMIN) -#define SIG_STOP_FOR_GC (SIGRTMIN+1) -#define SIG_RESUME_FROM_GC (SIGRTMIN+2) +#define SIG_STOP_FOR_GC (SIGUSR1) +#define SIG_RESUME_FROM_GC (SIGUSR2) /* Yaargh?! */ typedef int os_context_register_t ; diff --git a/src/runtime/thread.c b/src/runtime/thread.c index 69a32b3..ae2f990 100644 --- a/src/runtime/thread.c +++ b/src/runtime/thread.c @@ -668,21 +668,13 @@ void gc_start_the_world() p->os_thread)); p->state=STATE_RUNNING; -#if defined(SIG_RESUME_FROM_GC) status=kill_thread_safely(p->os_thread,SIG_RESUME_FROM_GC); -#else - status=kill_thread_safely(p->os_thread,SIG_STOP_FOR_GC); -#endif if (status) { lose("cannot resume thread=%lu: %d, %s\n", p->os_thread,status,strerror(status)); } } } - /* If we waited here until all threads leave STATE_SUSPENDED, then - * SIG_STOP_FOR_GC wouldn't need to be a rt signal. That has some - * performance implications, but does away with the 'rt signal - * queue full' problem. */ lock_ret = pthread_mutex_unlock(&all_threads_lock); gc_assert(lock_ret == 0); diff --git a/src/runtime/win32-os.h b/src/runtime/win32-os.h index 1526e8d..f08a784 100644 --- a/src/runtime/win32-os.h +++ b/src/runtime/win32-os.h @@ -37,6 +37,7 @@ typedef void *siginfo_t; #define SIG_INTERRUPT_THREAD (SIGRTMIN) #define SIG_STOP_FOR_GC (SIGRTMIN+1) +#define SIG_RESUME_FROM_GC (SIGRTMIN+4) #define SIG_DEQUEUE (SIGRTMIN+2) #define SIG_THREAD_EXIT (SIGRTMIN+3) diff --git a/version.lisp-expr b/version.lisp-expr index 8c4d00c..575dff3 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.25.27" +"1.0.25.28" -- 1.7.10.4