+/* This is called at the end of a critical section if the indications
+ * are that some signal was deferred during the section. Note that as
+ * far as C or the kernel is concerned we dealt with the signal
+ * already; we're just doing the Lisp-level processing now that we
+ * put off then */
+
+void
+run_deferred_handler(struct interrupt_data *data, void *v_context) {
+ /* The pending_handler may enable interrupts (see
+ * interrupt_maybe_gc_int) and then another interrupt may hit,
+ * overwrite interrupt_data, so reset the pending handler before
+ * calling it. Trust the handler to finish with the siginfo before
+ * enabling interrupts. */
+ void (*pending_handler) (int, siginfo_t*, void*)=data->pending_handler;
+ data->pending_handler=0;
+ (*pending_handler)(data->pending_signal,&(data->pending_info), v_context);
+}
+
+boolean
+maybe_defer_handler(void *handler, struct interrupt_data *data,
+ int signal, siginfo_t *info, os_context_t *context)
+{
+ struct thread *thread=arch_os_get_current_thread();
+
+ check_blockables_blocked_or_lose();
+
+ if (SymbolValue(INTERRUPT_PENDING,thread) != NIL)
+ lose("interrupt already pending");
+ /* If interrupts are disabled then INTERRUPT_PENDING is set and
+ * not PSEDUO_ATOMIC_INTERRUPTED. This is important for a pseudo
+ * atomic section inside a without-interrupts.
+ */
+ if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) {
+ store_signal_data_for_later(data,handler,signal,info,context);
+ SetSymbolValue(INTERRUPT_PENDING, T,thread);
+#ifdef QSHOW_SIGNALS
+ FSHOW((stderr,
+ "/maybe_defer_handler(%x,%d),thread=%ld: deferred\n",
+ (unsigned int)handler,signal,thread->os_thread));
+#endif
+ return 1;
+ }
+ /* a slightly confusing test. arch_pseudo_atomic_atomic() doesn't
+ * actually use its argument for anything on x86, so this branch
+ * may succeed even when context is null (gencgc alloc()) */
+ if (
+#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
+ (!foreign_function_call_active) &&
+#endif
+ arch_pseudo_atomic_atomic(context)) {
+ store_signal_data_for_later(data,handler,signal,info,context);
+ arch_set_pseudo_atomic_interrupted(context);
+#ifdef QSHOW_SIGNALS
+ FSHOW((stderr,
+ "/maybe_defer_handler(%x,%d),thread=%ld: deferred(PA)\n",
+ (unsigned int)handler,signal,thread->os_thread));
+#endif
+ return 1;
+ }
+#ifdef QSHOW_SIGNALS
+ FSHOW((stderr,
+ "/maybe_defer_handler(%x,%d),thread=%ld: not deferred\n",
+ (unsigned int)handler,signal,thread->os_thread));
+#endif
+ return 0;
+}
+