X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Finterrupt.c;h=8e8755170bc654ea0275c92d1bd3ccf5356b7148;hb=64eccd1724e5f1e638bfc574f7f376427ee3dcb1;hp=f651742f75f09ecd2a1e149aa221f18d527f5634;hpb=3dd90b64c37103d9c86d32b6c36277a6cea4098a;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index f651742..8e87551 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -68,6 +68,18 @@ #include "genesis/simple-fun.h" #include "genesis/cons.h" +/* Under Linux on some architectures, we appear to have to restore the + * FPU control word from the context, as after the signal is delivered + * we appear to have a null FPU control word. */ +#if defined(RESTORE_FP_CONTROL_FROM_CONTEXT) +#define RESTORE_FP_CONTROL_WORD(context,void_context) \ + os_context_t *context = arch_os_get_context(&void_context); \ + os_restore_fp_control(context); +#else +#define RESTORE_FP_CONTROL_WORD(context,void_context) \ + os_context_t *context = arch_os_get_context(&void_context); +#endif + /* These are to be used in signal handlers. Currently all handlers are * called from one of: * @@ -78,9 +90,10 @@ * low_level_maybe_now_maybe_later * low_level_unblock_me_trampoline */ -#define SAVE_ERRNO() \ +#define SAVE_ERRNO(context,void_context) \ { \ int _saved_errno = errno; \ + RESTORE_FP_CONTROL_WORD(context,void_context); \ { #define RESTORE_ERRNO \ @@ -854,13 +867,6 @@ interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context) check_interrupts_enabled_or_lose(context); #endif -#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT) - /* Under Linux on some architectures, we appear to have to restore - the FPU control word from the context, as after the signal is - delivered we appear to have a null FPU control word. */ - os_restore_fp_control(context); -#endif - handler = interrupt_handlers[signal]; if (ARE_SAME_HANDLER(handler.c, SIG_IGN)) { @@ -1044,15 +1050,10 @@ store_signal_data_for_later (struct interrupt_data *data, void *handler, static void maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(); - os_context_t *context = arch_os_get_context(&void_context); + SAVE_ERRNO(context,void_context); struct thread *thread = arch_os_get_current_thread(); struct interrupt_data *data = thread->interrupt_data; -#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT) - os_restore_fp_control(context); -#endif - if(!maybe_defer_handler(interrupt_handle_now,data,signal,info,context)) interrupt_handle_now(signal, info, context); RESTORE_ERRNO; @@ -1072,15 +1073,10 @@ low_level_interrupt_handle_now(int signal, siginfo_t *info, static void low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(); - os_context_t *context = arch_os_get_context(&void_context); + SAVE_ERRNO(context,void_context); struct thread *thread = arch_os_get_current_thread(); struct interrupt_data *data = thread->interrupt_data; -#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT) - os_restore_fp_control(context); -#endif - if(!maybe_defer_handler(low_level_interrupt_handle_now,data, signal,info,context)) low_level_interrupt_handle_now(signal, info, context); @@ -1153,10 +1149,7 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context) void interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(); - os_context_t *context = arch_os_get_context(&void_context); -#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT) - os_restore_fp_control(context); + SAVE_ERRNO(context,void_context); #ifndef LISP_FEATURE_WIN32 if ((signal == SIGILL) || (signal == SIGBUS) #ifndef LISP_FEATURE_LINUX @@ -1165,7 +1158,6 @@ interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context) ) corruption_warning_and_maybe_lose("Signal %d recieved", signal); #endif -#endif interrupt_handle_now(signal, info, context); RESTORE_ERRNO; } @@ -1195,7 +1187,7 @@ arrange_return_to_lisp_function(os_context_t *context, lispobj function) /* Build a stack frame showing `interrupted' so that the * user's backtrace makes (as much) sense (as usual) */ - /* FIXME: what about restoring fp state? */ + /* fp state is saved and restored by call_into_lisp */ /* FIXME: errno is not restored, but since current uses of this * function only call Lisp code that signals an error, it's not * much of a problem. In other words, running out of the control @@ -1390,8 +1382,8 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr) * previous page so that we can catch returns from the guard page * and restore it. */ corruption_warning_and_maybe_lose("Control stack exhausted"); - protect_control_stack_guard_page(0); - protect_control_stack_return_guard_page(1); + protect_control_stack_guard_page(0, NULL); + protect_control_stack_return_guard_page(1, NULL); #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK /* For the unfortunate case, when the control stack is @@ -1409,8 +1401,48 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr) * the return-guard-page, and hit it on our way to new * exhaustion instead. */ fprintf(stderr, "INFO: Control stack guard page reprotected\n"); - protect_control_stack_guard_page(1); - protect_control_stack_return_guard_page(0); + protect_control_stack_guard_page(1, NULL); + protect_control_stack_return_guard_page(0, NULL); + return 1; + } + else if(addr >= BINDING_STACK_GUARD_PAGE(th) && + addr < BINDING_STACK_GUARD_PAGE(th) + os_vm_page_size) { + corruption_warning_and_maybe_lose("Binding stack exhausted"); + protect_binding_stack_guard_page(0, NULL); + protect_binding_stack_return_guard_page(1, NULL); + + /* For the unfortunate case, when the binding stack is + * exhausted in a signal handler. */ + unblock_signals_in_context_and_maybe_warn(context); + arrange_return_to_lisp_function + (context, StaticSymbolFunction(BINDING_STACK_EXHAUSTED_ERROR)); + return 1; + } + else if(addr >= BINDING_STACK_RETURN_GUARD_PAGE(th) && + addr < BINDING_STACK_RETURN_GUARD_PAGE(th) + os_vm_page_size) { + fprintf(stderr, "INFO: Binding stack guard page reprotected\n"); + protect_binding_stack_guard_page(1, NULL); + protect_binding_stack_return_guard_page(0, NULL); + return 1; + } + else if(addr >= ALIEN_STACK_GUARD_PAGE(th) && + addr < ALIEN_STACK_GUARD_PAGE(th) + os_vm_page_size) { + corruption_warning_and_maybe_lose("Alien stack exhausted"); + protect_alien_stack_guard_page(0, NULL); + protect_alien_stack_return_guard_page(1, NULL); + + /* For the unfortunate case, when the alien stack is + * exhausted in a signal handler. */ + unblock_signals_in_context_and_maybe_warn(context); + arrange_return_to_lisp_function + (context, StaticSymbolFunction(ALIEN_STACK_EXHAUSTED_ERROR)); + return 1; + } + else if(addr >= ALIEN_STACK_RETURN_GUARD_PAGE(th) && + addr < ALIEN_STACK_RETURN_GUARD_PAGE(th) + os_vm_page_size) { + fprintf(stderr, "INFO: Alien stack guard page reprotected\n"); + protect_alien_stack_guard_page(1, NULL); + protect_alien_stack_return_guard_page(0, NULL); return 1; } else if (addr >= undefined_alien_address && @@ -1495,8 +1527,7 @@ see_if_sigaction_nodefer_works(void) static void unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(); - os_context_t *context = arch_os_get_context(&void_context); + SAVE_ERRNO(context,void_context); sigset_t unblock; sigemptyset(&unblock); @@ -1509,7 +1540,7 @@ unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) static void low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(); + SAVE_ERRNO(context,void_context); sigset_t unblock; sigemptyset(&unblock); @@ -1522,7 +1553,7 @@ low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) static void low_level_handle_now_handler(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(); + SAVE_ERRNO(context,void_context); (*interrupt_low_level_handlers[signal])(signal, info, void_context); RESTORE_ERRNO; } @@ -1671,10 +1702,14 @@ lisp_memory_fault_error(os_context_t *context, os_vm_address_t addr) */ current_memory_fault_address = addr; /* To allow debugging memory faults in signal handlers and such. */ - corruption_warning_and_maybe_lose("Memory fault"); + corruption_warning_and_maybe_lose("Memory fault at %x", addr); unblock_signals_in_context_and_maybe_warn(context); +#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK arrange_return_to_lisp_function(context, StaticSymbolFunction(MEMORY_FAULT_ERROR)); +#else + funcall0(StaticSymbolFunction(MEMORY_FAULT_ERROR)); +#endif } #endif