Index: /trunk/ccl/lisp-kernel/x86-exceptions.c
===================================================================
--- /trunk/ccl/lisp-kernel/x86-exceptions.c	(revision 6219)
+++ /trunk/ccl/lisp-kernel/x86-exceptions.c	(revision 6220)
@@ -1039,13 +1039,15 @@
 
 void
-altstack_signal_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
-{
-  TCR* tcr = get_tcr(true);
-  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
-#if 1
-  if (tcr->valence != TCR_STATE_LISP) {
-    Bug(context, "exception in foreign context");
-  }
-#endif
+handle_signal_on_foreign_stack(TCR *tcr,
+                               void *handler, 
+                               int signum, 
+                               siginfo_t *info, 
+                               ExceptionInformation *context,
+                               LispObj return_address
+#ifdef DARWIN_GS_HACK
+                               , Boolean gs_was_tcr
+#endif
+                               )
+{
 #ifdef LINUX
   fpregset_t fpregs = NULL;
@@ -1053,18 +1055,48 @@
   void *fpregs = NULL;
 #endif
+#ifdef DARWIN
+  MCONTEXT_T mcontextp = NULL;
+#endif
   siginfo_t *info_copy = NULL;
   ExceptionInformation *xp = NULL;
-
-  if (foreign_rsp) {
+  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
+
 #ifdef LINUX
-    foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
-#endif
-    foreign_rsp = copy_siginfo(info, foreign_rsp);
-    info_copy = (siginfo_t *)foreign_rsp;
-    foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
-    xp = (ExceptionInformation *)foreign_rsp;
-    *--foreign_rsp = (LispObj)__builtin_return_address(0);
-    switch_to_foreign_stack(foreign_rsp,signal_handler,signum,info_copy,xp);
-  }
+  foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
+#endif
+#ifdef DARWIN
+  foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
+#endif
+  foreign_rsp = copy_siginfo(info, foreign_rsp);
+  info_copy = (siginfo_t *)foreign_rsp;
+  foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
+  xp = (ExceptionInformation *)foreign_rsp;
+#ifdef DARWIN
+  UC_MCONTEXT(xp) = mcontextp;
+#endif
+  *--foreign_rsp = return_address;
+#ifdef DARWIN_GS_HACK
+  if (gs_was_tcr) {
+    set_gs_address(tcr);
+  }
+#endif
+  switch_to_foreign_stack(foreign_rsp,handler,signum,info_copy,xp);
+}
+
+
+void
+altstack_signal_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
+{
+  TCR* tcr = get_tcr(true);
+#if 1
+  if (tcr->valence != TCR_STATE_LISP) {
+    Bug(context, "exception in foreign context");
+  }
+#endif
+  handle_signal_on_foreign_stack(tcr,signal_handler,signum,info,context,(LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 , false
+#endif
+);
 }
 
@@ -1134,6 +1166,7 @@
 }
 
-void
-altstack_interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+#ifndef USE_SIGALTSTACK
+void
+arbstack_interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
 {
 #ifdef DARWIN_GS_HACK
@@ -1141,31 +1174,22 @@
 #endif
   TCR *tcr = get_interrupt_tcr(false);
-  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
-#ifdef LINUX
-  fpregset_t fpregs = NULL;
-#else
-  void *fpregs = NULL;
-#endif
-#ifdef DARWIN
-  MCONTEXT_T mcontextp = NULL;
-#endif
-  siginfo_t *info_copy = NULL;
-  ExceptionInformation *xp = NULL;
-
-  if (foreign_rsp) {
-#ifdef LINUX
-    foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
-#endif
-#ifdef DARWIN
-    foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
-#endif
-    foreign_rsp = copy_siginfo(info, foreign_rsp);
-    info_copy = (siginfo_t *)foreign_rsp;
-    foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
-    xp = (ExceptionInformation *)foreign_rsp;
-#ifdef DARWIN
-    UC_MCONTEXT(xp) = mcontextp;
-#endif
-    *--foreign_rsp = (LispObj)__builtin_return_address(0);
+  area *vs = tcr->vs_area;
+  BytePtr current_sp = (BytePtr) current_stack_pointer();
+
+  if ((current_sp >= vs->low) &&
+      (current_sp < vs->high)) {
+    handle_signal_on_foreign_stack(tcr,
+                                   interrupt_handler,
+                                   signum,
+                                   info,
+                                   context,
+                                   (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                   ,gs_was_tcr
+#endif
+                                   );
+  } else {
+    /* If we're not on the value stack, we pretty much have to be on
+       the C stack.  Just run the handler. */
 #ifdef DARWIN_GS_HACK
     if (gs_was_tcr) {
@@ -1173,7 +1197,25 @@
     }
 #endif
-    switch_to_foreign_stack(foreign_rsp,interrupt_handler,signum,info_copy,xp);
-  }
-}
+    interrupt_handler(signum, info, context);
+  }
+}
+
+#else /* altstack works */
+  
+void
+altstack_interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  handle_signal_on_foreign_stack(tcr,interrupt_handler,signum,info,context,(LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 ,gs_was_tcr
+#endif
+                                 );
+}
+
+#endif
 
 
@@ -1195,5 +1237,7 @@
   sa.sa_flags = 
     SA_RESTART
+#ifdef USE_SIGALTSTACK
     | SA_ONSTACK
+#endif
     | SA_SIGINFO;
 
@@ -1221,44 +1265,39 @@
   
   install_signal_handler(SIGNAL_FOR_PROCESS_INTERRUPT,
-			 altstack_interrupt_handler);
+#ifdef USE_SIGALTSTACK
+			 altstack_interrupt_handler
+#else
+                         arbstack_interrupt_handler
+#endif
+);
   signal(SIGPIPE, SIG_IGN);
 }
 
