Skip to content
interrupt.c 18.3 KiB
Newer Older
/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.c,v 1.44 2006/11/07 11:24:12 cshapiro Exp $ */
wlott's avatar
wlott committed

/* Interrupt handling magic. */
wlott's avatar
wlott committed

#include <stdio.h>
emarsden's avatar
 
emarsden committed
#include <unistd.h>
#include <stdlib.h>
wlott's avatar
wlott committed
#include <signal.h>
emarsden's avatar
 
emarsden committed
#include <assert.h>
wlott's avatar
wlott committed

#include "lisp.h"
ram's avatar
ram committed
#include "arch.h"
wlott's avatar
wlott committed
#include "internals.h"
#include "os.h"
ram's avatar
ram committed
#include "interrupt.h"
wlott's avatar
wlott committed
#include "globals.h"
#include "lispregs.h"
#include "validate.h"
#include "monitor.h"
#include "gc.h"
#include "alloc.h"
#include "dynbind.h"
#include "interr.h"

boolean internal_errors_enabled = 0;

os_context_t *lisp_interrupt_contexts[MAX_INTERRUPTS];
wlott's avatar
wlott committed

union interrupt_handler interrupt_handlers[NSIG];
void (*interrupt_low_level_handlers[NSIG]) (HANDLER_ARGS) = {
0};
ram's avatar
ram committed

static int pending_signal = 0;

#if defined(SOLARIS) || defined(__OpenBSD__) || defined(__NetBSD__)
ram's avatar
ram committed
static siginfo_t *pending_code;
ram's avatar
ram committed
#define PASSCODE(code) ((code))
#define DEREFCODE(code) ((code))
#else
static int pending_code = 0;
ram's avatar
ram committed
#define PASSCODE(code) (code)
#define DEREFCODE(code) (code)
#endif
wlott's avatar
wlott committed

ram's avatar
ram committed
#ifdef POSIX_SIGS
static sigset_t pending_mask;
#else
static int pending_mask = 0;
#endif
wlott's avatar
wlott committed
static boolean maybe_gc_pending = FALSE;


/****************************************************************\
* Utility routines used by various signal handlers.              *
\****************************************************************/

build_fake_control_stack_frame(os_context_t * context)
cwang's avatar
cwang committed
#if !(defined(i386) || defined(__x86_64))
    lispobj oldcont;

    /* Build a fake stack frame */
    current_control_frame_pointer = (lispobj *) SC_REG(context, reg_CSP);
    if ((lispobj *) SC_REG(context, reg_CFP) == current_control_frame_pointer) {
	/* There is a small window during call where the callee's frame */
	/* isn't built yet. */
	if (LowtagOf(SC_REG(context, reg_CODE)) == type_FunctionPointer) {
	    /* We have called, but not built the new frame, so
	       build it for them. */
	    current_control_frame_pointer[0] = SC_REG(context, reg_OCFP);
	    current_control_frame_pointer[1] = SC_REG(context, reg_LRA);
	    current_control_frame_pointer += 8;
	    /* Build our frame on top of it. */
	    oldcont = (lispobj) SC_REG(context, reg_CFP);
	} else {
	    /* We haven't yet called, build our frame as if the
	       partial frame wasn't there. */
	    oldcont = (lispobj) SC_REG(context, reg_OCFP);
	}
    /* ### We can't tell if we are still in the caller if it had to
       reg_ALLOCate the stack frame due to stack arguments. */
    /* ### Can anything strange happen during return? */

	/* Normal case. */
	oldcont = (lispobj) SC_REG(context, reg_CFP);

    current_control_stack_pointer = current_control_frame_pointer + 8;

    current_control_frame_pointer[0] = oldcont;
    current_control_frame_pointer[1] = NIL;
    current_control_frame_pointer[2] = (lispobj) SC_REG(context, reg_CODE);
void
fake_foreign_function_call(os_context_t * context)
wlott's avatar
wlott committed
{
    int context_index;
pw's avatar
pw committed

wlott's avatar
wlott committed
    /* Get current LISP state from context */
#ifdef reg_ALLOC
    current_dynamic_space_free_pointer = (lispobj *) SC_REG(context, reg_ALLOC);
hallgren's avatar
hallgren committed
#ifdef alpha
    if ((long) current_dynamic_space_free_pointer & 1) {
	printf("Dead in fake_foriegn_function-call, context = %x\n", context);
	lose("");
hallgren's avatar
hallgren committed
    }
#endif
wlott's avatar
wlott committed
#endif
#ifdef reg_BSP
    current_binding_stack_pointer = (lispobj *) SC_REG(context, reg_BSP);
wlott's avatar
wlott committed
#endif
    build_fake_control_stack_frame(context);
wlott's avatar
wlott committed
    /* Do dynamic binding of the active interrupt context index
       and save the context in the context array. */
    context_index = SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX) >> 2;

wlott's avatar
wlott committed
    if (context_index >= MAX_INTERRUPTS) {
wlott's avatar
wlott committed
		"Maximum number (%d) of interrupts exceeded.  Exiting.\n",
		MAX_INTERRUPTS);
	exit(1);
wlott's avatar
wlott committed
    }

    bind_variable(FREE_INTERRUPT_CONTEXT_INDEX, make_fixnum(context_index + 1));

