X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Finterrupt.c;h=d7f4a4201d53871217c4840cbebd27665669df23;hb=dcf5978d9d33098e868ae6eea28e1b310038c03d;hp=7b4665242018ab46180d625bbb6dbd7c969be94e;hpb=f7b3fe1bd86348bfd2a3c506e437084752142c83;p=sbcl.git diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 7b46652..d7f4a42 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -69,8 +69,8 @@ static void store_signal_data_for_later (struct interrupt_data *data, os_context_t *context); boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *v_context); -extern lispobj all_threads_lock; -extern int countdown_to_gc; +extern volatile lispobj all_threads_lock; +extern volatile int countdown_to_gc; /* * This is a workaround for some slightly silly Linux/GNU Libc @@ -103,8 +103,7 @@ void sigaddset_blockable(sigset_t *s) sigaddset(s, SIGUSR1); sigaddset(s, SIGUSR2); #ifdef LISP_FEATURE_SB_THREAD - /* don't block STOP_FOR_GC, we need to be able to interrupt threads - * for GC purposes even when they are blocked on queues etc */ + sigaddset(s, SIG_STOP_FOR_GC); sigaddset(s, SIG_INTERRUPT_THREAD); #endif } @@ -118,6 +117,39 @@ boolean internal_errors_enabled = 0; struct interrupt_data * global_interrupt_data; +/* At the toplevel repl we routinely call this function. The signal + * mask ought to be clear anyway most of the time, but may be non-zero + * if we were interrupted e.g. while waiting for a queue. */ + +#if 1 +void reset_signal_mask () +{ + sigset_t new; + sigemptyset(&new); + sigprocmask(SIG_SETMASK,&new,0); +} +#else +void reset_signal_mask () +{ + sigset_t new,old; + int i; + int wrong=0; + sigemptyset(&new); + sigprocmask(SIG_SETMASK,&new,&old); + for(i=1; iinterrupt_data; + /* FIXME I'm not altogether sure this is appropriate if we're + * here as the result of a pseudo-atomic */ SetSymbolValue(INTERRUPT_PENDING, NIL,thread); /* restore the saved signal mask from the original signal (the @@ -407,7 +441,7 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context) if (were_in_lisp) #endif { - undo_fake_foreign_function_call(context); + undo_fake_foreign_function_call(context); /* block signals again */ } #ifdef QSHOW_SIGNALS @@ -425,10 +459,9 @@ interrupt_handle_now(int signal, siginfo_t *info, void *void_context) void run_deferred_handler(struct interrupt_data *data, void *v_context) { - fprintf(stderr,"Running deferred handler for %d, 0x%x\n", - data->pending_signal, data->pending_handler); (*(data->pending_handler)) (data->pending_signal,&(data->pending_info), v_context); + data->pending_handler=0; } boolean @@ -507,23 +540,20 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context) os_context_t *context = arch_os_get_context(&void_context); struct thread *thread=arch_os_get_current_thread(); struct interrupt_data *data=thread->interrupt_data; - sigset_t block; + if(maybe_defer_handler(sig_stop_for_gc_handler,data, signal,info,context)){ return; } - sigemptyset(&block); - sigaddset_blockable(&block); - sigprocmask(SIG_BLOCK, &block, 0); - /* need the context stored so it can have registers scavenged */ fake_foreign_function_call(context); get_spinlock(&all_threads_lock,thread->pid); countdown_to_gc--; + thread->state=STATE_STOPPED; release_spinlock(&all_threads_lock); - kill(getpid(),SIGSTOP); + kill(thread->pid,SIGSTOP); undo_fake_foreign_function_call(context); } @@ -625,13 +655,13 @@ void arrange_return_to_lisp_function(os_context_t *context, lispobj function) } #ifdef LISP_FEATURE_SB_THREAD -void handle_rt_signal(int num, siginfo_t *info, void *v_context) +void interrupt_thread_handler(int num, siginfo_t *info, void *v_context) { os_context_t *context = (os_context_t*)arch_os_get_context(&v_context); struct thread *th=arch_os_get_current_thread(); struct interrupt_data *data= th ? th->interrupt_data : global_interrupt_data; - if(maybe_defer_handler(handle_rt_signal,data,num,info,context)){ + if(maybe_defer_handler(interrupt_thread_handler,data,num,info,context)){ return ; } arrange_return_to_lisp_function(context,info->si_value.sival_int); @@ -682,16 +712,22 @@ interrupt_maybe_gc(int signal, siginfo_t *info, void *void_context) #endif -/* this is also used by from gencgc.c alloc() */ +/* this is also used by gencgc, in alloc() */ boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context) { + sigset_t new; os_context_t *context=(os_context_t *) void_context; fake_foreign_function_call(context); /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in * which case we will be running with no gc trigger barrier * thing for a while. But it shouldn't be long until the end * of WITHOUT-GCING. */ + + sigemptyset(&new); + sigaddset_blockable(&new); + /* enable signals before calling into Lisp */ + sigprocmask(SIG_UNBLOCK,&new,0); funcall0(SymbolFunction(SUB_GC)); undo_fake_foreign_function_call(context); return 1;