X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Finterrupt.c;h=6a5205337553a916b33e090ed1e11592205136a4;hb=7fb597b585fc715537ea644f7d84440eca217ca1;hp=8a935260fa6f34b9dc02f2e29cf70229752f8466;hpb=e663f81f7297ab9f53b38d5f0975152de3557e69;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 8a93526..6a52053 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -40,16 +40,18 @@ * * - WHN 20000728, dan 20010128 */ +#include "sbcl.h" #include #include #include #include #include +#ifndef LISP_FEATURE_WIN32 #include +#endif #include -#include "sbcl.h" #include "runtime.h" #include "arch.h" #include "os.h" @@ -69,6 +71,7 @@ static void run_deferred_handler(struct interrupt_data *data, void *v_context); +#ifndef LISP_FEATURE_WIN32 static void store_signal_data_for_later (struct interrupt_data *data, void *handler, int signal, siginfo_t *info, @@ -111,10 +114,12 @@ sigaddset_blockable(sigset_t *s) /* initialized in interrupt_init */ static sigset_t deferrable_sigset; static sigset_t blockable_sigset; +#endif void check_blockables_blocked_or_lose() { +#ifndef LISP_FEATURE_WIN32 /* Get the current sigmask, by blocking the empty set. */ sigset_t empty,current; int i; @@ -122,8 +127,9 @@ check_blockables_blocked_or_lose() thread_sigmask(SIG_BLOCK, &empty, ¤t); for(i = 1; i < NSIG; i++) { if (sigismember(&blockable_sigset, i) && !sigismember(¤t, i)) - lose("blockable signal %d not blocked",i); + lose("blockable signal %d not blocked\n",i); } +#endif } inline static void @@ -131,13 +137,13 @@ check_interrupts_enabled_or_lose(os_context_t *context) { struct thread *thread=arch_os_get_current_thread(); if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) - lose("interrupts not enabled"); + lose("interrupts not enabled\n"); if ( #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) (!foreign_function_call_active) && #endif arch_pseudo_atomic_atomic(context)) - lose ("in pseudo atomic section"); + lose ("in pseudo atomic section\n"); } /* When we catch an internal error, should we pass it back to Lisp to @@ -147,7 +153,9 @@ check_interrupts_enabled_or_lose(os_context_t *context) * becomes 'yes'.) */ boolean internal_errors_enabled = 0; +#ifndef LISP_FEATURE_WIN32 static void (*interrupt_low_level_handlers[NSIG]) (int, siginfo_t*, void*); +#endif union interrupt_handler interrupt_handlers[NSIG]; /* At the toplevel repl we routinely call this function. The signal @@ -157,15 +165,19 @@ union interrupt_handler interrupt_handlers[NSIG]; void reset_signal_mask(void) { +#ifndef LISP_FEATURE_WIN32 sigset_t new; sigemptyset(&new); thread_sigmask(SIG_SETMASK,&new,0); +#endif } void block_blockable_signals(void) { +#ifndef LISP_FEATURE_WIN32 thread_sigmask(SIG_BLOCK, &blockable_sigset, 0); +#endif } @@ -244,7 +256,7 @@ fake_foreign_function_call(os_context_t *context) (*os_context_register_addr(context, reg_ALLOC)); #if defined(LISP_FEATURE_ALPHA) if ((long)dynamic_space_free_pointer & 1) { - lose("dead in fake_foreign_function_call, context = %x", context); + lose("dead in fake_foreign_function_call, context = %x\n", context); } #endif #endif @@ -262,7 +274,7 @@ fake_foreign_function_call(os_context_t *context) fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,thread)); if (context_index >= MAX_INTERRUPTS) { - lose("maximum interrupt nesting depth (%d) exceeded", MAX_INTERRUPTS); + lose("maximum interrupt nesting depth (%d) exceeded\n", MAX_INTERRUPTS); } bind_variable(FREE_INTERRUPT_CONTEXT_INDEX, @@ -311,14 +323,16 @@ interrupt_internal_error(int signal, siginfo_t *info, os_context_t *context, describe_internal_error(context); /* There's no good way to recover from an internal error * before the Lisp error handling mechanism is set up. */ - lose("internal error too early in init, can't recover"); + lose("internal error too early in init, can't recover\n"); } /* Allocate the SAP object while the interrupts are still * disabled. */ context_sap = alloc_sap(context); +#ifndef LISP_FEATURE_WIN32 thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0); +#endif SHOW("in interrupt_internal_error"); #ifdef QSHOW @@ -346,6 +360,12 @@ interrupt_handle_pending(os_context_t *context) thread=arch_os_get_current_thread(); data=thread->interrupt_data; +#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) + /* If pseudo_atomic_interrupted is set then the interrupt is going + * to be handled now, ergo it's safe to clear it. */ + arch_clear_pseudo_atomic_interrupted(context); +#endif + if (SymbolValue(GC_INHIBIT,thread)==NIL) { #ifdef LISP_FEATURE_SB_THREAD if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL) { @@ -388,6 +408,7 @@ interrupt_handle_pending(os_context_t *context) * PSEUDO_ATOMIC_INTERRUPTED only if interrupts are enabled.*/ SetSymbolValue(INTERRUPT_PENDING, NIL,thread); +#ifndef LISP_FEATURE_WIN32 /* restore the saved signal mask from the original signal (the * one that interrupted us during the critical section) into the * os_context for the signal we're currently in the handler for. @@ -396,6 +417,7 @@ interrupt_handle_pending(os_context_t *context) sigcopyset(os_context_sigmask_addr(context), &data->pending_mask); sigemptyset(&data->pending_mask); +#endif /* This will break on sparc linux: the deferred handler really wants * to be called with a void_context */ run_deferred_handler(data,(void *)context); @@ -427,8 +449,10 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context) #endif union interrupt_handler handler; check_blockables_blocked_or_lose(); +#ifndef LISP_FEATURE_WIN32 if (sigismember(&deferrable_sigset,signal)) check_interrupts_enabled_or_lose(context); +#endif #ifdef LISP_FEATURE_LINUX /* Under Linux on some architectures, we appear to have to restore @@ -459,7 +483,7 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context) /* This can happen if someone tries to ignore or default one * of the signals we need for runtime support, and the runtime * support decides to pass on it. */ - lose("no handler for signal %d in interrupt_handle_now(..)", signal); + lose("no handler for signal %d in interrupt_handle_now(..)\n", signal); } else if (lowtag_of(handler.lisp) == FUN_POINTER_LOWTAG) { /* Once we've decided what to do about contexts in a @@ -500,8 +524,10 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context) FSHOW_SIGNAL((stderr,"/calling C-level handler\n")); +#ifndef LISP_FEATURE_WIN32 /* Allow signals again. */ thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0); +#endif (*handler.c)(signal, info, void_context); } @@ -534,6 +560,7 @@ run_deferred_handler(struct interrupt_data *data, void *v_context) { (*pending_handler)(data->pending_signal,&(data->pending_info), v_context); } +#ifndef LISP_FEATURE_WIN32 boolean maybe_defer_handler(void *handler, struct interrupt_data *data, int signal, siginfo_t *info, os_context_t *context) @@ -543,7 +570,7 @@ maybe_defer_handler(void *handler, struct interrupt_data *data, check_blockables_blocked_or_lose(); if (SymbolValue(INTERRUPT_PENDING,thread) != NIL) - lose("interrupt already pending"); + lose("interrupt already pending\n"); /* If interrupts are disabled then INTERRUPT_PENDING is set and * not PSEDUO_ATOMIC_INTERRUPTED. This is important for a pseudo * atomic section inside a WITHOUT-INTERRUPTS. @@ -664,6 +691,7 @@ low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context) DARWIN_FIX_CONTEXT(context); #endif } +#endif #ifdef LISP_FEATURE_SB_THREAD @@ -993,7 +1021,9 @@ boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) { os_context_t *context=(os_context_t *) void_context; +#ifndef LISP_FEATURE_WIN32 struct thread *thread=arch_os_get_current_thread(); +#endif fake_foreign_function_call(context); @@ -1019,6 +1049,7 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) * A kludgy alternative is to propagate the sigmask change to the * outer context. */ +#ifndef LISP_FEATURE_WIN32 if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0); #ifdef LISP_FEATURE_SB_THREAD @@ -1029,6 +1060,7 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) thread_sigmask(SIG_UNBLOCK,&new,0); } #endif +#endif funcall0(SymbolFunction(SUB_GC)); undo_fake_foreign_function_call(context); @@ -1040,6 +1072,7 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) * noise to install handlers */ +#ifndef LISP_FEATURE_WIN32 /* In Linux 2.4 synchronous signals (sigtrap & co) can be delivered if * they are blocked, in Linux 2.6 the default handler is invoked * instead that usually coredumps. One might hastily think that adding @@ -1069,24 +1102,22 @@ sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context) static void see_if_sigaction_nodefer_works() { - struct sigaction sa; + struct sigaction sa, old_sa; sa.sa_flags = SA_SIGINFO | SA_NODEFER; sa.sa_sigaction = sigaction_nodefer_test_handler; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGABRT); - /* We can use any signal for which a handler will be installed - * later. Let's go with SIGINT because gdb barfs on SIGTRAP on - * Darwin. */ - sigaction(SIGINT, &sa, NULL); + sigaction(SIGUSR1, &sa, &old_sa); /* Make sure no signals are blocked. */ { sigset_t empty; sigemptyset(&empty); sigprocmask(SIG_SETMASK, &empty, 0); } - kill(getpid(), SIGINT); + kill(getpid(), SIGUSR1); while (sigaction_nodefer_works == -1); + sigaction(SIGUSR1, &old_sa, NULL); } static void @@ -1118,7 +1149,7 @@ undoably_install_low_level_interrupt_handler (int signal, struct sigaction sa; if (0 > signal || signal >= NSIG) { - lose("bad signal number %d", signal); + lose("bad signal number %d\n", signal); } if (ARE_SAME_HANDLER(handler, SIG_DFL)) @@ -1136,6 +1167,9 @@ undoably_install_low_level_interrupt_handler (int signal, (sigaction_nodefer_works ? SA_NODEFER : 0); #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK if((signal==SIG_MEMORY_FAULT) +#ifdef SIG_MEMORY_FAULT2 + || (signal==SIG_MEMORY_FAULT2) +#endif #ifdef SIG_INTERRUPT_THREAD || (signal==SIG_INTERRUPT_THREAD) #endif @@ -1147,11 +1181,13 @@ undoably_install_low_level_interrupt_handler (int signal, interrupt_low_level_handlers[signal] = (ARE_SAME_HANDLER(handler, SIG_DFL) ? 0 : handler); } +#endif /* This is called from Lisp. */ unsigned long install_handler(int signal, void handler(int, siginfo_t*, void*)) { +#ifndef LISP_FEATURE_WIN32 struct sigaction sa; sigset_t old, new; union interrupt_handler oldhandler; @@ -1190,11 +1226,16 @@ install_handler(int signal, void handler(int, siginfo_t*, void*)) FSHOW((stderr, "/leaving POSIX install_handler(%d, ..)\n", signal)); return (unsigned long)oldhandler.lisp; +#else + /* Probably-wrong Win32 hack */ + return 0; +#endif } void interrupt_init() { +#ifndef LISP_FEATURE_WIN32 int i; SHOW("entering interrupt_init()"); see_if_sigaction_nodefer_works(); @@ -1215,4 +1256,5 @@ interrupt_init() } SHOW("returning from interrupt_init()"); +#endif }