wlott's avatar
wlott committed
    lisp_interrupt_contexts[context_index] = context;
wlott's avatar
wlott committed
    /* No longer in Lisp now. */
    foreign_function_call_active = 1;
}

void
undo_fake_foreign_function_call(os_context_t * context)
wlott's avatar
wlott committed
{
    /* Block all blockable signals */
ram's avatar
ram committed
#ifdef POSIX_SIGS
    sigset_t block;
ram's avatar
ram committed
    sigemptyset(&block);
    FILLBLOCKSET(&block);
    sigprocmask(SIG_BLOCK, &block, 0);
#else
wlott's avatar
wlott committed
    sigblock(BLOCKABLE);
ram's avatar
ram committed
#endif
wlott's avatar
wlott committed
    /* Going back into lisp. */
    foreign_function_call_active = 0;
wlott's avatar
wlott committed
    /* Undo dynamic binding. */
    /* ### Do I really need to unbind_to_here()? */
    unbind();
wlott's avatar
wlott committed
#ifdef reg_ALLOC
    /* Put the dynamic space free pointer back into the context. */
    SC_REG(context, reg_ALLOC) =
	(unsigned long) current_dynamic_space_free_pointer;
wlott's avatar
wlott committed
#endif
}

interrupt_internal_error(HANDLER_ARGS, boolean continuable)
wlott's avatar
wlott committed
{
rtoy's avatar
rtoy committed
    lispobj context_sap = NIL;
cwang's avatar
cwang committed
#if ( defined( __linux__ ) && (defined( i386 ) || defined( __x86_64 ) ) )
ram's avatar
ram committed
#endif
	fake_foreign_function_call(context);
    /* Allocate the SAP object while the interrupts are still disabled. */
    if (internal_errors_enabled)
	context_sap = alloc_sap(context);
ram's avatar
ram committed
#ifdef POSIX_SIGS
#if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
    sigprocmask(SIG_SETMASK, &context->uc_sigmask, 0);
	sigset_t temp;

	sigemptyset(&temp);
	temp.__val[0] = context->uc_sigmask;
	sigprocmask(SIG_SETMASK, &temp, 0);
ram's avatar
ram committed
#else
wlott's avatar
wlott committed
    sigsetmask(context->sc_mask);
#endif /* POSIX_SIGS */
    if (internal_errors_enabled)
	funcall2(SymbolFunction(INTERNAL_ERROR), context_sap,
wlott's avatar
wlott committed
		 continuable ? T : NIL);
    else
	internal_error(context);
    undo_fake_foreign_function_call(context);
    if (continuable)
	arch_skip_instruction(context);
}

