diff --git a/lisp/interrupt.c b/lisp/interrupt.c index 91e8e8fb92e213f2fc9bed26eb29ae755be342ae..661e88eaf6a28eabb98c8a201912ad60432b3e16 100644 --- a/lisp/interrupt.c +++ b/lisp/interrupt.c @@ -1,4 +1,4 @@ -/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.c,v 1.4 1994/07/05 16:08:03 hallgren Exp $ */ +/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.c,v 1.5 1994/10/24 20:05:30 ram Exp $ */ /* Interrupt handing magic. */ @@ -12,12 +12,12 @@ #endif #include "lisp.h" +#include "arch.h" #include "internals.h" #include "os.h" -#include "arch.h" +#include "interrupt.h" #include "globals.h" #include "lispregs.h" -#include "interrupt.h" #include "validate.h" #include "monitor.h" #include "gc.h" @@ -30,10 +30,25 @@ boolean internal_errors_enabled = 0; struct sigcontext *lisp_interrupt_contexts[MAX_INTERRUPTS]; union interrupt_handler interrupt_handlers[NSIG]; -void (*interrupt_low_level_handlers[NSIG])(int signal, int code, - struct sigcontext *scp) = {0}; +void (*interrupt_low_level_handlers[NSIG]) (HANDLER_ARGS) = {0}; + +static int pending_signal = 0; + +#ifdef SOLARIS +static siginfo_t *pending_code; +#define PASSCODE(code) ((code)) +#define DEREFCODE(code) ((code)) +#else +static int pending_code = 0; +#define PASSCODE(code) (code) +#define DEREFCODE(code) (code) +#endif -static int pending_signal = 0, pending_code = 0, pending_mask = 0; +#ifdef POSIX_SIGS +static sigset_t pending_mask; +#else +static int pending_mask = 0; +#endif static boolean maybe_gc_pending = FALSE; @@ -118,7 +133,14 @@ void fake_foreign_function_call(struct sigcontext *context) void undo_fake_foreign_function_call(struct sigcontext *context) { /* Block all blockable signals */ +#ifdef POSIX_SIGS + sigset_t block; + sigemptyset(&block); + FILLBLOCKSET(&block); + sigprocmask(SIG_BLOCK, &block, 0); +#else sigblock(BLOCKABLE); +#endif /* Going back into lisp. */ foreign_function_call_active = 0; @@ -134,10 +156,14 @@ void undo_fake_foreign_function_call(struct sigcontext *context) #endif } -void interrupt_internal_error(int signal, int code, struct sigcontext *context, +void interrupt_internal_error(HANDLER_ARGS, boolean continuable) { +#ifdef POSIX_SIGS + sigprocmask(SIG_SETMASK,&context->uc_sigmask, 0); +#else sigsetmask(context->sc_mask); +#endif fake_foreign_function_call(context); if (internal_errors_enabled) funcall2(SymbolFunction(INTERNAL_ERROR), alloc_sap(context), @@ -164,16 +190,25 @@ void interrupt_handle_pending(struct sigcontext *context) undo_fake_foreign_function_call(context); } if (pending_signal) { - int signal, code; - + int signal; +#ifdef SOLARIS + siginfo_t *code; +#else + int code; +#endif signal = pending_signal; code = pending_code; pending_signal = 0; - pending_code = 0; - interrupt_handle_now(signal, code, context); + /* pending_code = 0; /**/ + interrupt_handle_now(signal, PASSCODE(code), context); } +#ifdef POSIX_SIGS + context->uc_sigmask = pending_mask; + sigemptyset(&pending_mask); +#else context->sc_mask = pending_mask; pending_mask = 0; +#endif } @@ -182,7 +217,7 @@ void interrupt_handle_pending(struct sigcontext *context) * the two main signal handlers. * \****************************************************************/ -void interrupt_handle_now(int signal, int code, struct sigcontext *context) +void interrupt_handle_now(HANDLER_ARGS) { int were_in_lisp; union interrupt_handler handler; @@ -192,12 +227,18 @@ void interrupt_handle_now(int signal, int code, struct sigcontext *context) if(handler.c==SIG_IGN) return; + SAVE_CONTEXT(); /**/ + were_in_lisp = !foreign_function_call_active; if (were_in_lisp) fake_foreign_function_call(context); /* Allow signals again. */ +#ifdef POSIX_SIGS + sigprocmask(SIG_SETMASK, &context->uc_sigmask, 0); +#else sigsetmask(context->sc_mask); +#endif if (handler.c==SIG_DFL) /* This can happen if someone tries to ignore or default on of the */ @@ -205,8 +246,13 @@ void interrupt_handle_now(int signal, int code, struct sigcontext *context) /* decides to pass on it. */ lose("interrupt_handle_now: No handler for signal %d?\n", signal); else if (LowtagOf(handler.lisp) == type_FunctionPointer) - funcall3(handler.lisp, make_fixnum(signal), make_fixnum(code), +#if 1 + funcall3(handler.lisp, make_fixnum(signal), make_fixnum(CODE(code)), + alloc_sap(context)); +#else + funcall3(handler.lisp, make_fixnum(signal), alloc_sap(code), alloc_sap(context)); +#endif else (*handler.c)(signal, code, context); @@ -214,21 +260,32 @@ void interrupt_handle_now(int signal, int code, struct sigcontext *context) undo_fake_foreign_function_call(context); } -static void maybe_now_maybe_later(int signal, int code, - struct sigcontext *context) +static void maybe_now_maybe_later(HANDLER_ARGS) { + SAVE_CONTEXT(); /**/ + if (SymbolValue(INTERRUPTS_ENABLED) == NIL) { pending_signal = signal; - pending_code = code; + pending_code = DEREFCODE(code); +#ifdef POSIX_SIGS + pending_mask = context->uc_sigmask; + FILLBLOCKSET(&context->uc_sigmask); +#else pending_mask = context->sc_mask; context->sc_mask |= BLOCKABLE; +#endif SetSymbolValue(INTERRUPT_PENDING, T); } else if ((!foreign_function_call_active) && arch_pseudo_atomic_atomic(context)) { pending_signal = signal; - pending_code = code; + pending_code = DEREFCODE(code); +#ifdef POSIX_SIGS + pending_mask = context->uc_sigmask; + FILLBLOCKSET(&context->uc_sigmask); +#else pending_mask = context->sc_mask; context->sc_mask |= BLOCKABLE; +#endif arch_set_pseudo_atomic_interrupted(context); } else interrupt_handle_now(signal, code, context); @@ -239,7 +296,7 @@ static void maybe_now_maybe_later(int signal, int code, \****************************************************************/ #ifndef INTERNAL_GC_TRIGGER -static boolean gc_trigger_hit(int signal, int code, struct sigcontext *context) +static boolean gc_trigger_hit(HANDLER_ARGS) { if (current_auto_gc_trigger == NULL) return FALSE; @@ -253,7 +310,7 @@ static boolean gc_trigger_hit(int signal, int code, struct sigcontext *context) #endif -boolean interrupt_maybe_gc(int signal, int code, struct sigcontext *context) +boolean interrupt_maybe_gc(HANDLER_ARGS) { if (!foreign_function_call_active #ifndef INTERNAL_GC_TRIGGER @@ -267,8 +324,13 @@ boolean interrupt_maybe_gc(int signal, int code, struct sigcontext *context) if (arch_pseudo_atomic_atomic(context)) { maybe_gc_pending = TRUE; if (pending_signal == 0) { +#ifdef POSIX_SIGS + pending_mask = context->uc_sigmask; + FILLBLOCKSET(&context->uc_sigmask); +#else pending_mask = context->sc_mask; context->sc_mask |= BLOCKABLE; +#endif } arch_set_pseudo_atomic_interrupted(context); } @@ -289,8 +351,18 @@ boolean interrupt_maybe_gc(int signal, int code, struct sigcontext *context) void interrupt_install_low_level_handler (int signal, - void handler(int signal, int code, struct sigcontext *handler)) + void handler(HANDLER_ARGS)) { +#ifdef POSIX_SIGS + struct sigaction sa; + + sa.sa_sigaction=handler; + sigemptyset(&sa.sa_mask); + FILLBLOCKSET(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_SIGINFO; + + sigaction(signal, &sa, NULL); +#else struct sigvec sv; sv.sv_handler=handler; @@ -298,13 +370,49 @@ void interrupt_install_low_level_handler sv.sv_flags=0; sigvec(signal,&sv,NULL); +#endif interrupt_low_level_handlers[signal]=(handler==SIG_DFL ? 0 : handler); } unsigned long install_handler(int signal, - void handler(int signal, int code, - struct sigcontext *handler)) + void handler(HANDLER_ARGS)) +#ifdef POSIX_SIGS +{ + struct sigaction sa; + sigset_t old,new; + union interrupt_handler oldhandler; + + sigemptyset(&new); + sigaddset(&new, signal); + sigprocmask(SIG_BLOCK, &new, &old); + + sigemptyset(&new); + FILLBLOCKSET(&new); + + if(interrupt_low_level_handlers[signal]==0){ + if(handler==SIG_DFL || handler==SIG_IGN) + sa.sa_sigaction = handler; + else if (sigismember(&new, signal)) + sa.sa_sigaction = maybe_now_maybe_later; + else + sa.sa_sigaction = interrupt_handle_now; + + sigemptyset(&sa.sa_mask); + FILLBLOCKSET(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_RESTART; + + sigaction(signal, &sa, NULL); + } + + oldhandler = interrupt_handlers[signal]; + interrupt_handlers[signal].c = handler; + + sigprocmask(SIG_SETMASK, &old, 0); + + return (unsigned long)oldhandler.lisp; +} +#else { struct sigvec sv; int oldmask; @@ -333,6 +441,7 @@ unsigned long install_handler(int signal, return (unsigned long)oldhandler.lisp; } +#endif void interrupt_init(void) { diff --git a/lisp/interrupt.h b/lisp/interrupt.h index 21058120c2937267fd852a799e0f3b1b5e672c8d..cb06c86e5c858baa37eb76aa1fe41d849d13df8b 100644 --- a/lisp/interrupt.h +++ b/lisp/interrupt.h @@ -1,4 +1,4 @@ -/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.h,v 1.3 1993/07/27 15:08:44 hallgren Exp $ */ +/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.h,v 1.4 1994/10/24 20:06:00 ram Exp $ */ #if !defined(_INCLUDE_INTERRUPT_H_) #define _INCLUDE_INTERRUPT_H_ @@ -11,24 +11,21 @@ extern struct sigcontext *lisp_interrupt_contexts[MAX_INTERRUPTS]; union interrupt_handler { lispobj lisp; - void (*c)(int signal, int code, struct sigcontext *scp); + void (*c)(HANDLER_ARGS); }; extern void interrupt_init(void); extern void fake_foreign_function_call(struct sigcontext *context); extern void undo_fake_foreign_function_call(struct sigcontext *context); -extern void interrupt_handle_now(int signal, int code, struct sigcontext *scp); +extern void interrupt_handle_now(HANDLER_ARGS); extern void interrupt_handle_pending(struct sigcontext *scp); -extern void interrupt_internal_error(int signal, int code, - struct sigcontext *scp, - boolean continuable); -extern boolean interrupt_maybe_gc(int sig, int code, struct sigcontext *scp); +extern void interrupt_internal_error(HANDLER_ARGS, boolean continuable); +extern boolean interrupt_maybe_gc(HANDLER_ARGS); extern void interrupt_install_low_level_handler (int signal, - void handler(int signal, int code, struct sigcontext *scp)); + void handler(HANDLER_ARGS)); extern unsigned long install_handler(int signal, - void handler(int signal, int code, - struct sigcontext *handler)); + void handler(HANDLER_ARGS)); extern union interrupt_handler interrupt_handlers[NSIG]; @@ -41,6 +38,16 @@ extern union interrupt_handler interrupt_handlers[NSIG]; sigmask(SIGPROF) | sigmask(SIGWINCH) | \ sigmask(SIGUSR1) | sigmask(SIGUSR2)) #else +#ifdef POSIX_SIGS +#define FILLBLOCKSET(s) (sigaddset(s,SIGHUP), sigaddset(s,SIGINT), \ + sigaddset(s,SIGQUIT), sigaddset(s,SIGPIPE), \ + sigaddset(s,SIGALRM), sigaddset(s,SIGURG), \ + sigaddset(s,SIGTSTP), sigaddset(s,SIGCHLD), \ + sigaddset(s,SIGIO), sigaddset(s,SIGXCPU), \ + sigaddset(s,SIGXFSZ), sigaddset(s,SIGVTALRM), \ + sigaddset(s,SIGPROF), sigaddset(s,SIGWINCH), \ + sigaddset(s,SIGUSR1), sigaddset(s,SIGUSR2)) +#else #define BLOCKABLE (sigmask(SIGHUP) | sigmask(SIGINT) | \ sigmask(SIGQUIT) | sigmask(SIGPIPE) | \ sigmask(SIGALRM) | sigmask(SIGURG) | \ @@ -51,3 +58,4 @@ extern union interrupt_handler interrupt_handlers[NSIG]; sigmask(SIGUSR1) | sigmask(SIGUSR2)) #endif #endif +#endif