[project @ 2000-02-04 11:15:04 by simonmar]
[ghc-hetmet.git] / ghc / rts / Exception.hc
index 10d380e..1ad991d 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Exception.hc,v 1.1 1999/12/01 14:34:38 simonmar Exp $
+ * $Id: Exception.hc,v 1.7 2000/02/04 11:15:04 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
 #include "StgRun.h"
 #include "Storage.h"
 #include "RtsUtils.h"
+#include "RtsFlags.h"
+#if defined(PAR)
+# include "FetchMe.h"
+#endif
 
 /* -----------------------------------------------------------------------------
    Exception Primitives
@@ -47,8 +51,13 @@ FN_(blockAsyncExceptionszh_fast)
 
     if (CurrentTSO->blocked_exceptions == NULL) {
       CurrentTSO->blocked_exceptions = END_TSO_QUEUE;
-      Sp--;
-      Sp[0] = (W_)&unblockAsyncExceptionszh_ret_info;
+      /* avoid growing the stack unnecessarily */
+      if (Sp[0] == (W_)&blockAsyncExceptionszh_ret_info) {
+       Sp++;
+      } else {
+       Sp--;
+       Sp[0] = (W_)&unblockAsyncExceptionszh_ret_info;
+      }
     }
     Sp--;
     Sp[0] = ARG_TAG(0);
@@ -61,7 +70,17 @@ FN_(unblockAsyncExceptionszh_ret_entry)
 {
   FB_
     ASSERT(CurrentTSO->blocked_exceptions != NULL);
+#if defined(GRAN)
+      awakenBlockedQueue(CurrentTSO->blocked_exceptions, 
+                        CurrentTSO->block_info.closure);
+#elif defined(PAR)
+      // is CurrentTSO->block_info.closure always set to the node
+      // holding the blocking queue !? -- HWL
+      awakenBlockedQueue(CurrentTSO->blocked_exceptions, 
+                        CurrentTSO->block_info.closure);
+#else
     awakenBlockedQueue(CurrentTSO->blocked_exceptions);
+#endif
     CurrentTSO->blocked_exceptions = NULL;
     Sp++;
     JMP_(ENTRY_CODE(Sp[0]));
@@ -75,10 +94,26 @@ FN_(unblockAsyncExceptionszh_fast)
     STK_CHK_GEN(2, R1_PTR, unblockAsyncExceptionszh_fast, );
 
     if (CurrentTSO->blocked_exceptions != NULL) {
+#if defined(GRAN)
+      awakenBlockedQueue(CurrentTSO->blocked_exceptions, 
+                        CurrentTSO->block_info.closure);
+#elif defined(PAR)
+      // is CurrentTSO->block_info.closure always set to the node
+      // holding the blocking queue !? -- HWL
+      awakenBlockedQueue(CurrentTSO->blocked_exceptions, 
+                        CurrentTSO->block_info.closure);
+#else
       awakenBlockedQueue(CurrentTSO->blocked_exceptions);
+#endif
       CurrentTSO->blocked_exceptions = NULL;
-      Sp--;
-      Sp[0] = (W_)&blockAsyncExceptionszh_ret_info;
+
+      /* avoid growing the stack unnecessarily */
+      if (Sp[0] == (W_)&unblockAsyncExceptionszh_ret_info) {
+       Sp++;
+      } else {
+       Sp--;   
+       Sp[0] = (W_)&blockAsyncExceptionszh_ret_info;
+      }
     }
     Sp--;
     Sp[0] = ARG_TAG(0);
@@ -103,6 +138,13 @@ FN_(killThreadzh_fast)
   FB_
   /* args: R1.p = TSO to kill, R2.p = Exception */
 
+  /* This thread may have been relocated.
+   * (see Schedule.c:threadStackOverflow)
+   */
+  while (R1.t->whatNext == ThreadRelocated) {
+    R1.t = R1.t->link;
+  }
+
   /* If the target thread is currently blocking async exceptions,
    * we'll have to block until it's ready to accept them.
    */
@@ -157,6 +199,7 @@ FN_(killThreadzh_fast)
    Catch frames
    -------------------------------------------------------------------------- */
 
+#ifdef REG_R1
 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret)  \
    FN_(label);                                 \
    FN_(label)                                  \
@@ -167,16 +210,38 @@ FN_(killThreadzh_fast)
       JMP_(ret);                               \
       FE_                                      \
    }
