X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Fruntime%2Finterrupt.c;h=eb1e834a9b4013d60a9aa7825e10fb9ea4d9ae76;hb=78c2361d1d9e680230df412f4d1489725781c6d2;hp=357a5b26bb3d9e6e3740cd1a1e831c4cb5e894db;hpb=bf282f716a1ecaa09794a2cac7ce7da8d0d87675;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 357a5b2..eb1e834 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -123,9 +123,9 @@ static sigset_t blockable_sigset; #endif void -check_blockables_blocked_or_lose() +check_blockables_blocked_or_lose(void) { -#ifndef LISP_FEATURE_WIN32 +#if !defined(LISP_FEATURE_WIN32) /* Get the current sigmask, by blocking the empty set. */ sigset_t empty,current; int i; @@ -138,6 +138,41 @@ check_blockables_blocked_or_lose() #endif } +void +check_gc_signals_unblocked_or_lose(void) +{ +#ifdef LISP_FEATURE_SB_THREAD +# if !defined(LISP_FEATURE_WIN32) + /* Get the current sigmask, by blocking the empty set. */ + sigset_t empty,current; + sigemptyset(&empty); + thread_sigmask(SIG_BLOCK, &empty, ¤t); + if (sigismember(¤t, SIG_STOP_FOR_GC)) + lose("SIG_STOP_FOR_GC blocked in thread %p at a bad place\n", + arch_os_get_current_thread()); +# if defined(SIG_RESUME_FROM_GC) + if (sigismember(¤t, SIG_RESUME_FROM_GC)) + lose("SIG_RESUME_FROM_GC blocked in thread %p at a bad place\n", + arch_os_get_current_thread()); +# endif +# endif +#endif +} + +void +unblock_gc_signals(void) +{ +#ifdef LISP_FEATURE_SB_THREAD + sigset_t new; + sigemptyset(&new); +#if defined(SIG_RESUME_FROM_GC) + sigaddset(&new,SIG_RESUME_FROM_GC); +#endif + sigaddset(&new,SIG_STOP_FOR_GC); + thread_sigmask(SIG_UNBLOCK,&new,0); +#endif +} + inline static void check_interrupts_enabled_or_lose(os_context_t *context) { @@ -186,6 +221,14 @@ block_blockable_signals(void) #endif } +void +block_deferrable_signals(void) +{ +#ifndef LISP_FEATURE_WIN32 + thread_sigmask(SIG_BLOCK, &deferrable_sigset, 0); +#endif +} + /* * utility routines used by various signal handlers @@ -576,7 +619,6 @@ run_deferred_handler(struct interrupt_data *data, void *v_context) { * pending handler before calling it. Trust the handler to finish * with the siginfo before enabling interrupts. */ void (*pending_handler) (int, siginfo_t*, void*)=data->pending_handler; - os_context_t *context = arch_os_get_context(&v_context); data->pending_handler=0; (*pending_handler)(data->pending_signal,&(data->pending_info), v_context); @@ -740,7 +782,7 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context) struct thread *thread=arch_os_get_current_thread(); sigset_t ss; - if ((arch_pseudo_atomic_atomic(context) || + if ((arch_pseudo_atomic_atomic(context) || SymbolValue(GC_INHIBIT,thread) != NIL)) { SetSymbolValue(STOP_FOR_GC_PENDING,T,thread); if (SymbolValue(GC_INHIBIT,thread) == NIL) @@ -814,7 +856,7 @@ gc_trigger_hit(int signal, siginfo_t *info, os_context_t *context) else{ void *badaddr=arch_get_bad_addr(signal,info,context); return (badaddr >= (void *)current_auto_gc_trigger && - badaddr <((void *)current_dynamic_space + DYNAMIC_SPACE_SIZE)); + badaddr <((void *)current_dynamic_space + dynamic_space_size)); } } #endif @@ -930,6 +972,7 @@ arrange_return_to_lisp_function(os_context_t *context, lispobj function) #elif defined(LISP_FEATURE_X86_64) u64 *sp=(u64 *)*os_context_register_addr(context,reg_RSP); + /* return address for call_into_lisp: */ *(sp-18) = (u64)post_signal_tramp; @@ -1139,22 +1182,14 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) * outer context. */ #ifndef LISP_FEATURE_WIN32 - if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) + if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) { thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0); -#ifdef LISP_FEATURE_SB_THREAD - else { - sigset_t new; - sigemptyset(&new); -#if defined(SIG_RESUME_FROM_GC) - sigaddset(&new,SIG_RESUME_FROM_GC); -#endif - sigaddset(&new,SIG_STOP_FOR_GC); - thread_sigmask(SIG_UNBLOCK,&new,0); + check_gc_signals_unblocked_or_lose(); } -#endif + else + unblock_gc_signals(); #endif funcall0(SymbolFunction(SUB_GC)); - undo_fake_foreign_function_call(context); return 1; } @@ -1189,7 +1224,7 @@ sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context) sigset_t empty, current; int i; sigemptyset(&empty); - sigprocmask(SIG_BLOCK, &empty, ¤t); + thread_sigmask(SIG_BLOCK, &empty, ¤t); /* There should be exactly two blocked signals: the two we added * to sa_mask when setting up the handler. NetBSD doesn't block * the signal we're handling when SA_NODEFER is set; Linux before @@ -1220,7 +1255,7 @@ see_if_sigaction_nodefer_works() { sigset_t empty; sigemptyset(&empty); - sigprocmask(SIG_SETMASK, &empty, 0); + thread_sigmask(SIG_SETMASK, &empty, 0); } kill(getpid(), SA_NODEFER_TEST_KILL_SIGNAL); while (sigaction_nodefer_works == -1); @@ -1376,3 +1411,24 @@ interrupt_init() SHOW("returning from interrupt_init()"); #endif } + +#ifndef LISP_FEATURE_WIN32 +int +siginfo_code(siginfo_t *info) +{ + return info->si_code; +} +os_vm_address_t current_memory_fault_address; + +void +lisp_memory_fault_error(os_context_t *context, os_vm_address_t addr) +{ + /* FIXME: This is lossy: if we get another memory fault (eg. from + * another thread) before lisp has read this, we the information. + * However, since this is mostly informative, we'll live with that for + * now -- some address is better then no address in this case. + */ + current_memory_fault_address = addr; + arrange_return_to_lisp_function(context, SymbolFunction(MEMORY_FAULT_ERROR)); +} +#endif