Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • rts/PrimOps.cmm
    ... ... @@ -1211,27 +1211,16 @@ INFO_TABLE_RET(stg_catch_retry_frame, CATCH_RETRY_FRAME,
    1211 1211
         gcptr trec, outer, arg;
    
    1212 1212
     
    
    1213 1213
         trec = StgTSO_trec(CurrentTSO);
    
    1214
    -    if (running_alt_code != 1) {
    
    1215
    -      // When exiting the lhs code of catchRetry# lhs rhs, we need to cleanup
    
    1216
    -      // the nested transaction.
    
    1217
    -      // See Note [catchRetry# implementation]
    
    1218
    -      outer  = StgTRecHeader_enclosing_trec(trec);
    
    1219
    -      (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
    
    1220
    -      if (r != 0) {
    
    1221
    -          // Succeeded in first branch
    
    1222
    -          StgTSO_trec(CurrentTSO) = outer;
    
    1223
    -          return (ret);
    
    1224
    -      } else {
    
    1225
    -          // Did not commit: abort and restart.
    
    1226
    -          StgTSO_trec(CurrentTSO) = outer;
    
    1227
    -          jump stg_abort();
    
    1228
    -      }
    
    1229
    -    }
    
    1230
    -    else {
    
    1231
    -      // nothing to do in the rhs code of catchRetry# lhs rhs, it's already
    
    1232
    -      // using the parent transaction (not a nested one).
    
    1233
    -      // See Note [catchRetry# implementation]
    
    1234
    -      return (ret);
    
    1214
    +    outer  = StgTRecHeader_enclosing_trec(trec);
    
    1215
    +    (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
    
    1216
    +    if (r != 0) {
    
    1217
    +        // Succeeded (either first branch or second branch)
    
    1218
    +        StgTSO_trec(CurrentTSO) = outer;
    
    1219
    +        return (ret);
    
    1220
    +    } else {
    
    1221
    +        // Did not commit: abort and restart.
    
    1222
    +        StgTSO_trec(CurrentTSO) = outer;
    
    1223
    +        jump stg_abort();
    
    1235 1224
         }
    
    1236 1225
     }
    
    1237 1226
     
    
    ... ... @@ -1464,26 +1453,21 @@ retry_pop_stack:
    1464 1453
         outer  = StgTRecHeader_enclosing_trec(trec);
    
    1465 1454
     
    
    1466 1455
         if (frame_type == CATCH_RETRY_FRAME) {
    
    1467
    -        // The retry reaches a CATCH_RETRY_FRAME before the ATOMICALLY_FRAME
    
    1468
    -
    
    1456
    +        // The retry reaches a CATCH_RETRY_FRAME before the atomic frame
    
    1457
    +        ASSERT(outer != NO_TREC);
    
    1458
    +        // Abort the transaction attempting the current branch
    
    1459
    +        ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
    
    1460
    +        ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
    
    1469 1461
             if (!StgCatchRetryFrame_running_alt_code(frame) != 0) {
    
    1470
    -            // Retrying in the lhs of catchRetry# lhs rhs, i.e. in a nested
    
    1471
    -            // transaction. See Note [catchRetry# implementation]
    
    1472
    -
    
    1473
    -            // check that we have a parent transaction
    
    1474
    -            ASSERT(outer != NO_TREC);
    
    1475
    -
    
    1476
    -            // Abort the nested transaction
    
    1477
    -            ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
    
    1478
    -            ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
    
    1479
    -
    
    1480
    -            // As we are retrying in the lhs code, we must now try the rhs code
    
    1481
    -            StgTSO_trec(CurrentTSO) = outer;
    
    1462
    +            // Retry in the first branch: try the alternative
    
    1463
    +            ("ptr" trec) = ccall stmStartTransaction(MyCapability() "ptr", outer "ptr");
    
    1464
    +            StgTSO_trec(CurrentTSO) = trec;
    
    1482 1465
                 StgCatchRetryFrame_running_alt_code(frame) = 1 :: CInt; // true;
    
    1483 1466
                 R1 = StgCatchRetryFrame_alt_code(frame);
    
    1484 1467
                 jump stg_ap_v_fast [R1];
    
    1485 1468
             } else {
    
    1486
    -            // Retry in the rhs code: propagate the retry
    
    1469
    +            // Retry in the alternative code: propagate the retry
    
    1470
    +            StgTSO_trec(CurrentTSO) = outer;
    
    1487 1471
                 Sp = Sp + SIZEOF_StgCatchRetryFrame;
    
    1488 1472
                 goto retry_pop_stack;
    
    1489 1473
             }
    

  • rts/RaiseAsync.c
    ... ... @@ -1043,7 +1043,8 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception,
    1043 1043
                 }
    
    1044 1044
     
    
    1045 1045
             case CATCH_STM_FRAME:
    
    1046
    -            // CATCH_STM frame within an atomically block: abort the
    
    1046
    +        case CATCH_RETRY_FRAME:
    
    1047
    +            // CATCH frames within an atomically block: abort the
    
    1047 1048
                 // inner transaction and continue.  Eventually we will
    
    1048 1049
                 // hit the outer transaction that will get frozen (see
    
    1049 1050
                 // above).
    
    ... ... @@ -1055,40 +1056,14 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception,
    1055 1056
             {
    
    1056 1057
                 StgTRecHeader *trec = tso -> trec;
    
    1057 1058
                 StgTRecHeader *outer = trec -> enclosing_trec;
    
    1058
    -            debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_STM frame");
    
    1059
    +            debugTraceCap(DEBUG_stm, cap,
    
    1060
    +                          "found atomically block delivering async exception");
    
    1059 1061
                 stmAbortTransaction(cap, trec);
    
    1060 1062
                 stmFreeAbortedTRec(cap, trec);
    
    1061 1063
                 tso -> trec = outer;
    
    1062 1064
                 break;
    
    1063 1065
             };
    
    1064 1066
     
    
    1065
    -        case CATCH_RETRY_FRAME:
    
    1066
    -            // CATCH_RETY frame within an atomically block: if we're executing
    
    1067
    -            // the lhs code, abort the inner transaction and continue; if we're
    
    1068
    -            // executing thr rhs, continue (no nested transaction to abort. See
    
    1069
    -            // Note [catchRetry# implementation]). Eventually we will hit the
    
    1070
    -            // outer transaction that will get frozen (see above).
    
    1071
    -            //
    
    1072
    -            // As for the CATCH_STM_FRAME case above, we do not care
    
    1073
    -            // whether the transaction is valid or not because its
    
    1074
    -            // possible validity cannot have caused the exception
    
    1075
    -            // and will not be visible after the abort.
    
    1076
    -        {
    
    1077
    -            if (!((StgCatchRetryFrame *)frame) -> running_alt_code) {
    
    1078
    -                debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (lhs)");
    
    1079
    -                StgTRecHeader *trec = tso -> trec;
    
    1080
    -                StgTRecHeader *outer = trec -> enclosing_trec;
    
    1081
    -                stmAbortTransaction(cap, trec);
    
    1082
    -                stmFreeAbortedTRec(cap, trec);
    
    1083
    -                tso -> trec = outer;
    
    1084
    -            }
    
    1085
    -            else
    
    1086
    -            {
    
    1087
    -                debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (rhs)");
    
    1088
    -            }
    
    1089
    -            break;
    
    1090
    -        };
    
    1091
    -
    
    1092 1067
             default:
    
    1093 1068
                 // see Note [Update async masking state on unwind] in Schedule.c
    
    1094 1069
                 if (*frame == (W_)&stg_unmaskAsyncExceptionszh_ret_info) {
    

  • rts/STM.c
    ... ... @@ -1505,30 +1505,3 @@ void stmWriteTVar(Capability *cap,
    1505 1505
     }
    
    1506 1506
     
    
    1507 1507
     /*......................................................................*/
    1508
    -
    
    1509
    -
    
    1510
    -
    
    1511
    -/*
    
    1512
    -
    
    1513
    -Note [catchRetry# implementation]
    
    1514
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1515
    -catchRetry# creates a nested transaction for its lhs:
    
    1516
    -- if the lhs transaction succeeds:
    
    1517
    -    - the lhs transaction is committed
    
    1518
    -    - its read-variables are merged with those of the parent transaction
    
    1519
    -    - the rhs code is ignored
    
    1520
    -- if the lhs transaction retries:
    
    1521
    -    - the lhs transaction is aborted
    
    1522
    -    - its read-variables are merged with those of the parent transaction
    
    1523
    -    - the rhs code is executed directly in the parent transaction (see #26028).
    
    1524
    -
    
    1525
    -So note that:
    
    1526
    -- lhs code uses a nested transaction
    
    1527
    -- rhs code doesn't use a nested transaction
    
    1528
    -
    
    1529
    -We have to take which case we're in into account (using the running_alt_code
    
    1530
    -field of the catchRetry frame) in catchRetry's entry code, in retry#
    
    1531
    -implementation, and also when an async exception is received (to cleanup the
    
    1532
    -right number of transactions).
    
    1533
    -
    
    1534
    -*/

  • testsuite/tests/lib/stm/T26028.hs deleted
    1
    -module Main where
    
    2
    -
    
    3
    -import GHC.Conc
    
    4
    -
    
    5
    -forever :: IO String
    
    6
    -forever = delay 10 >> forever
    
    7
    -
    
    8
    -terminates :: IO String
    
    9
    -terminates = delay 1 >> pure "terminates"
    
    10
    -
    
    11
    -delay s = threadDelay (1000000 * s)
    
    12
    -
    
    13
    -async :: IO a -> IO (STM a)
    
    14
    -async a = do 
    
    15
    -  var <- atomically (newTVar Nothing)
    
    16
    -  forkIO (a >>= atomically . writeTVar var . Just)
    
    17
    -  pure (readTVar var >>= maybe retry pure)
    
    18
    -
    
    19
    -main :: IO ()
    
    20
    -main = do
    
    21
    -  x <- mapM async $ terminates : replicate 50000 forever
    
    22
    -  r <- atomically (foldr1 orElse x)
    
    23
    -  print r

  • testsuite/tests/lib/stm/T26028.stdout deleted
    1
    -"terminates"

  • testsuite/tests/lib/stm/all.T deleted
    1
    -test('T26028', only_ways(['threaded1']), compile_and_run, ['-O2'])