diff --git a/ldb/interrupt.c b/ldb/interrupt.c index 662e846cb78b673a4a021b3ff6720680982eaee4..f56b841812eaa9de8941f14dffd9ba810593327b 100644 --- a/ldb/interrupt.c +++ b/ldb/interrupt.c @@ -1,24 +1,24 @@ -/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/ldb/Attic/interrupt.c,v 1.27 1991/05/24 04:59:04 wlott Exp $ */ +/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/ldb/Attic/interrupt.c,v 1.28 1991/05/24 17:50:13 wlott Exp $ */ /* Interrupt handing magic. */ +#include <stdio.h> + #include <signal.h> #ifdef mips #include <mips/cpu.h> #endif -#ifdef sparc -#include <machine/trap.h> -#endif -#include "lisp.h" #include "ldb.h" + +#include "os.h" +#include "arch.h" +#include "lisp.h" #include "globals.h" #include "lispregs.h" #include "interrupt.h" #include "validate.h" -#define crap_out(msg) do { write(2, msg, sizeof(msg)); exit(1); } while (0) - #define FIXNUM_VALUE(lispobj) (((int)lispobj)>>2) boolean internal_errors_enabled = 0; @@ -26,7 +26,8 @@ boolean internal_errors_enabled = 0; struct sigcontext *lisp_interrupt_contexts[MAX_INTERRUPTS]; union interrupt_handler interrupt_handlers[NSIG]; - +void (*interrupt_low_level_handlers[NSIG])() = {0}; + static int pending_signal = 0, pending_code = 0, pending_mask = 0; static boolean maybe_gc_pending = FALSE; @@ -35,7 +36,7 @@ static boolean maybe_gc_pending = FALSE; * Utility routines used by various signal handlers. * \****************************************************************/ -static void fake_foreign_function_call(context) +void fake_foreign_function_call(context) struct sigcontext *context; { int context_index; @@ -106,7 +107,7 @@ static void fake_foreign_function_call(context) foreign_function_call_active = 1; } -static void undo_fake_foreign_function_call(context) +void undo_fake_foreign_function_call(context) struct sigcontext *context; { /* Block all blockable signals */ @@ -130,34 +131,7 @@ static void undo_fake_foreign_function_call(context) call_into_lisp(MAYBE_GC, SymbolFunction(MAYBE_GC), \ current_control_stack_pointer, 0) -static void skip_instruction(context) - struct sigcontext *context; -{ -#ifdef mips - /* Skip the offending instruction */ - if (context->sc_cause & CAUSE_BD) - emulate_branch(context, *(unsigned long *)context->sc_pc); - else - context->sc_pc += 4; -#endif -#ifdef sparc - context->sc_pc = context->sc_npc; - context->sc_npc += 4; -#endif -#ifdef ibmrt - unsigned long pc = context->sc_iar; - unsigned long prev_inst = ((unsigned long *)pc)[-1]; - - if ((prev_inst >> 24) == 0x89) { - short offset = prev_inst & 0xffff; - context->sc_pc = pc - 4 + offset; - } - else - context->sc_pc = pc + 4; -#endif -} - -static void internal_error(signal, code, context, continuable) +void interrupt_internal_error(signal, code, context, continuable) struct sigcontext *context; boolean continuable; { @@ -177,13 +151,13 @@ static void internal_error(signal, code, context, continuable) args, 2); undo_fake_foreign_function_call(context); if (continuable) - skip_instruction(context); + arch_skip_instruction(context); } else - handle_now(signal, code, context); + interrupt_handle_now(signal, code, context); } -static void handle_pending_interrupt(context) +void interrupt_handle_pending(context) struct sigcontext *context; { if (foreign_function_call_active) @@ -208,20 +182,20 @@ static void handle_pending_interrupt(context) code = pending_code; pending_signal = 0; pending_code = 0; - handle_now(signal, code, context); + interrupt_handle_now(signal, code, context); } context->sc_mask = pending_mask; pending_mask = 0; - skip_instruction(context); + arch_skip_instruction(context); } /****************************************************************\ -* handle_now, maybe_now_maybe_later * +* interrupt_handle_now, maybe_now_maybe_later * * the two main signal handlers. * \****************************************************************/ -static handle_now(signal, code, context) +void interrupt_handle_now(signal, code, context) int signal, code; struct sigcontext *context; { @@ -231,20 +205,25 @@ struct sigcontext *context; lispobj callname, function; handler = interrupt_handlers[signal]; - were_in_lisp = !foreign_function_call_active; - - if (handler.c == SIG_DFL || handler.c == SIG_IGN) - /* This can happen if someone tries to ignore or default on of the */ - /* signals we need for runtime support. */ + + if(handler.c==SIG_IGN) return; + were_in_lisp = !foreign_function_call_active; if (were_in_lisp) fake_foreign_function_call(context); /* Allow signals again. */ sigsetmask(context->sc_mask); - if (LowtagOf(handler.lisp) == type_EvenFixnum || + if(handler.c==SIG_DFL){ + /* This can happen if someone tries to ignore or default on of the */ + /* signals we need for runtime support. */ + fprintf(stderr,"interrupt_handle_now: No handler for signal %d?\n",signal); + printf("[exit debugger to continue]\n"); + ldb_monitor(); + } + else if (LowtagOf(handler.lisp) == type_EvenFixnum || LowtagOf(handler.lisp) == type_OddFixnum) (*handler.c)(signal, code, context); else { @@ -265,7 +244,7 @@ struct sigcontext *context; undo_fake_foreign_function_call(context); } -static maybe_now_maybe_later(signal, code, context) +static void maybe_now_maybe_later(signal, code, context) int signal, code; struct sigcontext *context; { @@ -292,249 +271,9 @@ struct sigcontext *context; SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, T); #endif } else - handle_now(signal, code, context); + interrupt_handle_now(signal, code, context); } -/****************************************************************\ -* PMAX specific signal handlers. * -\****************************************************************/ - -#ifdef mips -static sigtrap_handler(signal, code, context) - int signal, code; - struct sigcontext *context; -{ - switch (code) { - case trap_PendingInterrupt: - handle_pending_interrupt(context); - break; - - case trap_Halt: - crap_out("%primitive halt called; the party is over.\n"); - - case trap_Error: - case trap_Cerror: - internal_error(signal, code, context, code==trap_Cerror); - break; - - case trap_Breakpoint: - sigsetmask(context->sc_mask); - fake_foreign_function_call(context); - handle_breakpoint(signal, code, context); - undo_fake_foreign_function_call(context); - break; - - default: - handle_now(signal, code, context); - break; - } -} - -static sigfpe_handler(signal, code, context) -int signal, code; -struct sigcontext *context; -{ - unsigned long bad_inst; - unsigned int op, rs, rt, rd, funct, dest; - int immed; - long result; - - if (context->sc_cause & CAUSE_BD) - bad_inst = *(unsigned long *)(context->sc_pc + 4); - else - bad_inst = *(unsigned long *)(context->sc_pc); - - op = (bad_inst >> 26) & 0x3f; - rs = (bad_inst >> 21) & 0x1f; - rt = (bad_inst >> 16) & 0x1f; - rd = (bad_inst >> 11) & 0x1f; - funct = bad_inst & 0x3f; - immed = (((int)(bad_inst & 0xffff)) << 16) >> 16; - - switch (op) { - case 0x0: /* SPECIAL */ - switch (funct) { - case 0x20: /* ADD */ - result = FIXNUM_VALUE(context->sc_regs[rs]) + FIXNUM_VALUE(context->sc_regs[rt]); - dest = rd; - break; - - case 0x22: /* SUB */ - result = FIXNUM_VALUE(context->sc_regs[rs]) - FIXNUM_VALUE(context->sc_regs[rt]); - dest = rd; - break; - - default: - dest = 32; - break; - } - break; - - case 0x8: /* ADDI */ - result = FIXNUM_VALUE(context->sc_regs[rs]) + (immed>>2); - dest = rt; - break; - - default: - dest = 32; - break; - } - - if (dest < 32) { - set_global_pointer(saved_global_pointer); - current_dynamic_space_free_pointer = - (lispobj *) context->sc_regs[ALLOC]; - - context->sc_regs[dest] = alloc_number(result); - - context->sc_regs[ALLOC] = - (unsigned long) current_dynamic_space_free_pointer; - - skip_instruction(context); - - } - else - handle_now(signal, code, context); -} -#endif - -/****************************************************************\ -* SPARC specific signal handlers. * -\****************************************************************/ - -#ifdef sparc -static sigill_handler(signal, code, context) -int signal, code; -struct sigcontext *context; -{ - int badinst; - - if (code == T_UNIMP_INSTR) { - int trap; - - trap = *(unsigned long *)(context->sc_pc) & 0x3fffff; - - switch (trap) { - case trap_PendingInterrupt: - handle_pending_interrupt(context); - break; - - case trap_Halt: - crap_out("%primitive halt called; the party is over.\n"); - - case trap_Error: - case trap_Cerror: - internal_error(signal, code, context, trap == trap_Cerror); - break; - - default: - handle_now(signal, code, context); - break; - } - } - else if (code >= T_SOFTWARE_TRAP + 16 & code < T_SOFTWARE_TRAP + 32) - internal_error(signal, code, context, FALSE); - else - handle_now(signal, code, context); -} - -static sigemt_handler(signal, code, context) - int signal, code; - struct sigcontext *context; -{ - unsigned long badinst; - boolean subtract, immed; - int rd, rs1, op1, rs2, op2, result; - - badinst = *(unsigned long *)context->sc_pc; - if ((badinst >> 30) != 2 || ((badinst >> 20) & 0x1f) != 0x11) { - /* It wasn't a tagged add. Pass the signal into lisp. */ - handle_now(signal, code, context); - return; - } - - /* Extract the parts of the inst. */ - subtract = badinst & (1<<19); - rs1 = (badinst>>14) & 0x1f; - op1 = context->sc_regs[rs1]; - if ((op1 & 3) != 0) { - /* The first arg wan't a fixnum. */ - internal_error(signal, code, context, FALSE); - return; - } - - if (immed = badinst & (1<<13)) { - op2 = badinst & 0x1fff; - if (op2 & (1<<12)) - op2 |= -1<<13; - } - else { - rs2 = badinst & 0x1f; - op2 = context->sc_regs[rs2]; - } - - if ((op2 & 3) != 0) { - /* The second arg wan't a fixnum. */ - internal_error(signal, code, context, FALSE); - return; - } - - rd = (badinst>>25) & 0x1f; - if (rd != 0) { - /* Don't bother computing the result unless we are going to use it. */ - if (subtract) - result = (op1>>2) - (op2>>2); - else - result = (op1>>2) + (op2>>2); - - current_dynamic_space_free_pointer = - (lispobj *) context->sc_regs[ALLOC]; - - context->sc_regs[rd] = alloc_number(result); - - context->sc_regs[ALLOC] = - (unsigned long) current_dynamic_space_free_pointer; - } - skip_instruction(context); -} -#endif - -/****************************************************************\ -* RT Specific Signal Handlers * -\****************************************************************/ - -#ifdef ibmrt -static sigtrap_handler(signal, code, context) - int signal, code; - struct sigcontext *context; -{ - switch (*((unsigned short *)context->sc_iar+1)) { - case trap_PendingInterrupt: - handle_pending_interrupt(context); - break; - - case trap_Halt: - crap_out("%primitive halt called; the party is over.\n"); - - case trap_Error: - case trap_Cerror: - internal_error(signal, code, context, code==trap_Cerror); - break; - - case trap_Breakpoint: - sigsetmask(context->sc_mask); - fake_foreign_function_call(context); - handle_breakpoint(signal, code, context); - undo_fake_foreign_function_call(context); - break; - - default: - handle_now(signal, code, context); - break; - } -} -#endif - /****************************************************************\ * Stuff to detect and handle hitting the gc trigger. * \****************************************************************/ @@ -542,78 +281,18 @@ static sigtrap_handler(signal, code, context) static boolean gc_trigger_hit(context) struct sigcontext *context; { - lispobj *badaddr; -#ifdef sparc - unsigned long badinst; - int rs1; -#endif if (current_auto_gc_trigger == NULL) return FALSE; + else{ + lispobj *badaddr=(lispobj *)arch_get_bad_addr(context); -#ifdef mips - /* Finding the bad address on the mips is easy. */ - badaddr = (lispobj *)context->sc_badvaddr; -#endif - -#ifdef sparc - /* On the sparc, we have to decode the instruction. */ - - /* Make sure it's not the pc thats bogus, and that it was lisp code */ - /* that caused the fault. */ - if ((context->sc_pc & 3) != 0 || - ((context->sc_pc < READ_ONLY_SPACE_START || - context->sc_pc >= READ_ONLY_SPACE_START+READ_ONLY_SPACE_SIZE) && - ((lispobj *)context->sc_pc < current_dynamic_space && - (lispobj *)context->sc_pc >= - current_dynamic_space + DYNAMIC_SPACE_SIZE))) - return FALSE; - - badinst = *(unsigned long *)context->sc_pc; - - if ((badinst >> 30) != 3) - /* All load/store instructions have op = 11 (binary) */ - return FALSE; - - rs1 = (badinst>>14)&0x1f; - - if (badinst & (1<<13)) { - /* r[rs1] + simm(13) */ - int simm13 = badinst & 0x1fff; - - if (simm13 & (1<<12)) - simm13 |= -1<<13; - - badaddr = (lispobj *)(context->sc_regs[rs1] + simm13); + return (badaddr >= current_auto_gc_trigger && + badaddr < current_dynamic_space + DYNAMIC_SPACE_SIZE); } - else { - /* r[rs1] + r[rs2] */ - int rs2 = badinst & 0x1f; - - badaddr = (lispobj *)(context->sc_regs[rs1] + context->sc_regs[rs2]); - } -#endif - -#ifdef ibmrt - if (!SymbolValue(PSEUDO_ATOMIC_ATOMIC)) - /* If we are not pseudo-atomic, then we could only have hit the */ - /* trigger if the allocation pointer points beyond the trigger. */ - badaddr = (lispobj *)SymbolValue(ALLOCATION_POINTER); - else - /* Otherwise, we might be inside an allocator. The best we can do */ - /* is to try turning off the trigger and seeing if the problem goes */ - /* away. If it does, then we guessed right. If it doesn't, we will */ - /* end up back here, except current_auto_gc_trigger will be NULL, */ - /* so we will take the sigbus at that time. */ - return TRUE; -#endif - - return (badaddr >= current_auto_gc_trigger && - badaddr < current_dynamic_space + DYNAMIC_SPACE_SIZE); } -static sigbus_handler(signal, code, context) -int signal, code; +boolean interrupt_maybe_gc(context) struct sigcontext *context; { if (!foreign_function_call_active && gc_trigger_hit(context)) { @@ -645,59 +324,57 @@ struct sigcontext *context; call_maybe_gc(); undo_fake_foreign_function_call(context); } - } - else - handle_now(signal, code, context); + + return TRUE; + }else + return FALSE; } /****************************************************************\ * Noise to install handlers. * \****************************************************************/ +void interrupt_install_low_level_handler(signal,handler) +int signal; +void (*handler)(); +{ + struct sigvec sv; + + sv.sv_handler=handler; + sv.sv_mask=BLOCKABLE; + sv.sv_flags=0; + + sigvec(signal,&sv,NULL); + + interrupt_low_level_handlers[signal]=(handler==SIG_DFL ? 0 : handler); +} + unsigned long install_handler(signal, handler) int signal; -int (*handler)(); +void (*handler)(); { struct sigvec sv; int oldmask; union interrupt_handler oldhandler; -#ifdef mips - if (signal == SIGTRAP) - sv.sv_handler = sigtrap_handler; - else if (signal == SIGFPE) - sv.sv_handler = sigfpe_handler; - else if (signal == SIGBUS || signal == SIGSEGV) - sv.sv_handler = sigbus_handler; -#endif -#ifdef sparc - if (signal == SIGILL) - sv.sv_handler = sigill_handler; - else if (signal == SIGEMT) - sv.sv_handler = sigemt_handler; - else if (signal == SIGBUS) - sv.sv_handler = sigbus_handler; -#endif -#ifdef ibmrt - if (signal == SIGTRAP) - sv.sv_handler = sigtrap_handler; - else if (signal == SIGBUS) - sv.sv_handler = sigbus_handler; -#endif - else if (handler == SIG_DFL || handler == SIG_IGN) - sv.sv_handler = handler; - else if (sigmask(signal)&BLOCKABLE) - sv.sv_handler = maybe_now_maybe_later; - else - sv.sv_handler = handle_now; - sv.sv_mask = BLOCKABLE; - sv.sv_flags = 0; - oldmask = sigblock(sigmask(signal)); + if(interrupt_low_level_handlers[signal]==0){ + if(handler==SIG_DFL || handler==SIG_IGN) + sv.sv_handler=handler; + else if (sigmask(signal)&BLOCKABLE) + sv.sv_handler = maybe_now_maybe_later; + else + sv.sv_handler = interrupt_handle_now; + + sv.sv_mask = BLOCKABLE; + sv.sv_flags = 0; + + sigvec(signal, &sv, NULL); + } + oldhandler = interrupt_handlers[signal]; interrupt_handlers[signal].c = handler; - sigvec(signal, &sv, NULL); sigsetmask(oldmask);