X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Finterrupt.c;h=c2ef993717522d88adddb5cfb6817f561f412edf;hb=c01ff86b012283af04641a02e45f066aa7cdb10c;hp=23773085e3d09b03c783c2ec778e3fb78930dd24;hpb=cd056980425e3fa67b8b77de3936ccb46508c3b0;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 2377308..c2ef993 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -199,7 +199,7 @@ fake_foreign_function_call(os_context_t *context) #ifdef reg_ALLOC dynamic_space_free_pointer = (lispobj *)(*os_context_register_addr(context, reg_ALLOC)); -#ifdef alpha +#if defined(LISP_FEATURE_ALPHA) if ((long)dynamic_space_free_pointer & 1) { lose("dead in fake_foreign_function_call, context = %x", context); } @@ -305,8 +305,9 @@ interrupt_handle_pending(os_context_t *context) thread=arch_os_get_current_thread(); data=thread->interrupt_data; - /* FIXME I'm not altogether sure this is appropriate if we're - * here as the result of a pseudo-atomic */ + + /* FIXME: This is almost certainly wrong if we're here as the + * result of a pseudo-atomic as opposed to WITHOUT-INTERRUPTS. */ SetSymbolValue(INTERRUPT_PENDING, NIL,thread); /* restore the saved signal mask from the original signal (the @@ -517,7 +518,7 @@ maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context) interrupt_handle_now(signal, info, context); #ifdef LISP_FEATURE_DARWIN /* Work around G5 bug */ - sigreturn(void_context); + DARWIN_FIX_CONTEXT(context); #endif } @@ -547,11 +548,19 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context) * awful state, to stop them from being waited for indefinitely. * Userland reaping is done later when GC is finished */ mark_dead_threads(); - + if(thread->state!=STATE_STOPPING) { + lose("sig_stop_for_gc_handler: wrong thread state: %ld\n", + fixnum_value(thread->state)); + } thread->state=STATE_STOPPED; sigemptyset(&ss); sigaddset(&ss,SIG_STOP_FOR_GC); sigwaitinfo(&ss,0); + if(thread->state!=STATE_STOPPED) { + lose("sig_stop_for_gc_handler: wrong thread state on wakeup: %ld\n", + fixnum_value(thread->state)); + } + thread->state=STATE_RUNNING; undo_fake_foreign_function_call(context); } @@ -563,7 +572,7 @@ interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context) os_context_t *context = arch_os_get_context(&void_context); interrupt_handle_now(signal, info, context); #ifdef LISP_FEATURE_DARWIN - sigreturn(void_context); + DARWIN_FIX_CONTEXT(context); #endif } @@ -808,6 +817,53 @@ interrupt_maybe_gc(int signal, siginfo_t *info, void *void_context) #endif +void +kludge_sigset_for_gc(sigset_t * set) +{ +#ifndef LISP_FEATURE_GENCGC + /* FIXME: It is not sure if GENCGC is really right here: maybe this + * really affects eg. only Sparc and PPC. And the following KLUDGE + * could really use real fixing as well. + * + * KLUDGE: block some async signals that seem to have the ability + * to hang us in an uninterruptible state during GC -- at least + * part of the time. The main beneficiary of this is SB-SPROF, as + * SIGPROF was almost certain to be eventually triggered at a bad + * moment, rendering it virtually useless. SIGINT and SIGIO from + * user or eg. Slime also seemed to occasionally do this. + * + * The problem this papers over appears to be something going awry + * in SB-UNIX:RECEIVE-PENDING-SIGNALS at the end of the + * WITHOUT-INTERRUPTS in SUB-GC: adding debugging output shows us + * leaving the body of W-I, but never entering sigtrap_handler. + * + * Empirically, it seems that the problem is only triggered if the + * GC was triggered/deferred during a PA section, but this is not + * a sufficient condition: some collections triggered in such a + * manner seem to be able to receive and defer a signal during the + * GC without issues. Likewise empirically, it seems that the + * problem arises more often with floating point code then not. Eg + * (LOOP (* (RANDOM 1.0) (RANDOM 1.0))) will eventually hang if + * run with SB-SPROF on, but (LOOP (FOO (MAKE-LIST 24))) will not. + * All this makes some badnesss in the interaction between PA and + * W-I seem likely, possibly in the form of one or more bad VOPs. + * + * For additional entertainment on the affected platforms we + * currently use an actual illegal instruction to receive pending + * interrupts instead of a trap: whether this has any bearing on + * the matter is unknown. + * + * Apparently CMUCL blocks everything but SIGILL for GC on Sparc, + * possibly for this very reason. + * + * -- NS 2005-05-20 + */ + sigdelset(set, SIGPROF); + sigdelset(set, SIGIO); + sigdelset(set, SIGINT); +#endif +} + /* this is also used by gencgc, in alloc() */ boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) @@ -815,16 +871,24 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) sigset_t new; os_context_t *context=(os_context_t *) void_context; fake_foreign_function_call(context); + /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in * which case we will be running with no gc trigger barrier * thing for a while. But it shouldn't be long until the end - * of WITHOUT-GCING. */ + * of WITHOUT-GCING. + * + * FIXME: It would be good to protect the end of dynamic space + * and signal a storage condition from there. + */ + /* enable some signals before calling into Lisp */ sigemptyset(&new); sigaddset_blockable(&new); - /* enable signals before calling into Lisp */ + kludge_sigset_for_gc(&new); sigprocmask(SIG_UNBLOCK,&new,0); + funcall0(SymbolFunction(SUB_GC)); + undo_fake_foreign_function_call(context); return 1; }