void
interrupt_handle_pending(os_context_t * context)
wlott's avatar
wlott committed
{
    boolean were_in_lisp = !foreign_function_call_active;

    SetSymbolValue(INTERRUPT_PENDING, NIL);

    if (maybe_gc_pending) {
	maybe_gc_pending = FALSE;
wlott's avatar
wlott committed
	if (were_in_lisp)
wlott's avatar
wlott committed
	    fake_foreign_function_call(context);
	funcall0(SymbolFunction(MAYBE_GC));
wlott's avatar
wlott committed
	if (were_in_lisp)
wlott's avatar
wlott committed
	    undo_fake_foreign_function_call(context);
    }
#if  !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
    context->uc_sigmask = pending_mask;
#else
    context->uc_sigmask = pending_mask.__val[0];
#endif
    sigemptyset(&pending_mask);
#else
    context->sc_mask = pending_mask;
    pending_mask = 0;
#endif /* POSIX_SIGS */
wlott's avatar
wlott committed
    if (pending_signal) {
ram's avatar
ram committed
	int signal;
#if defined(SOLARIS) || defined(__OpenBSD__) || defined(__NetBSD__)
ram's avatar
ram committed
	siginfo_t *code;
#else
	int code;
#endif
wlott's avatar
wlott committed
	signal = pending_signal;
	code = pending_code;
	pending_signal = 0;
ram's avatar
ram committed
	/* pending_code = 0; */
cwang's avatar
cwang committed
#if ( defined( __linux__ ) && ( defined( i386 ) || defined ( __x86_64 ) ) )
	interrupt_handle_now(signal, *context);
ram's avatar
ram committed
#else
ram's avatar
ram committed
	interrupt_handle_now(signal, PASSCODE(code), context);
ram's avatar
ram committed
#endif
wlott's avatar
wlott committed
    }
}


/****************************************************************\
* interrupt_handle_now_handler, maybe_now_maybe_later            *
wlott's avatar
wlott committed
*    the two main signal handlers.                               *
* interrupt_handle_now                                           *
*    is called from those to do the real work, but isn't itself  *
*    a handler.                                                  *
wlott's avatar
wlott committed
\****************************************************************/