-
-void
-altstack_suspend_resume_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
+#ifndef USE_SIGALTSTACK
+void
+arbstack_suspend_resume_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
 {
 #ifdef DARWIN_GS_HACK
   Boolean gs_was_tcr = ensure_gs_pthread();
 #endif
-  TCR* tcr = get_tcr(true);
-  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
-#ifdef LINUX
-  fpregset_t fpregs = NULL;
-#else
-  void *fpregs = NULL;
-#endif
-#ifdef DARWIN
-  MCONTEXT_T mcontextp = NULL;
-#endif
-
-  siginfo_t *info_copy = NULL;
-  ExceptionInformation *xp = NULL;
-
-  if (foreign_rsp) {
-#ifdef LINUX
-    foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
-#endif
-#ifdef DARWIN
-    foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
-#endif
-    foreign_rsp = copy_siginfo(info, foreign_rsp);
-    info_copy = (siginfo_t *)foreign_rsp;
-    foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
-    xp = (ExceptionInformation *)foreign_rsp;
-#ifdef DARWIN
-    UC_MCONTEXT(xp) = mcontextp;
-#endif
-    *--foreign_rsp = (LispObj)__builtin_return_address(0);
+  TCR *tcr = get_interrupt_tcr(false);
+  area *vs = tcr->vs_area;
+  BytePtr current_sp = (BytePtr) current_stack_pointer();
+
+  if ((current_sp >= vs->low) &&
+      (current_sp < vs->high)) {
+    handle_signal_on_foreign_stack(tcr,
+                                   suspend_resume_handler,
+                                   signum,
+                                   info,
+                                   context,
+                                   (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                   ,gs_was_tcr
+#endif
+                                   );
+  } else {
+    /* If we're not on the value stack, we pretty much have to be on
+       the C stack.  Just run the handler. */
 #ifdef DARWIN_GS_HACK
     if (gs_was_tcr) {
@@ -1266,10 +1305,33 @@
     }
 #endif
-    switch_to_foreign_stack(foreign_rsp,suspend_resume_handler,signum,info_copy,xp);
-  }
-}
-
-void
-quit_handler(int signum, siginfo_t info, ExceptionInformation *xp)
+    suspend_resume_handler(signum, info, context);
+  }
+}
+
+
+#else /* altstack works */
+void
+altstack_suspend_resume_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR* tcr = get_tcr(true);
+  handle_signal_on_foreign_stack(tcr,
+                                 suspend_resume_handler,
+                                 signum,
+                                 info,
+                                 context,
+                                 (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 ,gs_was_tcr
+#endif
+                                 );
+}
+
+#endif
+
+void
+quit_handler(int signum, siginfo_t *info, ExceptionInformation *xp)
 {
   TCR *tcr = get_tcr(false);
@@ -1300,42 +1362,67 @@
 }
 
