}
void
-check_gc_signals_unblocked_or_lose(void)
-{
-#ifdef LISP_FEATURE_SB_THREAD
-# if !defined(LISP_FEATURE_WIN32)
- /* Get the current sigmask, by blocking the empty set. */
- sigset_t empty,current;
- sigemptyset(&empty);
- thread_sigmask(SIG_BLOCK, &empty, ¤t);
- if (sigismember(¤t, SIG_STOP_FOR_GC))
- lose("SIG_STOP_FOR_GC blocked in thread %p at a bad place\n",
- arch_os_get_current_thread());
-# if defined(SIG_RESUME_FROM_GC)
- if (sigismember(¤t, SIG_RESUME_FROM_GC))
- lose("SIG_RESUME_FROM_GC blocked in thread %p at a bad place\n",
- arch_os_get_current_thread());
-# endif
-# endif
-#endif
-}
-
-void
unblock_gc_signals(void)
{
#ifdef LISP_FEATURE_SB_THREAD
void
interrupt_handle_pending(os_context_t *context)
{
- struct thread *thread;
- struct interrupt_data *data;
+ /* There are three ways we can get here. First, if an interrupt
+ * occurs within pseudo-atomic, it will be deferred, and we'll
+ * trap to here at the end of the pseudo-atomic block. Second, if
+ * the GC (in alloc()) decides that a GC is required, it will set
+ * *GC-PENDING* and pseudo-atomic-interrupted, and alloc() is
+ * always called from within pseudo-atomic, and thus we end up
+ * here again. Third, when calling GC-ON or at the end of a
+ * WITHOUT-GCING, MAYBE-HANDLE-PENDING-GC will trap to here if
+ * there is a pending GC. */
+
+ /* Win32 only needs to handle the GC cases (for now?) */
+
+ struct thread *thread = arch_os_get_current_thread();
FSHOW_SIGNAL((stderr, "/entering interrupt_handle_pending\n"));
check_blockables_blocked_or_lose();
- thread=arch_os_get_current_thread();
- data=thread->interrupt_data;
/* If pseudo_atomic_interrupted is set then the interrupt is going
* to be handled now, ergo it's safe to clear it. */
check_blockables_blocked_or_lose();
}
+#ifndef LISP_FEATURE_WIN32
/* we may be here only to do the gc stuff, if interrupts are
* enabled run the pending handler */
if (!((SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) ||
(!foreign_function_call_active) &&
#endif
arch_pseudo_atomic_atomic(context)))) {
+ struct interrupt_data *data = thread->interrupt_data;
/* There may be no pending handler, because it was only a gc
* that had to be executed or because pseudo atomic triggered
* PSEUDO_ATOMIC_INTERRUPTED only if interrupts are enabled.*/
SetSymbolValue(INTERRUPT_PENDING, NIL,thread);
-#ifndef LISP_FEATURE_WIN32
/* restore the saved signal mask from the original signal (the
* one that interrupted us during the critical section) into the
* os_context for the signal we're currently in the handler for.
sigcopyset(os_context_sigmask_addr(context), &data->pending_mask);
sigemptyset(&data->pending_mask);
-#endif
/* This will break on sparc linux: the deferred handler really wants
* to be called with a void_context */
run_deferred_handler(data,(void *)context);
}
}
+#endif
}
\f
/*
*/
void
-interrupt_handle_now(int signal, siginfo_t *info, void *void_context)
+interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context)
{
- os_context_t *context = (os_context_t*)void_context;
-#ifndef LISP_FEATURE_SB_THREAD
+#ifdef FOREIGN_FUNCTION_CALL_FLAG
boolean were_in_lisp;
#endif
union interrupt_handler handler;
check_blockables_blocked_or_lose();
-
#ifndef LISP_FEATURE_WIN32
if (sigismember(&deferrable_sigset,signal))
check_interrupts_enabled_or_lose(context);
os_restore_fp_control(context);
#endif
-
handler = interrupt_handlers[signal];
if (ARE_SAME_HANDLER(handler.c, SIG_IGN)) {
/* Allow signals again. */
thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
#endif
-
- (*handler.c)(signal, info, void_context);
+ (*handler.c)(signal, info, context);
}
-#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
+#ifdef FOREIGN_FUNCTION_CALL_FLAG
if (were_in_lisp)
#endif
{
maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
os_context_t *context = arch_os_get_context(&void_context);
-
- struct thread *thread;
- struct interrupt_data *data;
-
- thread=arch_os_get_current_thread();
- data=thread->interrupt_data;
+ struct thread *thread = arch_os_get_current_thread();
+ struct interrupt_data *data = thread->interrupt_data;
#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
os_restore_fp_control(context);
#endif
- if(maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
- return;
- interrupt_handle_now(signal, info, context);
+ if(!maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
+ interrupt_handle_now(signal, info, context);
+
#ifdef LISP_FEATURE_DARWIN
- /* Work around G5 bug */
DARWIN_FIX_CONTEXT(context);
#endif
}
static void
-low_level_interrupt_handle_now(int signal, siginfo_t *info, void *void_context)
+low_level_interrupt_handle_now(int signal, siginfo_t *info, os_context_t *context)
{
- os_context_t *context = (os_context_t*)void_context;
-
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
- os_restore_fp_control(context);
-#endif
-
+ /* No FP control fixage needed, caller has done that. */
check_blockables_blocked_or_lose();
check_interrupts_enabled_or_lose(context);
- interrupt_low_level_handlers[signal](signal, info, void_context);
-#ifdef LISP_FEATURE_DARWIN
- /* Work around G5 bug */
- DARWIN_FIX_CONTEXT(context);
-#endif
+ interrupt_low_level_handlers[signal](signal, info, context);
+ /* No Darwin context fixage needed, caller does that. */
}
static void
low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
os_context_t *context = arch_os_get_context(&void_context);
- struct thread *thread;
- struct interrupt_data *data;
-
- thread=arch_os_get_current_thread();
- data=thread->interrupt_data;
+ struct thread *thread = arch_os_get_current_thread();
+ struct interrupt_data *data = thread->interrupt_data;
#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
os_restore_fp_control(context);
#endif
- if(maybe_defer_handler(low_level_interrupt_handle_now,data,
- signal,info,context))
- return;
- low_level_interrupt_handle_now(signal, info, context);
+ if(!maybe_defer_handler(low_level_interrupt_handle_now,data,
+ signal,info,context))
+ low_level_interrupt_handle_now(signal, info, context);
+
#ifdef LISP_FEATURE_DARWIN
- /* Work around G5 bug */
DARWIN_FIX_CONTEXT(context);
#endif
}
interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
{
os_context_t *context = arch_os_get_context(&void_context);
+#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
+ os_restore_fp_control(context);
+#endif
interrupt_handle_now(signal, info, context);
#ifdef LISP_FEATURE_DARWIN
DARWIN_FIX_CONTEXT(context);
#endif
}
-/*
- * stuff to detect and handle hitting the GC trigger
- */
-
-#ifndef LISP_FEATURE_GENCGC
-#endif
-
/* manipulate the signal context and stack such that when the handler
* returns, it will call function instead of whatever it was doing
* previously
}
#endif
+void
+unhandled_trap_error(os_context_t *context)
+{
+ lispobj context_sap;
+ fake_foreign_function_call(context);
+ context_sap = alloc_sap(context);
+#ifndef LISP_FEATURE_WIN32
+ thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
+#endif
+ funcall1(SymbolFunction(UNHANDLED_TRAP_ERROR), context_sap);
+ lose("UNHANDLED-TRAP-ERROR fell through");
+}
+
/* Common logic far trapping instructions. How we actually handle each
- * case is highly architecture dependant, but the overall shape is
+ * case is highly architecture dependent, but the overall shape is
* this. */
-boolean
-maybe_handle_trap(os_context_t *context, int trap)
+void
+handle_trap(os_context_t *context, int trap)
{
switch(trap) {
case trap_PendingInterrupt:
fake_foreign_function_call(context);
lose("%%PRIMITIVE HALT called; the party is over.\n");
default:
- FSHOW((stderr,"/[C--trap default %d %d %x]\n",
- signal, trap, context));
- /* Not our trap! */
- return 0;
+ unhandled_trap_error(context);
}
- return 1;
}