+ if (SymbolValue(GC_INHIBIT,thread)==NIL) {
+ void *original_pending_handler = data->pending_handler;
+
+#ifdef LISP_FEATURE_SB_SAFEPOINT
+ /* handles the STOP_FOR_GC_PENDING case, plus THRUPTIONS */
+ if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL
+# ifdef LISP_FEATURE_SB_THRUPTION
+ || SymbolValue(THRUPTION_PENDING,thread) != NIL
+# endif
+ )
+ {
+ /* We ought to take this chance to do a pitstop now. */
+
+ /* Now, it goes without saying that the context sigmask
+ * tweaking around this call is not pretty. However, it
+ * currently seems to be "needed" for the following
+ * situation. (So let's find a better solution and remove
+ * this comment afterwards.)
+ *
+ * Suppose we are in a signal handler (let's say SIGALRM).
+ * At the end of a WITHOUT-INTERRUPTS, the lisp code notices
+ * that a thruption is pending, and says to itself "let's
+ * receive pending interrupts then". We trust that the
+ * caller is happy to run those sorts of things now,
+ * including thruptions, otherwise it wouldn't have called
+ * us. But that's the problem: Even though we can guess the
+ * caller's intention, may_thrupt() would see that signals
+ * are blocked in the signal context (because that context
+ * itself points to a signal handler). So we cheat and
+ * pretend that signals weren't blocked.
+ * --DFL */
+#ifndef LISP_FEATURE_WIN32
+ sigset_t old, *ctxset = os_context_sigmask_addr(context);
+ unblock_signals(&deferrable_sigset, ctxset, &old);
+#endif
+ thread_pitstop(context);
+#ifndef LISP_FEATURE_WIN32
+ sigcopyset(&old, ctxset);
+#endif
+ }
+#elif defined(LISP_FEATURE_SB_THREAD)
+ if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL) {
+ /* STOP_FOR_GC_PENDING and GC_PENDING are cleared by
+ * the signal handler if it actually stops us. */
+ arch_clear_pseudo_atomic_interrupted(context);
+ sig_stop_for_gc_handler(SIG_STOP_FOR_GC,NULL,context);
+ } else
+#endif
+ /* Test for T and not for != NIL since the value :IN-PROGRESS
+ * is used in SUB-GC as part of the mechanism to supress
+ * recursive gcs.*/
+ if (SymbolValue(GC_PENDING,thread) == T) {
+
+ /* Two reasons for doing this. First, if there is a
+ * pending handler we don't want to run. Second, we are
+ * going to clear pseudo atomic interrupted to avoid
+ * spurious trapping on every allocation in SUB_GC and
+ * having a pending handler with interrupts enabled and
+ * without pseudo atomic interrupted breaks an
+ * invariant. */
+ if (data->pending_handler) {
+ bind_variable(ALLOW_WITH_INTERRUPTS, NIL, thread);
+ bind_variable(INTERRUPTS_ENABLED, NIL, thread);
+ }
+
+ arch_clear_pseudo_atomic_interrupted(context);
+
+ /* GC_PENDING is cleared in SUB-GC, or if another thread
+ * is doing a gc already we will get a SIG_STOP_FOR_GC and
+ * that will clear it.
+ *
+ * If there is a pending handler or gc was triggerred in a
+ * signal handler then maybe_gc won't run POST_GC and will
+ * return normally. */
+ if (!maybe_gc(context))
+ lose("GC not inhibited but maybe_gc did not GC.");
+
+ if (data->pending_handler) {
+ unbind(thread);
+ unbind(thread);
+ }
+ } else if (SymbolValue(GC_PENDING,thread) != NIL) {
+ /* It's not NIL or T so GC_PENDING is :IN-PROGRESS. If
+ * GC-PENDING is not NIL then we cannot trap on pseudo
+ * atomic due to GC (see if(GC_PENDING) logic in
+ * cheneygc.c an gengcgc.c), plus there is a outer
+ * WITHOUT-INTERRUPTS SUB_GC, so how did we end up
+ * here? */
+ lose("Trapping to run pending handler while GC in progress.");
+ }
+
+ check_blockables_blocked_or_lose(0);
+
+ /* No GC shall be lost. If SUB_GC triggers another GC then
+ * that should be handled on the spot. */
+ if (SymbolValue(GC_PENDING,thread) != NIL)
+ lose("GC_PENDING after doing gc.");
+#ifdef THREADS_USING_GCSIGNAL
+ if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL)
+ lose("STOP_FOR_GC_PENDING after doing gc.");
+#endif
+ /* Check two things. First, that gc does not clobber a handler
+ * that's already pending. Second, that there is no interrupt
+ * lossage: if original_pending_handler was NULL then even if
+ * an interrupt arrived during GC (POST-GC, really) it was
+ * handled. */
+ if (original_pending_handler != data->pending_handler)
+ lose("pending handler changed in gc: %x -> %d.",
+ original_pending_handler, data->pending_handler);