#include "alloc.h"
#include "dynbind.h"
#include "interr.h"
+#include "genesis/simple-fun.h"
+#include "genesis/fdefn.h"
+#include "genesis/symbol.h"
+#include "genesis/static-symbols.h"
void sigaddset_blockable(sigset_t *s)
{
static siginfo_t pending_info;
static sigset_t pending_mask;
-static boolean maybe_gc_pending = 0;
+boolean maybe_gc_pending = 0;
\f
/*
* utility routines used by various signal handlers
* the two main signal handlers:
* interrupt_handle_now(..)
* maybe_now_maybe_later(..)
+ *
+ * to which we have added interrupt_handle_now_handler(..). Why?
+ * Well, mostly because the SPARC/Linux platform doesn't quite do
+ * signals the way we want them done. The third argument in the
+ * handler isn't filled in by the kernel properly, so we fix it up
+ * ourselves in the arch_os_get_context(..) function; however, we only
+ * want to do this when we first hit the handler, and not when
+ * interrupt_handle_now(..) is being called from some other handler
+ * (when the fixup will already have been done). -- CSR, 2002-07-23
*/
void
union interrupt_handler handler;
#ifdef LISP_FEATURE_LINUX
- /* Under Linux, we appear to have to restore the fpu control word
- from the context, as after the signal is delivered we appear to
- have a null fpu control word. */
+ /* Under Linux on some architectures, we appear to have to restore
+ the FPU control word from the context, as after the signal is
+ delivered we appear to have a null FPU control word. */
os_restore_fp_control(context);
#endif
handler = interrupt_handlers[signal];
static void
maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
- os_context_t *context = (os_context_t*)void_context;
+ os_context_t *context = arch_os_get_context(&void_context);
- /* FIXME: See Debian cmucl 2.4.17, and mail from DTC on the CMU CL
- * mailing list 23 Oct 1999, for changes in FPU handling at
- * interrupt time which should be ported into SBCL. Also see the
- * analogous logic at the head of interrupt_handle_now for
- * more related FIXME stuff.
- */
-
#ifdef LISP_FEATURE_LINUX
os_restore_fp_control(context);
#endif
}
}
\f
+
+void
+interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
+{
+ os_context_t *context = arch_os_get_context(&void_context);
+ interrupt_handle_now(signal, info, context);
+}
+
/*
* stuff to detect and handle hitting the GC trigger
*/
-#ifndef GENCGC /* since GENCGC has its own way to record trigger */
+#ifndef LISP_FEATURE_GENCGC
+/* since GENCGC has its own way to record trigger */
static boolean
gc_trigger_hit(int signal, siginfo_t *info, os_context_t *context)
{
{
/* note the os_context hackery here. When the signal handler returns,
* it won't go back to what it was doing ... */
- if(addr>=CONTROL_STACK_GUARD_PAGE &&
- addr<(CONTROL_STACK_GUARD_PAGE+os_vm_page_size)) {
- void *function;
+ if(addr>=(void *)CONTROL_STACK_GUARD_PAGE &&
+ addr<(void *)(CONTROL_STACK_GUARD_PAGE+os_vm_page_size)) {
+ void *fun;
+ void *code;
+
/* we hit the end of the control stack. disable protection
* temporarily so the error handler has some headroom */
protect_control_stack_guard_page(0);
- function=
- &(((struct simple_fun *)
- native_pointer(SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)))
- ->code);
+ fun = (void *)
+ native_pointer((lispobj) SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR));
+ code = &(((struct simple_fun *) fun)->code);
/* Build a stack frame showing `interrupted' so that the
* user's backtrace makes (as much) sense (as usual) */
build_fake_control_stack_frames(context);
/* signal handler will "return" to this error-causing function */
- *os_context_pc_addr(context)= function;
-#ifndef LISP_FEATURE_X86
+ *os_context_pc_addr(context) = code;
+#ifdef LISP_FEATURE_X86
+ *os_context_register_addr(context,reg_ECX) = 0;
+#else
/* this much of the calling convention is common to all
non-x86 ports */
- *os_context_register_addr(context,reg_NARGS)=0;
- *os_context_register_addr(context,reg_LIP)= function;
- *os_context_register_addr(context,reg_CFP)=
+ *os_context_register_addr(context,reg_NARGS) = 0;
+ *os_context_register_addr(context,reg_LIP) = code;
+ *os_context_register_addr(context,reg_CFP) =
current_control_frame_pointer;
+#endif
#ifdef ARCH_HAS_NPC_REGISTER
- *os_context_register_addr(context,reg_LIP)=
- 4+*os_context_pc_addr(context);
+ *os_context_npc_addr(context) =
+ 4 + *os_context_pc_addr(context);
#endif
+#ifdef LISP_FEATURE_SPARC
+ /* Bletch. This is a feature of the SPARC calling convention,
+ which sadly I'm not going to go into in large detail here,
+ as I don't know it well enough. Suffice to say that if the
+ line
+
+ (INST MOVE CODE-TN FUNCTION)
+
+ in compiler/sparc/call.lisp is changed, then this bit can
+ probably go away. -- CSR, 2002-07-24 */
+ *os_context_register_addr(context,reg_CODE) =
+ fun + FUN_POINTER_LOWTAG;
#endif
return 1;
}
else return 0;
}
-#ifndef __i386__
+#ifndef LISP_FEATURE_X86
/* This function gets called from the SIGSEGV (for e.g. Linux or
* OpenBSD) or SIGBUS (for e.g. FreeBSD) handler. Here we check
* whether the signal was due to treading on the mprotect()ed zone -
os_context_t *context=(os_context_t *) void_context;
if (!foreign_function_call_active
-#ifndef GENCGC /* since GENCGC has its own way to record trigger */
+#ifndef LISP_FEATURE_GENCGC
+ /* nb: GENCGC on non-x86? I really don't think so. This
+ * happens every time */
&& gc_trigger_hit(signal, info, context)
#endif
) {
-#ifndef GENCGC /* since GENCGC has its own way to record trigger */
+#ifndef LISP_FEATURE_GENCGC
clear_auto_gc_trigger();
#endif
} else if (sigismember(&new, signal)) {
sa.sa_sigaction = maybe_now_maybe_later;
} else {
- sa.sa_sigaction = interrupt_handle_now;
+ sa.sa_sigaction = interrupt_handle_now_handler;
}
sigemptyset(&sa.sa_mask);