-void
-altstack_quit_handler(int signum, siginfo_t *info, ExceptionInformation *context)
+#ifndef USE_SIGALTSTACK
+arbstack_quit_handler(int signum, siginfo_t *info, ExceptionInformation *context)
 {
 #ifdef DARWIN_GS_HACK
   Boolean gs_was_tcr = ensure_gs_pthread();
 #endif
+  TCR *tcr = get_interrupt_tcr(false);
+  area *vs = tcr->vs_area;
+  BytePtr current_sp = (BytePtr) current_stack_pointer();
+
+  if ((current_sp >= vs->low) &&
+      (current_sp < vs->high)) {
+    handle_signal_on_foreign_stack(tcr,
+                                   quit_handler,
+                                   signum,
+                                   info,
+                                   context,
+                                   (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                   ,gs_was_tcr
+#endif
+                                   );
+  } else {
+    /* If we're not on the value stack, we pretty much have to be on
+       the C stack.  Just run the handler. */
+#ifdef DARWIN_GS_HACK
+    if (gs_was_tcr) {
+      set_gs_address(tcr);
+    }
+#endif
+    quit_handler(signum, info, context);
+  }
+}
+
+
+#else
+void
+altstack_quit_handler(int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
   TCR* tcr = get_tcr(true);
-  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
-#ifdef LINUX
-  fpregset_t fpregs = NULL;
+  handle_signal_on_foreign_stack(tcr,
+                                 quit_handler,
+                                 signum,
+                                 info,
+                                 context,
+                                 (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 ,gs_was_tcr
+#endif
+                                 );
+}
+#endif
+
+#ifdef USE_SIGALTSTACK
+#define SUSPEND_RESUME_HANDLER altstack_suspend_resume_handler
+#define QUIT_HANDLER altstack_quit_handler
 #else
-  void *fpregs = NULL;
-#endif
-#ifdef DARWIN
-  MCONTEXT_T mcontextp = NULL;
-#endif
-
-  siginfo_t *info_copy = NULL;
-  ExceptionInformation *xp = NULL;
-
-  if (foreign_rsp) {
-#ifdef LINUX
-    foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
-#endif
-#ifdef DARWIN
-    foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
-#endif
-    foreign_rsp = copy_siginfo(info, foreign_rsp);
-    info_copy = (siginfo_t *)foreign_rsp;
-    foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
-    xp = (ExceptionInformation *)foreign_rsp;
-#ifdef DARWIN
-    UC_MCONTEXT(xp) = mcontextp;
-#endif
-    *--foreign_rsp = (LispObj)__builtin_return_address(0);
-    switch_to_foreign_stack(foreign_rsp,quit_handler,signum,info_copy,xp);
-  }
-}
+#define SUSPEND_RESUME_HANDLER arbstack_suspend_resume_handler
+#define QUIT_HANDLER arbstack_quit_handler
+#endif
 
 void
@@ -1345,7 +1432,7 @@
   thread_resume_signal = SIG_RESUME_THREAD;
 
-  install_signal_handler(thread_suspend_signal, (void *)altstack_suspend_resume_handler);
-  install_signal_handler(thread_resume_signal, (void *)altstack_suspend_resume_handler);
-  install_signal_handler(SIGQUIT, (void *)altstack_quit_handler);
+  install_signal_handler(thread_suspend_signal, (void *)SUSPEND_RESUME_HANDLER);
+  install_signal_handler(thread_resume_signal, (void *)SUSPEND_RESUME_HANDLER);
+  install_signal_handler(SIGQUIT, (void *)QUIT_HANDLER);
 }
 
@@ -1403,4 +1490,5 @@
 
 
+#ifdef USE_SIGALTSTACK
 void
 setup_sigaltstack(area *a)
@@ -1412,6 +1500,10 @@
   stack.ss_flags = 0;
   mmap(stack.ss_sp,stack.ss_size, PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_ANON|MAP_PRIVATE,-1,0);
-  sigaltstack(&stack, NULL);
-}
+  if (sigaltstack(&stack, NULL) != 0) {
+    perror("sigaltstack");
+    exit(-1);
+  }
+}
+#endif
 
 extern opcode egc_write_barrier_start, egc_write_barrier_end,
