+/* and similarly for the control stack guard page */
+
+boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr)
+{
+ /* note the os_context hackery here. When the signal handler returns,
+ * it won't go back to what it was doing ... */
+ if(addr>=CONTROL_STACK_GUARD_PAGE &&
+ addr<(CONTROL_STACK_GUARD_PAGE+os_vm_page_size)) {
+ void *function;
+ /* we hit the end of the control stack. disable protection
+ * temporarily so the error handler has some headroom */
+ protect_control_stack_guard_page(0);
+
+ function=
+ &(((struct simple_fun *)
+ native_pointer(SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)))
+ ->code);
+
+ /* Build a stack frame showing `interrupted' so that the
+ * user's backtrace makes (as much) sense (as usual) */
+ build_fake_control_stack_frames(context);
+ /* signal handler will "return" to this error-causing function */
+ *os_context_pc_addr(context)= function;
+#ifndef LISP_FEATURE_X86
+ /* this much of the calling convention is common to all
+ non-x86 ports */
+ *os_context_register_addr(context,reg_NARGS)=0;
+ *os_context_register_addr(context,reg_LIP)= function;
+ *os_context_register_addr(context,reg_CFP)=
+ current_control_frame_pointer;
+#ifdef ARCH_HAS_NPC_REGISTER
+ *os_context_register_addr(context,reg_LIP)=
+ 4+*os_context_pc_addr(context);
+#endif
+#endif
+ return 1;
+ }
+ else return 0;
+}
+