X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Finterrupt.c;h=882e2bb322e64bda821c0c90dadee262911685f5;hb=bf40ae88bc289fd765a33861cc4bc0853ed483ba;hp=9b82a58f8cbf1135812c1ce40f100fb4c439efb7;hpb=7aef55b130d95c384b63422807f1848faa9aba5a;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 9b82a58..882e2bb 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -642,9 +642,9 @@ build_fake_control_stack_frames(struct thread *th,os_context_t *context) /* Build a fake stack frame or frames */ access_control_frame_pointer(th) = - (lispobj *)(unsigned long) + (lispobj *)(uword_t) (*os_context_register_addr(context, reg_CSP)); - if ((lispobj *)(unsigned long) + if ((lispobj *)(uword_t) (*os_context_register_addr(context, reg_CFP)) == access_control_frame_pointer(th)) { /* There is a small window during call where the callee's @@ -702,19 +702,19 @@ fake_foreign_function_call(os_context_t *context) thread->pseudo_atomic_bits = #else dynamic_space_free_pointer = - (lispobj *)(unsigned long) + (lispobj *)(uword_t) #endif (*os_context_register_addr(context, reg_ALLOC)); /* fprintf(stderr,"dynamic_space_free_pointer: %p\n", */ /* dynamic_space_free_pointer); */ #if defined(LISP_FEATURE_ALPHA) || defined(LISP_FEATURE_MIPS) - if ((long)dynamic_space_free_pointer & 1) { + if ((sword_t)dynamic_space_free_pointer & 1) { lose("dead in fake_foreign_function_call, context = %x\n", context); } #endif /* why doesnt PPC and SPARC do something like this: */ #if defined(LISP_FEATURE_HPPA) - if ((long)dynamic_space_free_pointer & 4) { + if ((sword_t)dynamic_space_free_pointer & 4) { lose("dead in fake_foreign_function_call, context = %x, d_s_f_p = %x\n", context, dynamic_space_free_pointer); } #endif @@ -766,13 +766,13 @@ undo_fake_foreign_function_call(os_context_t *context) #if defined(reg_ALLOC) && !defined(LISP_FEATURE_SB_THREAD) /* Put the dynamic space free pointer back into the context. */ *os_context_register_addr(context, reg_ALLOC) = - (unsigned long) dynamic_space_free_pointer + (uword_t) dynamic_space_free_pointer | (*os_context_register_addr(context, reg_ALLOC) & LOWTAG_MASK); /* - ((unsigned long)(*os_context_register_addr(context, reg_ALLOC)) + ((uword_t)(*os_context_register_addr(context, reg_ALLOC)) & ~LOWTAG_MASK) - | ((unsigned long) dynamic_space_free_pointer & LOWTAG_MASK); + | ((uword_t) dynamic_space_free_pointer & LOWTAG_MASK); */ #endif #if defined(reg_ALLOC) && defined(LISP_FEATURE_SB_THREAD) @@ -780,7 +780,7 @@ undo_fake_foreign_function_call(os_context_t *context) * into the context (p-a-bits for p-a, and dynamic space free * pointer for ROOM). */ *os_context_register_addr(context, reg_ALLOC) = - (unsigned long) dynamic_space_free_pointer + (uword_t) dynamic_space_free_pointer | (thread->pseudo_atomic_bits & LOWTAG_MASK); /* And clear them so we don't get bit later by call-in/call-out * not updating them. */ @@ -916,39 +916,12 @@ interrupt_handle_pending(os_context_t *context) /* handles the STOP_FOR_GC_PENDING case, plus THRUPTIONS */ if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL # ifdef LISP_FEATURE_SB_THRUPTION - || SymbolValue(THRUPTION_PENDING,thread) != NIL + || (SymbolValue(THRUPTION_PENDING,thread) != NIL + && SymbolValue(INTERRUPTS_ENABLED, thread) != NIL) # endif ) - { /* We ought to take this chance to do a pitstop now. */ - - /* Now, it goes without saying that the context sigmask - * tweaking around this call is not pretty. However, it - * currently seems to be "needed" for the following - * situation. (So let's find a better solution and remove - * this comment afterwards.) - * - * Suppose we are in a signal handler (let's say SIGALRM). - * At the end of a WITHOUT-INTERRUPTS, the lisp code notices - * that a thruption is pending, and says to itself "let's - * receive pending interrupts then". We trust that the - * caller is happy to run those sorts of things now, - * including thruptions, otherwise it wouldn't have called - * us. But that's the problem: Even though we can guess the - * caller's intention, may_thrupt() would see that signals - * are blocked in the signal context (because that context - * itself points to a signal handler). So we cheat and - * pretend that signals weren't blocked. - * --DFL */ -#ifndef LISP_FEATURE_WIN32 - sigset_t old, *ctxset = os_context_sigmask_addr(context); - unblock_signals(&deferrable_sigset, ctxset, &old); -#endif - thread_pitstop(context); -#ifndef LISP_FEATURE_WIN32 - sigcopyset(&old, ctxset); -#endif - } + thread_in_lisp_raised(context); #elif defined(LISP_FEATURE_SB_THREAD) if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL) { /* STOP_FOR_GC_PENDING and GC_PENDING are cleared by @@ -1016,7 +989,7 @@ interrupt_handle_pending(os_context_t *context) * an interrupt arrived during GC (POST-GC, really) it was * handled. */ if (original_pending_handler != data->pending_handler) - lose("pending handler changed in gc: %x -> %d.", + lose("pending handler changed in gc: %x -> %x.", original_pending_handler, data->pending_handler); } @@ -1806,6 +1779,89 @@ see_if_sigaction_nodefer_works(void) #undef SA_NODEFER_TEST_BLOCK_SIGNAL #undef SA_NODEFER_TEST_KILL_SIGNAL +#if defined(LISP_FEATURE_SB_SAFEPOINT_STRICTLY) && !defined(LISP_FEATURE_WIN32) + +static void * +signal_thread_trampoline(void *pthread_arg) +{ + int signo = (int) pthread_arg; + os_context_t fake_context; + siginfo_t fake_info; +#ifdef LISP_FEATURE_PPC + mcontext_t uc_regs; +#endif + + memset(&fake_info, 0, sizeof(fake_info)); + memset(&fake_context, 0, sizeof(fake_context)); +#ifdef LISP_FEATURE_PPC + memset(&uc_regs, 0, sizeof(uc_regs)); + fake_context.uc_mcontext.uc_regs = &uc_regs; +#endif + + *os_context_pc_addr(&fake_context) = &signal_thread_trampoline; +#ifdef ARCH_HAS_STACK_POINTER /* aka x86(-64) */ + *os_context_sp_addr(&fake_context) = __builtin_frame_address(0); +#endif + + signal_handler_callback(interrupt_handlers[signo].lisp, + signo, &fake_info, &fake_context); + return 0; +} + +static void +sigprof_handler_trampoline(int signal, siginfo_t *info, void *void_context) +{ + SAVE_ERRNO(signal,context,void_context); + struct thread *self = arch_os_get_current_thread(); + + /* alloc() is not re-entrant and still uses pseudo atomic (even though + * inline allocation does not). In this case, give up. */ + if (get_pseudo_atomic_atomic(self)) + goto cleanup; + + struct alloc_region tmp = self->alloc_region; + self->alloc_region = self->sprof_alloc_region; + self->sprof_alloc_region = tmp; + + interrupt_handle_now_handler(signal, info, void_context); + + /* And we're back. We know that the SIGPROF handler never unwinds + * non-locally, and can simply swap things back: */ + + tmp = self->alloc_region; + self->alloc_region = self->sprof_alloc_region; + self->sprof_alloc_region = tmp; + +cleanup: + ; /* Dear C compiler, it's OK to have a label here. */ + RESTORE_ERRNO; +} + +static void +spawn_signal_thread_handler(int signal, siginfo_t *info, void *void_context) +{ + SAVE_ERRNO(signal,context,void_context); + + pthread_attr_t attr; + pthread_t th; + + if (pthread_attr_init(&attr)) + goto lost; + if (pthread_attr_setstacksize(&attr, thread_control_stack_size)) + goto lost; + if (pthread_create(&th, &attr, &signal_thread_trampoline, (void*) signal)) + goto lost; + if (pthread_attr_destroy(&attr)) + goto lost; + + RESTORE_ERRNO; + return; + +lost: + lose("spawn_signal_thread_handler"); +} +#endif + static void unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) { @@ -1889,8 +1945,9 @@ undoably_install_low_level_interrupt_handler (int signal, #endif /* This is called from Lisp. */ -unsigned long -install_handler(int signal, void handler(int, siginfo_t*, os_context_t*)) +uword_t +install_handler(int signal, void handler(int, siginfo_t*, os_context_t*), + int synchronous) { #ifndef LISP_FEATURE_WIN32 struct sigaction sa; @@ -1907,6 +1964,12 @@ install_handler(int signal, void handler(int, siginfo_t*, os_context_t*)) if (ARE_SAME_HANDLER(handler, SIG_DFL) || ARE_SAME_HANDLER(handler, SIG_IGN)) sa.sa_sigaction = (void (*)(int, siginfo_t*, void*))handler; +#ifdef LISP_FEATURE_SB_SAFEPOINT_STRICTLY + else if (signal == SIGPROF) + sa.sa_sigaction = sigprof_handler_trampoline; + else if (!synchronous) + sa.sa_sigaction = spawn_signal_thread_handler; +#endif else if (sigismember(&deferrable_sigset, signal)) sa.sa_sigaction = maybe_now_maybe_later; else if (!sigaction_nodefer_works && @@ -1928,7 +1991,7 @@ install_handler(int signal, void handler(int, siginfo_t*, os_context_t*)) FSHOW((stderr, "/leaving POSIX install_handler(%d, ..)\n", signal)); - return (unsigned long)oldhandler.lisp; + return (uword_t)oldhandler.lisp; #else /* Probably-wrong Win32 hack */ return 0; @@ -2065,7 +2128,7 @@ handle_trap(os_context_t *context, int trap) arch_handle_single_step_trap(context, trap); break; #endif -#ifdef LISP_FEATURE_SB_SAFEPOINT +#ifdef trap_GlobalSafepoint case trap_GlobalSafepoint: fake_foreign_function_call(context); thread_in_lisp_raised(context);