X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Finterrupt.c;h=123a57635e9068881e97cb449567ff1482bd853b;hb=371577a214ce2659c271279ad48e4c42e1c0c93e;hp=47656454ba13b6292c181a03118e0487a8323b81;hpb=9ee246f59019b776b38f6c09b2ce730cd0b32844;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 4765645..123a576 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -59,10 +59,10 @@ #include "globals.h" #include "lispregs.h" #include "validate.h" +#include "interr.h" #include "gc.h" #include "alloc.h" #include "dynbind.h" -#include "interr.h" #include "pseudo-atomic.h" #include "genesis/fdefn.h" #include "genesis/simple-fun.h" @@ -102,6 +102,7 @@ union interrupt_handler interrupt_handlers[NSIG]; * work for SIGSEGV and similar. It is good enough for timers, and * maybe all deferrables. */ +#ifdef LISP_FEATURE_SB_THREAD static void add_handled_signals(sigset_t *sigset) { @@ -115,6 +116,7 @@ add_handled_signals(sigset_t *sigset) } void block_signals(sigset_t *what, sigset_t *where, sigset_t *old); +#endif static boolean maybe_resignal_to_lisp_thread(int signal, os_context_t *context) @@ -1240,6 +1242,12 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, os_context_t *context) set_thread_state(thread,STATE_SUSPENDED); FSHOW_SIGNAL((stderr,"suspended\n")); + /* While waiting for gc to finish occupy ourselves with zeroing + * the unused portion of the control stack to reduce conservatism. + * On hypothetic platforms with threads and exact gc it is + * actually a must. */ + scrub_control_stack(); + wait_for_thread_state_change(thread, STATE_SUSPENDED); FSHOW_SIGNAL((stderr,"resumed\n")); @@ -1263,7 +1271,7 @@ interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context) || (signal == SIGEMT) #endif ) - corruption_warning_and_maybe_lose("Signal %d recieved", signal); + corruption_warning_and_maybe_lose("Signal %d received", signal); #endif interrupt_handle_now(signal, info, context); RESTORE_ERRNO; @@ -1477,6 +1485,37 @@ undefined_alien_function(void) funcall0(StaticSymbolFunction(UNDEFINED_ALIEN_FUNCTION_ERROR)); } +void lower_thread_control_stack_guard_page(struct thread *th) +{ + protect_control_stack_guard_page(0, th); + protect_control_stack_return_guard_page(1, th); + th->control_stack_guard_page_protected = NIL; + fprintf(stderr, "INFO: Control stack guard page unprotected\n"); +} + +void reset_thread_control_stack_guard_page(struct thread *th) +{ + memset(CONTROL_STACK_GUARD_PAGE(th), 0, os_vm_page_size); + protect_control_stack_guard_page(1, th); + protect_control_stack_return_guard_page(0, th); + th->control_stack_guard_page_protected = T; + fprintf(stderr, "INFO: Control stack guard page reprotected\n"); +} + +/* Called from the REPL, too. */ +void reset_control_stack_guard_page(void) +{ + struct thread *th=arch_os_get_current_thread(); + if (th->control_stack_guard_page_protected == NIL) { + reset_thread_control_stack_guard_page(th); + } +} + +void lower_control_stack_guard_page(void) +{ + lower_thread_control_stack_guard_page(arch_os_get_current_thread()); +} + boolean handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr) { @@ -1492,10 +1531,9 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr) * protection so the error handler has some headroom, protect the * previous page so that we can catch returns from the guard page * and restore it. */ - protect_control_stack_guard_page(0, NULL); - protect_control_stack_return_guard_page(1, NULL); - fprintf(stderr, "INFO: Control stack guard page unprotected\n"); - + if (th->control_stack_guard_page_protected == NIL) + lose("control_stack_guard_page_protected NIL"); + lower_control_stack_guard_page(); #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK /* For the unfortunate case, when the control stack is * exhausted in a signal handler. */ @@ -1511,9 +1549,9 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr) * unprotect this one. This works even if we somehow missed * the return-guard-page, and hit it on our way to new * exhaustion instead. */ - protect_control_stack_guard_page(1, NULL); - protect_control_stack_return_guard_page(0, NULL); - fprintf(stderr, "INFO: Control stack guard page reprotected\n"); + if (th->control_stack_guard_page_protected != NIL) + lose("control_stack_guard_page_protected not NIL"); + reset_control_stack_guard_page(); return 1; } else if(addr >= BINDING_STACK_HARD_GUARD_PAGE(th) &&