+#ifdef LISP_FEATURE_GENCGC
+static lispobj *
+pa_alloc(int bytes, int page_type_flag)
+{
+ lispobj *result;
+ struct thread *th = arch_os_get_current_thread();
+
+ /* SIG_STOP_FOR_GC must be unblocked: else two threads racing here
+ * may deadlock: one will wait on the GC lock, and the other
+ * cannot stop the first one... */
+ check_gc_signals_unblocked_or_lose(0);
+
+ /* FIXME: OOAO violation: see arch_pseudo_* */
+ set_pseudo_atomic_atomic(th);
+ result = general_alloc(bytes, page_type_flag);
+#if 0
+ /* See how the runtime deals with GC being triggerred. */
+ if ((SymbolValue(GC_PENDING,th) == NIL) &&
+ (SymbolValue(GC_INHIBIT,th) == NIL) &&
+ (random() < RAND_MAX/100)) {
+ SetSymbolValue(GC_PENDING,T,th);
+ set_pseudo_atomic_interrupted(th);
+ maybe_save_gc_mask_and_block_deferrables(NULL);
+ }
+#endif
+ clear_pseudo_atomic_atomic(th);
+
+ if (get_pseudo_atomic_interrupted(th)) {
+ /* WARNING KLUDGE FIXME: pa_alloc() is not pseudo-atomic on
+ * anything but x86[-64]. maybe_defer_handler doesn't defer
+ * interrupts if foreign_function_call_active
+ *
+ * If the C stack is not scavenged during GC, result needs to
+ * be protected against not being referred to by any roots, so
+ * we push it onto the lisp control stack, and read it back
+ * off after any potential GC has finished */
+#ifndef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
+#ifdef LISP_FEATURE_STACK_GROWS_DOWNWARD_NOT_UPWARD
+#error "!C_STACK_IS_CONTROL_STACK and STACK_GROWS_DOWNWARD_NOT_UPWARD is not supported"
+#endif
+ *current_control_stack_pointer = (lispobj) result;
+ current_control_stack_pointer += 1;
+#endif
+ do_pending_interrupt();
+#ifndef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
+ current_control_stack_pointer -= 1;
+ result = (lispobj *) *current_control_stack_pointer;
+#endif
+ }
+ return result;
+}