* In that case, the Lisp-level handler is stored in interrupt_handlers[..]
* and interrupt_low_level_handlers[..] is cleared.
*
- * However, some signals need special handling, e.g. the SIGSEGV (for
- * Linux) or SIGBUS (for FreeBSD) used by the garbage collector to
- * detect violations of write protection, because some cases of such
- * signals (e.g. GC-related violations of write protection) are
- * handled at C level and never passed on to Lisp. For such signals,
- * we still store any Lisp-level handler in interrupt_handlers[..],
- * but for the outermost handle we use the value from
- * interrupt_low_level_handlers[..], instead of the ordinary
- * interrupt_handle_now(..) or interrupt_handle_later(..).
+ * However, some signals need special handling, e.g.
*
- * -- WHN 20000728 */
+ * o the SIGSEGV (for Linux) or SIGBUS (for FreeBSD) used by the
+ * garbage collector to detect violations of write protection,
+ * because some cases of such signals (e.g. GC-related violations of
+ * write protection) are handled at C level and never passed on to
+ * Lisp. For such signals, we still store any Lisp-level handler
+ * in interrupt_handlers[..], but for the outermost handle we use
+ * the value from interrupt_low_level_handlers[..], instead of the
+ * ordinary interrupt_handle_now(..) or interrupt_handle_later(..).
+ *
+ * o the SIGTRAP (Linux/Alpha) which Lisp code uses to handle breakpoints,
+ * pseudo-atomic sections, and some classes of error (e.g. "function
+ * not defined"). This never goes anywhere near the Lisp handlers at all.
+ * See runtime/alpha-arch.c and code/signal.lisp
+ *
+ * - WHN 20000728, dan 20010128 */
+
+
void (*interrupt_low_level_handlers[NSIG]) (int, siginfo_t*, void*) = {0};
union interrupt_handler interrupt_handlers[NSIG];
if (internal_errors_enabled) {
SHOW("in interrupt_internal_error");
+#define QSHOW 1
#if QSHOW
/* Display some rudimentary debugging information about the
* error, so that even if the Lisp error handler gets badly
}
}
+/* This function handles pending interrupts. Note that in C/kernel
+ * terms we dealt with the signal already; we just haven't decided
+ * whether to call a Lisp handler or do a GC or something like that.
+ * If it helps, you can think of pending_{signal,mask,info} as a
+ * one-element queue of signals that we have acknowledged but not
+ * processed */
+
void
interrupt_handle_pending(os_context_t *context)
{
* (FIXME: Why? This is the way it was done in CMU CL, and it
* even had the comment noting that this is the way it was
* done, but no motivation..) */
- lispobj context_sap = alloc_sap(context);
- lispobj info_sap = alloc_sap(info);
-
+ lispobj info_sap,context_sap = alloc_sap(context);
+ info_sap = alloc_sap(info);
/* Allow signals again. */
sigprocmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
* SET_FPU_CONTROL_WORD(context->__fpregs_mem.cw);
* #endif */
+ /* see comments at top of code/signal.lisp for what's going on here
+ * with INTERRUPTS_ENABLED/INTERRUPT_HANDLE_NOW
+ */
if (SymbolValue(INTERRUPTS_ENABLED) == NIL) {
/* FIXME: This code is exactly the same as the code in the
os_context_sigmask_addr(context),
sizeof(sigset_t));
sigaddset_blockable(os_context_sigmask_addr(context));
-
SetSymbolValue(INTERRUPT_PENDING, T);
} else if (
context);
return (badaddr >= current_auto_gc_trigger &&
- badaddr < DYNAMIC_SPACE_START + DYNAMIC_SPACE_SIZE);
+ badaddr < current_dynamic_space + DYNAMIC_SPACE_SIZE);
}
}
#endif
#ifndef __i386__
+/* This function gets called from the SIGSEGV (Linux) or SIGBUS (BSD)
+ * handler. Here we check whether the signal was due to treading on
+ * the mprotect()ed zone - and if so, arrange for a GC to happen.
+ */
boolean
-interrupt_maybe_gc(int signal, siginfo_t *info, os_context_t *context)
+interrupt_maybe_gc(int signal, siginfo_t *info, void *void_context)
{
+ os_context_t *context=(os_context_t *) void_context;
+
if (!foreign_function_call_active
#ifndef INTERNAL_GC_TRIGGER
&& gc_trigger_hit(signal, info, context)
#endif
if (arch_pseudo_atomic_atomic(context)) {
+ /* don't GC during an atomic operation. Instead, copy the
+ * signal mask somewhere safe. interrupt_handle_pending
+ * will detect pending_signal==0 and know to do a GC with the
+ * signal context instead of calling a Lisp-level handler */
maybe_gc_pending = 1;
if (pending_signal == 0) {
/* FIXME: This copy-pending_mask-then-sigaddset_blockable