interrupt_handle_now_handler(HANDLER_ARGS)
{
#if defined(__linux__) && (defined(i386) || defined(__x86_64))
    interrupt_handle_now(signal, contextstruct);
    interrupt_handle_now(signal, code, context);
    /* Work around G5 bug; fix courtesy gbyers via chandler */
ram's avatar
ram committed
interrupt_handle_now(HANDLER_ARGS)
wlott's avatar
wlott committed
{
cwang's avatar
cwang committed
#if defined(__linux__) && (defined(i386) || defined(__x86_64))
ram's avatar
ram committed
#endif
wlott's avatar
wlott committed
    int were_in_lisp;
    union interrupt_handler handler;
ram's avatar
ram committed

cwang's avatar
cwang committed
#if defined(__linux__) && ( defined(i386) || defined(__x86_64) )
    /*
     * Restore the FPU control word, setting the rounding mode to nearest.
     */

cwang's avatar
cwang committed
#if defined(__x86_64)
	setfpucw(contextstruct.fpstate->cwd & ~0xc00);
cwang's avatar
cwang committed
#else
	setfpucw(contextstruct.fpstate->cw & ~0xc00);
cwang's avatar
cwang committed
#endif
wlott's avatar
wlott committed
    handler = interrupt_handlers[signal];

    if (handler.c == (void (*)(HANDLER_ARGS)) SIG_IGN)
wlott's avatar
wlott committed
	return;

    SAVE_CONTEXT();
    /**/ were_in_lisp = !foreign_function_call_active;
cwang's avatar
cwang committed
#if ! (defined(i386) || defined(_x86_64))
wlott's avatar
wlott committed
    if (were_in_lisp)
	fake_foreign_function_call(context);

    if (handler.c == (void (*)(HANDLER_ARGS)) SIG_DFL)
cwang's avatar
cwang committed
	/* This can happen if someone tries to ignore or default on one of the */
wlott's avatar
wlott committed
	/* signals we need for runtime support, and the runtime support */
	/* decides to pass on it.  */
	lose("interrupt_handle_now: No handler for signal %d?\n", signal);
    else if (LowtagOf(handler.lisp) == type_FunctionPointer) {
	/* Allocate the SAP object while the interrupts are still
	   disabled. */
	lispobj context_sap = alloc_sap(context);
	/* Allow signals again. */
#if  !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
	sigprocmask(SIG_SETMASK, &context->uc_sigmask, 0);
	    sigset_t temp;

	    sigemptyset(&temp);
	    temp.__val[0] = context->uc_sigmask;
	    sigprocmask(SIG_SETMASK, &temp, 0);
	sigsetmask(context->sc_mask);
#endif /* POSIX_SIGS */
ram's avatar
ram committed
#if 1
	funcall3(handler.lisp, make_fixnum(signal), make_fixnum(CODE(code)),
ram's avatar
ram committed
#else
	funcall3(handler.lisp, make_fixnum(signal), alloc_sap(code),
ram's avatar
ram committed
#endif
	/* Allow signals again. */
#if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
	sigprocmask(SIG_SETMASK, &context->uc_sigmask, 0);
	    sigset_t temp;

	    sigemptyset(&temp);
	    temp.__val[0] = context->uc_sigmask;
	    sigprocmask(SIG_SETMASK, &temp, 0);
	sigsetmask(context->sc_mask);
#endif /* POSIX_SIGS */
cwang's avatar
cwang committed
#if ( defined( __linux__ ) && ( defined( i386 ) || defined ( __x86_64 ) ) )
	(*handler.c) (signal, contextstruct);
ram's avatar
ram committed
#else
	(*handler.c) (signal, code, context);
ram's avatar
ram committed
#endif
cwang's avatar
cwang committed
#if !(defined(i386) || defined(__x86_64))
wlott's avatar
wlott committed
    if (were_in_lisp)
	undo_fake_foreign_function_call(context);
wlott's avatar
wlott committed
}

ram's avatar
ram committed
maybe_now_maybe_later(HANDLER_ARGS)
wlott's avatar
wlott committed
{
cwang's avatar
cwang committed
#if defined(__linux__) && (defined(i386) || defined(__x86_64))
ram's avatar
ram committed
#endif
	SAVE_CONTEXT();
    /**/ if (SymbolValue(INTERRUPTS_ENABLED) == NIL) {
	pending_signal = signal;
	pending_code = DEREFCODE(code);
ram's avatar
ram committed
#ifdef POSIX_SIGS
#if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
	pending_mask = context->uc_sigmask;
ram's avatar
ram committed
	FILLBLOCKSET(&context->uc_sigmask);
	    sigset_t temp;

	    sigemptyset(&temp);
	    pending_mask.__val[0] = context->uc_sigmask;
	    temp.__val[0] = context->uc_sigmask;
	    FILLBLOCKSET(&temp);

	    context->uc_sigmask = temp.__val[0];
ram's avatar
ram committed
#else
	pending_mask = context->sc_mask;
	context->sc_mask |= BLOCKABLE;
#endif /* POSIX_SIGS */

	SetSymbolValue(INTERRUPT_PENDING, T);
cwang's avatar
cwang committed
#if !(defined(i386) || defined(__x86_64))
		  (!foreign_function_call_active) &&
		  arch_pseudo_atomic_atomic(context)) {
	pending_signal = signal;
	pending_code = DEREFCODE(code);
ram's avatar
ram committed
#ifdef POSIX_SIGS
#if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
	pending_mask = context->uc_sigmask;
ram's avatar
ram committed
	FILLBLOCKSET(&context->uc_sigmask);
	    sigset_t temp;

	    sigemptyset(&temp);
	    pending_mask.__val[0] = context->uc_sigmask;
	    temp.__val[0] = context->uc_sigmask;
	    FILLBLOCKSET(&temp);
	    context->uc_sigmask = temp.__val[0];
ram's avatar
ram committed
#else
	pending_mask = context->sc_mask;
	context->sc_mask |= BLOCKABLE;
#endif /* POSIX_SIGS */

wlott's avatar
wlott committed
	arch_set_pseudo_atomic_interrupted(context);
cwang's avatar
cwang committed
#if defined(__linux__) && (defined(i386) || defined(__x86_64))
	/*
	 * Restore the FPU control word, setting the rounding mode to nearest.
	 */
	if (contextstruct.fpstate)
cwang's avatar
cwang committed
#if defined(__x86_64)
	    setfpucw(contextstruct.fpstate->cwd & ~0xc00);
cwang's avatar
cwang committed
#else
	    setfpucw(contextstruct.fpstate->cw & ~0xc00);
cwang's avatar
cwang committed
#endif
cwang's avatar
cwang committed
#if ( defined( __linux__ ) && ( defined( i386 ) || defined( __x86_64 ) ) )
	interrupt_handle_now(signal, contextstruct);
ram's avatar
ram committed
#else
	interrupt_handle_now(signal, code, context);
ram's avatar
ram committed
#endif

#ifdef DARWIN
    /* Work around G5 bug; fix courtesy gbyers via chandler */
    sigreturn(context);
#endif
wlott's avatar
wlott committed
}

/****************************************************************\
* Stuff to detect and handle hitting the gc trigger.             *
\****************************************************************/

#ifndef INTERNAL_GC_TRIGGER
static boolean
gc_trigger_hit(HANDLER_ARGS)
wlott's avatar
wlott committed
{
emarsden's avatar
 
emarsden committed
    if (current_auto_gc_trigger == NULL) {
wlott's avatar
wlott committed
	return FALSE;
emarsden's avatar
 
emarsden committed
    } else {
	lispobj *badaddr = (lispobj *) arch_get_bad_addr(signal, code, context);
wlott's avatar
wlott committed

emarsden's avatar
 
emarsden committed
#ifdef PRINTNOISE
	fprintf(stderr,
		"gc_trigger_hit: badaddr=%p, current_auto_gc_trigger=%p, limit=%p\n",
		badaddr, current_auto_gc_trigger,
		current_dynamic_space + dynamic_space_size);
emarsden's avatar
 
emarsden committed
#endif
wlott's avatar
wlott committed
	return (badaddr >= current_auto_gc_trigger &&
		(unsigned long) badaddr <
		(unsigned long) current_dynamic_space +
		(unsigned long) dynamic_space_size);
wlott's avatar
wlott committed
    }
}
#endif

cwang's avatar
cwang committed
#if !(defined(i386) || defined(__x86_64))
boolean
interrupt_maybe_gc(HANDLER_ARGS)
wlott's avatar
wlott committed
{
    if (!foreign_function_call_active
#ifndef INTERNAL_GC_TRIGGER
	&& gc_trigger_hit(signal, code, context)
wlott's avatar
wlott committed
#endif
	) {
#ifndef INTERNAL_GC_TRIGGER
	clear_auto_gc_trigger();
#endif

	if (arch_pseudo_atomic_atomic(context)) {
	    maybe_gc_pending = TRUE;
	    if (pending_signal == 0) {
ram's avatar
ram committed
#ifdef POSIX_SIGS
pw's avatar
pw committed
#if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
		pending_mask = context->uc_sigmask;
ram's avatar
ram committed
		FILLBLOCKSET(&context->uc_sigmask);
pw's avatar
pw committed
#else
		{
		    sigset_t temp;

		    sigemptyset(&temp);
		    pending_mask.__val[0] = context->uc_sigmask;
		    temp.__val[0] = context->uc_sigmask;
		    FILLBLOCKSET(&temp);
		    context->uc_sigmask = temp.__val[0];
pw's avatar
pw committed
		}
#endif
ram's avatar
ram committed
#else
wlott's avatar
wlott committed
		pending_mask = context->sc_mask;
		context->sc_mask |= BLOCKABLE;
#endif /* POSIX_SIGS */
wlott's avatar
wlott committed
	    }
	    arch_set_pseudo_atomic_interrupted(context);
wlott's avatar
wlott committed
	    fake_foreign_function_call(context);
	    funcall0(SymbolFunction(MAYBE_GC));
	    undo_fake_foreign_function_call(context);
	}

	return TRUE;
    } else
wlott's avatar
wlott committed
	return FALSE;
}
wlott's avatar
wlott committed
/****************************************************************\
* Noise to install handlers.                                     *
\****************************************************************/

cwang's avatar
cwang committed
#if !(defined(i386) || defined(__x86_64))
#define SIGNAL_STACK_SIZE SIGSTKSZ
static char altstack[SIGNAL_STACK_SIZE];
#endif

interrupt_install_low_level_handler(int signal, void handler(HANDLER_ARGS))
wlott's avatar
wlott committed
{
ram's avatar
ram committed
#ifdef POSIX_SIGS
    struct sigaction sa;

    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    FILLBLOCKSET(&sa.sa_mask);
    sa.sa_flags = SA_RESTART | USE_SA_SIGINFO;

    /* Deliver protection violations on a dedicated signal stack,
       because, when we get that signal because of hitting a control
       stack guard zone, it's not a good idea to use more of the
       control stack for handling the signal.  */
    /* But we only need this on x86 since the Lisp control stack and the
       C control stack are the same.  For others, they're separate so
       the C stack can still be used.  */
    if (signal == PROTECTION_VIOLATION_SIGNAL) {
	stack_t sigstack;

#if (defined( i386 ) || defined(__x86_64))
	sigstack.ss_sp = (void *) SIGNAL_STACK_START;
	sigstack.ss_sp = (void *) altstack;
	sigstack.ss_flags = 0;
	sigstack.ss_size = SIGNAL_STACK_SIZE;
	if (sigaltstack(&sigstack, 0) == -1)
	    perror("sigaltstack");
	sa.sa_flags |= SA_ONSTACK;
    }
#endif /* RED_ZONE_HIT */
ram's avatar
ram committed

    sigaction(signal, &sa, NULL);

#else /* not POSIX_SIGNALS */
    sv.sv_handler = handler;
    sv.sv_mask = BLOCKABLE;
    sv.sv_flags = 0;
    sigvec(signal, &sv, NULL);
#endif /* not POSIX_SIGNALS */

    if (handler == (void (*)(HANDLER_ARGS)) SIG_DFL)
	interrupt_low_level_handlers[signal] = 0;
    else
	interrupt_low_level_handlers[signal] = handler;
wlott's avatar
wlott committed
}

unsigned long
install_handler(int signal, void handler(HANDLER_ARGS))
ram's avatar
ram committed
#ifdef POSIX_SIGS
{
    struct sigaction sa;
ram's avatar
ram committed
    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 == (void (*)(HANDLER_ARGS)) SIG_DFL
	    || handler == (void (*)(HANDLER_ARGS)) SIG_IGN)
	    sa.sa_sigaction = handler;
ram's avatar
ram committed
	else if (sigismember(&new, signal))
	    sa.sa_sigaction = maybe_now_maybe_later;
ram's avatar
ram committed
	else
	    sa.sa_sigaction = interrupt_handle_now_handler;
ram's avatar
ram committed

	sigemptyset(&sa.sa_mask);
	FILLBLOCKSET(&sa.sa_mask);
	sa.sa_flags = USE_SA_SIGINFO | SA_RESTART;
ram's avatar
ram committed

	sigaction(signal, &sa, NULL);
    }

    oldhandler = interrupt_handlers[signal];
    interrupt_handlers[signal].c = handler;

    sigprocmask(SIG_SETMASK, &old, 0);

    return (unsigned long) oldhandler.lisp;
ram's avatar
ram committed
}
#else
wlott's avatar
wlott committed
{
    struct sigvec sv;
    int oldmask;
    union interrupt_handler oldhandler;

    oldmask = sigblock(sigmask(signal));

    if (interrupt_low_level_handlers[signal] == 0) {
	if (handler == (void (*)(HANDLER_ARGS)) SIG_DFL
	    || handler == (void (*)(HANDLER_ARGS)) SIG_IGN)
wlott's avatar
wlott committed
	    sv.sv_handler = handler;
	else if (sigmask(signal) & BLOCKABLE)
wlott's avatar
wlott committed
	    sv.sv_handler = maybe_now_maybe_later;
	else
	    sv.sv_handler = interrupt_handle_now_handler;
wlott's avatar
wlott committed

	sv.sv_mask = BLOCKABLE;
	sv.sv_flags = 0;
	sigvec(signal, &sv, NULL);
    }

    oldhandler = interrupt_handlers[signal];
    interrupt_handlers[signal].c = handler;

    sigsetmask(oldmask);

    return (unsigned long) oldhandler.lisp;
wlott's avatar
wlott committed
}
ram's avatar
ram committed
#endif
wlott's avatar
wlott committed

#ifdef FEATURE_HEAP_OVERFLOW_CHECK
interrupt_handle_space_overflow(lispobj error, os_context_t * context)
#if defined(i386) || defined(__x86_64)
    SC_PC(context) = (int) ((struct function *) PTR(error))->code;
    SC_REG(context, reg_NARGS) = 0;
#elif defined(sparc)
    build_fake_control_stack_frame(context);
    /* This part should be common to all non-x86 ports */
    SC_PC(context) = (long) ((struct function *) PTR(error))->code;
    SC_NPC(context) = SC_PC(context) + 4;
    SC_REG(context, reg_NARGS) = 0;
    SC_REG(context, reg_LIP) = (long) ((struct function *) PTR(error))->code;
    SC_REG(context, reg_CFP) = (long) current_control_frame_pointer;
    /* This is sparc specific */
    SC_REG(context, reg_CODE) = ((long) PTR(error)) + type_FunctionPointer;
#else
#error interrupt_handle_space_overflow not implemented for this system
#endif
#endif /* FEATURE_HEAP_OVERFLOW_CHECK */
void
interrupt_init(void)
wlott's avatar
wlott committed
{
    int i;

    for (i = 0; i < NSIG; i++)
	interrupt_handlers[i].c = (void (*)(HANDLER_ARGS)) SIG_DFL;
wlott's avatar
wlott committed
}