Fixed uninitialised FunBind fun_tick field
[ghc-hetmet.git] / rts / Exception.cmm
index f4327b9..ae123f9 100644 (file)
@@ -119,10 +119,13 @@ unblockAsyncExceptionszh_fast
     /* Args: R1 :: IO a */
     STK_CHK_GEN( WDS(2), R1_PTR, unblockAsyncExceptionszh_fast);
 
-    if (TO_W_(StgTSO_flags(CurrentTSO)) & TSO_BLOCKEX) {
+    if ((TO_W_(StgTSO_flags(CurrentTSO)) & TSO_BLOCKEX) != 0) {
        foreign "C" awakenBlockedExceptionQueue(MyCapability() "ptr", 
                                                CurrentTSO "ptr") [R1];
 
+       StgTSO_flags(CurrentTSO) = StgTSO_flags(CurrentTSO) & 
+          ~(TSO_BLOCKEX::I32|TSO_INTERRUPTIBLE::I32);
+
        /* avoid growing the stack unnecessarily */
        if (Sp(0) == stg_unblockAsyncExceptionszh_ret_info) {
            Sp_adj(1);
@@ -148,7 +151,7 @@ killThreadzh_fast
     target = R1;
     exception = R2;
     
-    STK_CHK_GEN( WDS(3), R1_PTR | R2_PTR, killThreadzh_fast);
+    STK_CHK_GEN( WDS(3), R1_PTR & R2_PTR, killThreadzh_fast);
 
     /* 
      * We might have killed ourselves.  In which case, better be *very*
@@ -329,10 +332,13 @@ raisezh_fast
     /* ToDo: currently this is a hack.  Would be much better if
      * the info was only displayed for an *uncaught* exception.
      */
-    if (RtsFlags_ProfFlags_showCCSOnException(RtsFlags)) {
+    if (RtsFlags_ProfFlags_showCCSOnException(RtsFlags) != 0::I32) {
       foreign "C" fprintCCS_stderr(W_[CCCS] "ptr");
     }
 #endif
+    
+    /* Inform the Hpc that an exception has been thrown */
+    foreign "C" hs_hpc_event("Raise",CurrentTSO);
 
 retry_pop_stack:
     StgTSO_sp(CurrentTSO) = Sp;
@@ -341,14 +347,27 @@ retry_pop_stack:
     if (frame_type == ATOMICALLY_FRAME) {
       /* The exception has reached the edge of a memory transaction.  Check that 
        * the transaction is valid.  If not then perhaps the exception should
-       * not have been thrown: re-run the transaction */
-      W_ trec;
+       * not have been thrown: re-run the transaction.  "trec" will either be
+       * a top-level transaction running the atomic block, or a nested 
+       * transaction running an invariant check.  In the latter case we
+       * abort and de-allocate the top-level transaction that encloses it
+       * as well (we could just abandon its transaction record, but this makes
+       * sure it's marked as aborted and available for re-use). */
+      W_ trec, outer;
       W_ r;
       trec = StgTSO_trec(CurrentTSO);
       r = foreign "C" stmValidateNestOfTransactions(trec "ptr");
+      "ptr" outer = foreign "C" stmGetEnclosingTRec(trec "ptr") [];
       foreign "C" stmAbortTransaction(MyCapability() "ptr", trec "ptr");
+      foreign "C" stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
+
+      if (outer != NO_TREC) {
+        foreign "C" stmAbortTransaction(MyCapability() "ptr", outer "ptr");
+        foreign "C" stmFreeAbortedTRec(MyCapability() "ptr", outer "ptr");
+      }
+
       StgTSO_trec(CurrentTSO) = NO_TREC;
-      if (r) {
+      if (r != 0) {
         // Transaction was valid: continue searching for a catch frame
         Sp = Sp + SIZEOF_StgAtomicallyFrame;
         goto retry_pop_stack;
@@ -397,6 +416,9 @@ retry_pop_stack:
      * If exceptions were unblocked, arrange that they are unblocked
      * again after executing the handler by pushing an
      * unblockAsyncExceptions_ret stack frame.
+     *
+     * If we've reached an STM catch frame then roll back the nested
+     * transaction we were using.
      */
     W_ frame;
     frame = Sp;
@@ -407,6 +429,12 @@ retry_pop_stack:
         Sp(0) = stg_unblockAsyncExceptionszh_ret_info;
       }
     } else {
+      W_ trec, outer;
+      trec = StgTSO_trec(CurrentTSO);
+      "ptr" outer = foreign "C" stmGetEnclosingTRec(trec "ptr") [];
+      foreign "C" stmAbortTransaction(MyCapability() "ptr", trec "ptr") [];
+      foreign "C" stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr") [];
+      StgTSO_trec(CurrentTSO) = outer;
       Sp = Sp + SIZEOF_StgCatchSTMFrame;
     }