+#else
+#define CATCH_FRAME_ENTRY_TEMPLATE(label,ret)  \
+   FN_(label);                                 \
+   FN_(label)                                  \
+   {                                           \
+      StgWord rval;                            \
+      FB_                                      \
+      rval = Sp[0];                            \
+      Sp++;                                    \
+      Su = ((StgCatchFrame *)Sp)->link;                \
+      Sp += sizeofW(StgCatchFrame) - 1;                \
+      Sp[0] = rval;                            \
+      JMP_(ret);                               \
+      FE_                                      \
+   }
+#endif
+
+#ifdef REG_R1
+#define SP_OFF 0
+#else
+#define SP_OFF 1
+#endif
 
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_entry,ENTRY_CODE(Sp[0]));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_0_entry,RET_VEC(Sp[0],0));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_1_entry,RET_VEC(Sp[0],1));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_2_entry,RET_VEC(Sp[0],2));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_3_entry,RET_VEC(Sp[0],3));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_4_entry,RET_VEC(Sp[0],4));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_5_entry,RET_VEC(Sp[0],5));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_6_entry,RET_VEC(Sp[0],6));
-CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_7_entry,RET_VEC(Sp[0],7));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_entry,ENTRY_CODE(Sp[SP_OFF]));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_0_entry,RET_VEC(Sp[SP_OFF],0));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_1_entry,RET_VEC(Sp[SP_OFF],1));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_2_entry,RET_VEC(Sp[SP_OFF],2));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_3_entry,RET_VEC(Sp[SP_OFF],3));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_4_entry,RET_VEC(Sp[SP_OFF],4));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_5_entry,RET_VEC(Sp[SP_OFF],5));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_6_entry,RET_VEC(Sp[SP_OFF],6));
+CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_7_entry,RET_VEC(Sp[SP_OFF],7));
 
 #ifdef PROFILING
 #define CATCH_FRAME_BITMAP 7
@@ -216,8 +281,10 @@ FN_(catchzh_fast)
   StgCatchFrame *fp;
   FB_
 
-    /* args: R1 = m, R2 = handler */
-    STK_CHK_GEN(sizeofW(StgCatchFrame), R1_PTR | R2_PTR, catchzh_fast, );
+    /* args: R1 = m :: IO a, R2 = handler :: Exception -> IO a */
+    STK_CHK_GEN(sizeofW(StgCatchFrame) + 1, R1_PTR | R2_PTR, catchzh_fast, );
+  
+    /* Set up the catch frame */
     Sp -= sizeofW(StgCatchFrame);
     fp = (StgCatchFrame *)Sp;
     SET_HDR(fp,(StgInfoTable *)&catch_frame_info,CCCS);
@@ -226,6 +293,10 @@ FN_(catchzh_fast)
     fp -> link = Su;
     Su = (StgUpdateFrame *)fp;
     TICK_CATCHF_PUSHED();
+
+    /* Push realworld token and enter R1. */
+    Sp--;
+    Sp[0] = ARG_TAG(0);
     TICK_ENT_VIA_NODE();
     JMP_(GET_ENTRY(R1.cl));
     
@@ -318,7 +389,7 @@ FN_(raisezh_fast)
     Su = ((StgCatchFrame *)p)->link; 
     handler = ((StgCatchFrame *)p)->handler;
     
-    Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
+    Sp = (P_)p + sizeofW(StgCatchFrame);
 
     /* Restore the blocked/unblocked state for asynchronous exceptions
      * at the CATCH_FRAME.  
@@ -328,7 +399,7 @@ FN_(raisezh_fast)
      * unblockAsyncExceptions_ret stack frame.
      */
     if (! ((StgCatchFrame *)p)->exceptions_blocked) {
-      *(Sp--) = (W_)&unblockAsyncExceptionszh_ret_info;
+      *(--Sp) = (W_)&unblockAsyncExceptionszh_ret_info;
     }
 
     /* Ensure that async excpetions are blocked when running the handler.
@@ -337,9 +408,12 @@ FN_(raisezh_fast)
       CurrentTSO->blocked_exceptions = END_TSO_QUEUE;
     }
 
-    /* Enter the handler, passing the exception value as an argument.
+    /* Enter the handler, passing the exception value and a realworld
+     * token as arguments.
      */
-    *Sp = R1.w;
+    Sp -= 2;
+    Sp[0] = R1.w;
+    Sp[1] = ARG_TAG(0);
     TICK_ENT_VIA_NODE();
     R1.cl = handler;
     JMP_(GET_ENTRY(R1.cl));