Duncan Coutts pushed to branch wip/dcoutts/issue-26717 at Glasgow Haskell Compiler / GHC

Commits:

15 changed files:

Changes:

  • rts/IOManager.c
    ... ... @@ -611,41 +611,6 @@ void markCapabilityIOManager(evac_fn evac, void *user, Capability *cap)
    611 611
     }
    
    612 612
     
    
    613 613
     
    
    614
    -void scavengeTSOIOManager(StgTSO *tso)
    
    615
    -{
    
    616
    -    switch (iomgr_type) {
    
    617
    -
    
    618
    -            /* case IO_MANAGER_SELECT:
    
    619
    -             * BlockedOn{Read,Write} uses block_info.fd
    
    620
    -             * BlockedOnDelay        uses block_info.target
    
    621
    -             * both of these are not GC pointers, so there is nothing to do.
    
    622
    -             */
    
    623
    -
    
    624
    -#if defined(IOMGR_ENABLED_POLL)
    
    625
    -        case IO_MANAGER_POLL:
    
    626
    -            /* BlockedOn{Read,Write} uses block_info.aiop
    
    627
    -             * BlockedOnDelay        uses block_info.timeout
    
    628
    -             * both of these are heap allocated, so we can do the same in all
    
    629
    -             * cases, which is why we can use the generic block_info.closure.
    
    630
    -             */
    
    631
    -            evacuate(&tso->block_info.closure);
    
    632
    -            break;
    
    633
    -#endif
    
    634
    -
    
    635
    -            /* case IO_MANAGER_WIN32_LEGACY:
    
    636
    -             * BlockedOn{Read,Write,DoProc} uses block_info.async_reqID
    
    637
    -             * which is a plain integer, so nothing to scavenge.
    
    638
    -             */
    
    639
    -
    
    640
    -        default:
    
    641
    -            /* All the other I/O managers do not use I/O-related why_blocked
    
    642
    -             * reasons, so there are no cases to handle.
    
    643
    -             */
    
    644
    -            break;
    
    645
    -    }
    
    646
    -}
    
    647
    -
    
    648
    -
    
    649 614
     /* Declared in rts/IOInterface.h. Used only by the MIO threaded I/O manager on
    
    650 615
      * Unix platforms.
    
    651 616
      */
    
    ... ... @@ -807,16 +772,16 @@ bool syncIOWaitReady(Capability *cap,
    807 772
     #if defined(IOMGR_ENABLED_SELECT)
    
    808 773
             case IO_MANAGER_SELECT:
    
    809 774
             {
    
    810
    -            StgWord why_blocked = rw == IORead ? BlockedOnRead : BlockedOnWrite;
    
    775
    +            StgWord why_blocked = (rw == IORead ? BlockedOnRead : BlockedOnWrite)
    
    776
    +                                | BlockInfoForceNonClosure;
    
    811 777
                 tso->block_info.fd = fd;
    
    812
    -            RELEASE_STORE(&tso->why_blocked, why_blocked);
    
    813 778
                 appendToIOBlockedQueue(cap, tso);
    
    779
    +            RELEASE_STORE(&tso->why_blocked, why_blocked);
    
    814 780
                 return true;
    
    815 781
             }
    
    816 782
     #endif
    
    817 783
     #if defined(IOMGR_ENABLED_POLL)
    
    818 784
             case IO_MANAGER_POLL:
    
    819
    -            ASSERT(tso->why_blocked == NotBlocked);
    
    820 785
                 return syncIOWaitReadyPoll(cap, tso, rw, fd);
    
    821 786
     #endif
    
    822 787
             default:
    
    ... ... @@ -868,8 +833,8 @@ bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
    868 833
             {
    
    869 834
                 LowResTime target = getDelayTarget(us_delay);
    
    870 835
                 tso->block_info.target = target;
    
    871
    -            RELEASE_STORE(&tso->why_blocked, BlockedOnDelay);
    
    872 836
                 insertIntoSleepingQueue(cap, tso, target);
    
    837
    +            RELEASE_STORE(&tso->why_blocked, BlockedOnDelay | BlockInfoForceNonClosure);
    
    873 838
                 return true;
    
    874 839
             }
    
    875 840
     #endif
    
    ... ... @@ -889,8 +854,8 @@ bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
    889 854
                  * simplifies matters, so set the status to OnDoProc and put the
    
    890 855
                  * delayed thread on the blocked_queue.
    
    891 856
                  */
    
    892
    -            RELEASE_STORE(&tso->why_blocked, BlockedOnDoProc);
    
    893 857
                 appendToIOBlockedQueue(cap, tso);
    
    858
    +            RELEASE_STORE(&tso->why_blocked, BlockedOnDoProc);
    
    894 859
                 return true;
    
    895 860
             }
    
    896 861
     #endif
    
    ... ... @@ -906,6 +871,7 @@ void syncDelayCancel(Capability *cap, StgTSO *tso)
    906 871
         switch (iomgr_type) {
    
    907 872
     #if defined(IOMGR_ENABLED_SELECT)
    
    908 873
             case IO_MANAGER_SELECT:
    
    874
    +            ASSERT(tso->why_blocked == (BlockedOnDelay | BlockInfoForceNonClosure));
    
    909 875
                 removeThreadFromQueue(cap, &cap->iomgr->sleeping_queue, tso);
    
    910 876
                 break;
    
    911 877
     #endif
    

  • rts/IOManager.h
    ... ... @@ -291,11 +291,6 @@ void wakeupIOManager(void);
    291 291
     void markCapabilityIOManager(evac_fn evac, void *user, Capability *cap);
    
    292 292
     
    
    293 293
     
    
    294
    -/* GC hook: scavenge I/O related tso->block_info. Used by scavengeTSO.
    
    295
    - */
    
    296
    -void scavengeTSOIOManager(StgTSO *tso);
    
    297
    -
    
    298
    -
    
    299 294
     /* Several code paths are almost identical between read and write paths. In
    
    300 295
      * such cases we use a shared code path with an enum to say which we're doing.
    
    301 296
      */
    

  • rts/PrimOps.cmm
    ... ... @@ -2275,7 +2275,8 @@ stg_asyncReadzh ( W_ fd, W_ is_sock, W_ len, W_ buf )
    2275 2275
         StgTSO_block_info(CurrentTSO) = reqID;
    
    2276 2276
     
    
    2277 2277
         ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32);
    
    2278
    -    %release StgTSO_why_blocked(CurrentTSO) = BlockedOnRead::I32;
    
    2278
    +    %release StgTSO_why_blocked(CurrentTSO) = BlockedOnRead::I32
    
    2279
    +                                            | BlockInfoForceNonClosure::I32;
    
    2279 2280
     
    
    2280 2281
         ccall appendToIOBlockedQueue(MyCapability() "ptr", CurrentTSO "ptr");
    
    2281 2282
         jump stg_block_async();
    
    ... ... @@ -2294,7 +2295,8 @@ stg_asyncWritezh ( W_ fd, W_ is_sock, W_ len, W_ buf )
    2294 2295
         StgTSO_block_info(CurrentTSO) = reqID;
    
    2295 2296
     
    
    2296 2297
         ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32);
    
    2297
    -    %release StgTSO_why_blocked(CurrentTSO) = BlockedOnWrite::I32;
    
    2298
    +    %release StgTSO_why_blocked(CurrentTSO) = BlockedOnWrite::I32
    
    2299
    +                                            | BlockInfoForceNonClosure::I32;
    
    2298 2300
     
    
    2299 2301
         ccall appendToIOBlockedQueue(MyCapability() "ptr", CurrentTSO "ptr");
    
    2300 2302
         jump stg_block_async();
    

  • rts/RaiseAsync.c
    ... ... @@ -233,7 +233,6 @@ throwTo (Capability *cap, // the Capability we hold
    233 233
     uint32_t
    
    234 234
     throwToMsg (Capability *cap, MessageThrowTo *msg)
    
    235 235
     {
    
    236
    -    StgWord status;
    
    237 236
         StgTSO *target = ACQUIRE_LOAD(&msg->target);
    
    238 237
         Capability *target_cap;
    
    239 238
     
    
    ... ... @@ -268,9 +267,9 @@ check_target:
    268 267
             return THROWTO_BLOCKED;
    
    269 268
         }
    
    270 269
     
    
    271
    -    status = ACQUIRE_LOAD(&target->why_blocked);
    
    270
    +    StgWord why_blocked = ACQUIRE_LOAD(&target->why_blocked);
    
    272 271
     
    
    273
    -    switch (UntagWhyBlocked(status)) {
    
    272
    +    switch (UntagWhyBlocked(why_blocked)) {
    
    274 273
         case NotBlocked:
    
    275 274
         {
    
    276 275
             if ((target->flags & TSO_BLOCKEX) == 0) {
    
    ... ... @@ -370,8 +369,9 @@ check_target:
    370 369
     
    
    371 370
             // we have the MVar, let's check whether the thread
    
    372 371
             // is still blocked on the same MVar.
    
    373
    -        if ((target->why_blocked != BlockedOnMVar
    
    374
    -             && target->why_blocked != BlockedOnMVarRead)
    
    372
    +        StgWord why_blocked_still = ACQUIRE_LOAD(&target->why_blocked);
    
    373
    +        if ((   why_blocked_still != BlockedOnMVar
    
    374
    +             && why_blocked_still != BlockedOnMVarRead)
    
    375 375
                 || target->block_info.mvar != mvar) {
    
    376 376
                 unlockClosure((StgClosure *)mvar, info);
    
    377 377
                 goto retry;
    
    ... ... @@ -490,7 +490,7 @@ check_target:
    490 490
             goto retry;
    
    491 491
     
    
    492 492
         default:
    
    493
    -        barf("throwTo: unrecognised why_blocked (%d)", target->why_blocked);
    
    493
    +        barf("throwTo: unrecognised why_blocked (%ld)", why_blocked);
    
    494 494
         }
    
    495 495
         barf("throwTo");
    
    496 496
     }
    
    ... ... @@ -667,7 +667,7 @@ removeFromMVarBlockedQueue (StgTSO *tso)
    667 667
     static void
    
    668 668
     removeFromQueues(Capability *cap, StgTSO *tso)
    
    669 669
     {
    
    670
    -  switch (UntagWhyBlocked(tso->why_blocked)) {
    
    670
    +  switch (UntagWhyBlocked(ACQUIRE_LOAD(&tso->why_blocked))) {
    
    671 671
     
    
    672 672
       case NotBlocked:
    
    673 673
       case ThreadMigrating:
    
    ... ... @@ -721,8 +721,8 @@ removeFromQueues(Capability *cap, StgTSO *tso)
    721 721
       }
    
    722 722
     
    
    723 723
      done:
    
    724
    -  RELAXED_STORE(&tso->why_blocked, NotBlocked);
    
    725 724
       appendToRunQueue(cap, tso);
    
    725
    +  RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    726 726
     }
    
    727 727
     
    
    728 728
     /* -----------------------------------------------------------------------------
    
    ... ... @@ -1105,9 +1105,9 @@ done:
    1105 1105
         IF_DEBUG(sanity, checkTSO(tso));
    
    1106 1106
     
    
    1107 1107
         // wake it up
    
    1108
    -    if (tso->why_blocked != NotBlocked) {
    
    1109
    -        tso->why_blocked = NotBlocked;
    
    1108
    +    if (RELAXED_LOAD(&tso->why_blocked) != NotBlocked) {
    
    1110 1109
             appendToRunQueue(cap,tso);
    
    1110
    +        RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    1111 1111
         }
    
    1112 1112
     
    
    1113 1113
         return tso;
    

  • rts/Schedule.c
    ... ... @@ -1098,7 +1098,7 @@ schedulePostRunThread (Capability *cap, StgTSO *t)
    1098 1098
         //
    
    1099 1099
         // and a is never equal to b given a consistent view of memory.
    
    1100 1100
         //
    
    1101
    -    if (t -> trec != NO_TREC && t -> why_blocked == NotBlocked) {
    
    1101
    +    if (t -> trec != NO_TREC && RELAXED_LOAD(&t->why_blocked) == NotBlocked) {
    
    1102 1102
             if (!stmValidateNestOfTransactions(cap, t -> trec, true)) {
    
    1103 1103
                 debugTrace(DEBUG_sched | DEBUG_stm,
    
    1104 1104
                            "trec %p found wasting its time", t);
    
    ... ... @@ -2523,9 +2523,9 @@ suspendThread (StgRegTable *reg, bool interruptible)
    2523 2523
     
    
    2524 2524
       tso->block_info.unused = END_TSO_QUEUE;
    
    2525 2525
       if (interruptible) {
    
    2526
    -    tso->why_blocked = BlockedOnCCall_Interruptible;
    
    2526
    +    RELEASE_STORE(&tso->why_blocked, BlockedOnCCall_Interruptible);
    
    2527 2527
       } else {
    
    2528
    -    tso->why_blocked = BlockedOnCCall;
    
    2528
    +    RELEASE_STORE(&tso->why_blocked, BlockedOnCCall);
    
    2529 2529
       }
    
    2530 2530
     
    
    2531 2531
       // Hand back capability
    
    ... ... @@ -2583,16 +2583,25 @@ resumeThread (void *task_)
    2583 2583
         tso = incall->suspended_tso;
    
    2584 2584
         incall->suspended_tso = NULL;
    
    2585 2585
         incall->suspended_cap = NULL;
    
    2586
    +
    
    2587
    +    // we set why_blocked previously in suspendThread
    
    2588
    +    ASSERT(tso->why_blocked == BlockedOnCCall ||
    
    2589
    +           tso->why_blocked == BlockedOnCCall_Interruptible);
    
    2590
    +
    
    2586 2591
         // we will modify tso->_link
    
    2587 2592
         IF_NONMOVING_WRITE_BARRIER_ENABLED {
    
    2588 2593
             updateRemembSetPushClosure(cap, (StgClosure *)tso->_link);
    
    2589 2594
         }
    
    2590 2595
         tso->_link = END_TSO_QUEUE;
    
    2596
    +    // but no need to modify tso->block_info.prev as coincidentally
    
    2597
    +    // it has the value we want already (since in suspendThread we set
    
    2598
    +    // tso->block_info.unused to END_TSO_QUEUE for BlockedOnCCall).
    
    2599
    +    ASSERT(tso->block_info.prev == END_TSO_QUEUE);
    
    2591 2600
     
    
    2592 2601
         traceEventRunThread(cap, tso);
    
    2593 2602
     
    
    2594 2603
         /* Reset blocking status */
    
    2595
    -    tso->why_blocked  = NotBlocked;
    
    2604
    +    RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    2596 2605
     
    
    2597 2606
         if ((tso->flags & TSO_BLOCKEX) == 0) {
    
    2598 2607
             // avoid locking the TSO if we don't have to
    
    ... ... @@ -2944,8 +2953,9 @@ deleteThread (StgTSO *tso)
    2944 2953
         // The TSO must be on the run queue of the Capability we own, or
    
    2945 2954
         // we must own all Capabilities.
    
    2946 2955
     
    
    2947
    -    if (tso->why_blocked != BlockedOnCCall &&
    
    2948
    -        tso->why_blocked != BlockedOnCCall_Interruptible) {
    
    2956
    +    StgWord why_blocked = RELAXED_LOAD(&tso->why_blocked);
    
    2957
    +    if (why_blocked != BlockedOnCCall &&
    
    2958
    +        why_blocked != BlockedOnCCall_Interruptible) {
    
    2949 2959
             throwToSingleThreaded(tso->cap,tso,NULL);
    
    2950 2960
         }
    
    2951 2961
     }
    
    ... ... @@ -2956,10 +2966,12 @@ deleteThread_(StgTSO *tso)
    2956 2966
     { // for forkProcess only:
    
    2957 2967
       // like deleteThread(), but we delete threads in foreign calls, too.
    
    2958 2968
     
    
    2959
    -    if (tso->why_blocked == BlockedOnCCall ||
    
    2960
    -        tso->why_blocked == BlockedOnCCall_Interruptible) {
    
    2969
    +    StgWord why_blocked = RELAXED_LOAD(&tso->why_blocked);
    
    2970
    +    if (why_blocked == BlockedOnCCall ||
    
    2971
    +        why_blocked == BlockedOnCCall_Interruptible) {
    
    2961 2972
             tso->what_next = ThreadKilled;
    
    2962 2973
             appendToRunQueue(tso->cap, tso);
    
    2974
    +        RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    2963 2975
         } else {
    
    2964 2976
             deleteThread(tso);
    
    2965 2977
         }
    
    ... ... @@ -3310,7 +3322,7 @@ resurrectThreads (StgTSO *threads)
    3310 3322
             // Wake up the thread on the Capability it was last on
    
    3311 3323
             cap = tso->cap;
    
    3312 3324
     
    
    3313
    -        switch (tso->why_blocked) {
    
    3325
    +        switch (RELAXED_LOAD(&tso->why_blocked)) {
    
    3314 3326
             case BlockedOnMVar:
    
    3315 3327
             case BlockedOnMVarRead:
    
    3316 3328
                 /* Called by GC - sched_mutex lock is currently held. */
    

  • rts/Threads.c
    ... ... @@ -335,8 +335,8 @@ tryWakeupThread (Capability *cap, StgTSO *tso)
    335 335
     unblock:
    
    336 336
         // just run the thread now, if the BH is not really available,
    
    337 337
         // we'll block again.
    
    338
    -    tso->why_blocked = NotBlocked;
    
    339 338
         appendToRunQueue(cap,tso);
    
    339
    +    RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    340 340
     
    
    341 341
         // We used to set the context switch flag here, which would
    
    342 342
         // trigger a context switch a short time in the future (at the end
    
    ... ... @@ -368,7 +368,7 @@ migrateThread (Capability *from, StgTSO *tso, Capability *to)
    368 368
         // ThreadMigrating tells the target cap that it needs to be added to
    
    369 369
         // the run queue when it receives the MSG_TRY_WAKEUP.
    
    370 370
         tso->block_info.unused = END_TSO_QUEUE;
    
    371
    -    tso->why_blocked = ThreadMigrating;
    
    371
    +    RELEASE_STORE(&tso->why_blocked, ThreadMigrating);
    
    372 372
         tso->cap = to;
    
    373 373
         tryWakeupThread(from, tso);
    
    374 374
     }
    
    ... ... @@ -1017,7 +1017,7 @@ printAllThreads(void)
    1017 1017
       debugBelch("other threads:\n");
    
    1018 1018
       for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
    
    1019 1019
         for (t = generations[g].threads; t != END_TSO_QUEUE; t = next) {
    
    1020
    -      if (t->why_blocked != NotBlocked) {
    
    1020
    +      if (RELAXED_LOAD(&t->why_blocked) != NotBlocked) {
    
    1021 1021
               printThreadStatus(t);
    
    1022 1022
           }
    
    1023 1023
           next = t->global_link;
    

  • rts/TraverseHeap.c
    ... ... @@ -1242,15 +1242,12 @@ inner_loop:
    1242 1242
             traversePushClosure(ts, (StgClosure *) tso->blocked_exceptions, c, sep, child_data);
    
    1243 1243
             traversePushClosure(ts, (StgClosure *) tso->bq, c, sep, child_data);
    
    1244 1244
             traversePushClosure(ts, (StgClosure *) tso->trec, c, sep, child_data);
    
    1245
    -        switch (ACQUIRE_LOAD(&tso->why_blocked)) {
    
    1246
    -        case BlockedOnMVar:
    
    1247
    -        case BlockedOnMVarRead:
    
    1248
    -        case BlockedOnBlackHole:
    
    1249
    -        case BlockedOnMsgThrowTo:
    
    1245
    +
    
    1246
    +        StgWord why_blocked = ACQUIRE_LOAD(&tso->why_blocked);
    
    1247
    +        if (IsBlockInfoClosure(why_blocked) && why_blocked != NotBlocked) {
    
    1248
    +            // The NotBlocked case uses block_info.prev as a TSO back link.
    
    1249
    +            // Do not follow in that case or we'll get into a loop.
    
    1250 1250
                 traversePushClosure(ts, tso->block_info.closure, c, sep, child_data);
    
    1251
    -            break;
    
    1252
    -        default:
    
    1253
    -            break;
    
    1254 1251
             }
    
    1255 1252
             goto loop;
    
    1256 1253
         }
    

  • rts/posix/Poll.c
    ... ... @@ -146,8 +146,9 @@ bool syncIOWaitReadyPoll(Capability *cap, StgTSO *tso,
    146 146
         aiop->notify.tso     = tso;
    
    147 147
         aiop->notify_type    = NotifyTSO;
    
    148 148
         aiop->live           = &stg_ASYNCIO_LIVE0_closure;
    
    149
    -    tso->why_blocked     = rw == IORead ? BlockedOnRead : BlockedOnWrite;
    
    150 149
         tso->block_info.aiop = aiop;
    
    150
    +    RELEASE_STORE(&tso->why_blocked, rw == IORead ? BlockedOnRead
    
    151
    +                                                  : BlockedOnWrite);
    
    151 152
         return asyncIOWaitReadyPoll(cap, aiop, rw, fd);
    
    152 153
     }
    
    153 154
     
    
    ... ... @@ -258,10 +259,9 @@ static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop)
    258 259
                      * cap because the tso was not on the run queue of any cap and
    
    259 260
                      * so is not subject to thread migration.
    
    260 261
                      */
    
    261
    -                StgTSO *tso      = aiop->notify.tso;
    
    262
    -                tso->why_blocked = NotBlocked;
    
    263
    -                tso->_link       = END_TSO_QUEUE;
    
    262
    +                StgTSO *tso = aiop->notify.tso;
    
    264 263
                     pushOnRunQueue(cap, tso);
    
    264
    +                RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    265 265
                 }
    
    266 266
                 break;
    
    267 267
             }
    

  • rts/posix/Select.c
    ... ... @@ -105,11 +105,10 @@ static bool wakeUpSleepingThreads (Capability *cap, LowResTime now)
    105 105
                 break;
    
    106 106
             }
    
    107 107
             iomgr->sleeping_queue = tso->_link;
    
    108
    -        RELAXED_STORE(&tso->why_blocked, NotBlocked);
    
    109
    -        tso->_link = END_TSO_QUEUE;
    
    110 108
             IF_DEBUG(scheduler, debugBelch("Waking up sleeping thread %"
    
    111 109
                                            FMT_StgThreadID "\n", tso->id));
    
    112 110
             pushOnRunQueue(cap,tso);
    
    111
    +        RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    113 112
             flag = true;
    
    114 113
         }
    
    115 114
         return flag;
    
    ... ... @@ -397,7 +396,7 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
    397 396
                   int fd;
    
    398 397
                   enum FdState fd_state = RTS_FD_IS_BLOCKING;
    
    399 398
     
    
    400
    -              switch (UntagWhyBlocked(tso->why_blocked)) {
    
    399
    +              switch (UntagWhyBlocked(ACQUIRE_LOAD(&tso->why_blocked))) {
    
    401 400
                   case BlockedOnRead:
    
    402 401
                       fd = tso->block_info.fd;
    
    403 402
     
    
    ... ... @@ -436,9 +435,8 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
    436 435
                       IF_DEBUG(scheduler,
    
    437 436
                           debugBelch("Waking up blocked thread %" FMT_StgThreadID "\n",
    
    438 437
                                      tso->id));
    
    439
    -                  tso->why_blocked = NotBlocked;
    
    440
    -                  tso->_link = END_TSO_QUEUE;
    
    441 438
                       pushOnRunQueue(cap,tso);
    
    439
    +                  RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    442 440
                       break;
    
    443 441
                   case RTS_FD_IS_BLOCKING:
    
    444 442
                       if (prev == NULL)
    

  • rts/posix/Timeout.c
    ... ... @@ -48,8 +48,8 @@ bool syncDelayTimeout(Capability *cap, StgTSO *tso, HsInt us_delay)
    48 48
         initElemTimeoutQueue(timeout, notify, NotifyTSO, cap->r.rCCCS);
    
    49 49
     
    
    50 50
         ASSERT(tso->why_blocked == NotBlocked);
    
    51
    -    tso->why_blocked = BlockedOnDelay;
    
    52 51
         tso->block_info.timeout = timeout;
    
    52
    +    RELEASE_STORE(&tso->why_blocked, BlockedOnDelay);
    
    53 53
     
    
    54 54
         insertTimeoutQueue(&cap->iomgr->timeout_queue, timeout, target);
    
    55 55
     
    
    ... ... @@ -118,10 +118,10 @@ static void notifyTimeoutCompletion(Capability *cap, StgTimeout *timeout)
    118 118
         switch (timeout->notify_type) {
    
    119 119
             case NotifyTSO:
    
    120 120
             {
    
    121
    -            StgTSO *tso      = timeout->notify.tso;
    
    122
    -            tso->why_blocked = NotBlocked;
    
    123
    -            tso->_link       = END_TSO_QUEUE;
    
    121
    +            StgTSO *tso = timeout->notify.tso;
    
    122
    +            tso->_link  = END_TSO_QUEUE;
    
    124 123
                 pushOnRunQueue(cap, tso);
    
    124
    +            RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    125 125
                 break;
    
    126 126
             }
    
    127 127
             case NotifyMVar:
    

  • rts/sm/Compact.c
    ... ... @@ -468,16 +468,10 @@ thread_TSO (StgTSO *tso)
    468 468
         thread_(&tso->_link);
    
    469 469
         thread_(&tso->global_link);
    
    470 470
     
    
    471
    -    switch (ACQUIRE_LOAD(&tso->why_blocked)) {
    
    472
    -    case BlockedOnMVar:
    
    473
    -    case BlockedOnMVarRead:
    
    474
    -    case BlockedOnBlackHole:
    
    475
    -    case BlockedOnMsgThrowTo:
    
    476
    -    case NotBlocked:
    
    471
    +    if (IsBlockInfoClosure(ACQUIRE_LOAD(&tso->why_blocked))) {
    
    472
    +        /* This also follows the block_info.prev back-link in
    
    473
    +         * the NotBlocked case, which may not be necessary. */
    
    477 474
             thread_(&tso->block_info.closure);
    
    478
    -        break;
    
    479
    -    default:
    
    480
    -        break;
    
    481 475
         }
    
    482 476
         thread_(&tso->blocked_exceptions);
    
    483 477
         thread_(&tso->bq);
    

  • rts/sm/NonMovingMark.c
    ... ... @@ -1055,16 +1055,10 @@ trace_tso (MarkQueue *queue, StgTSO *tso)
    1055 1055
         if (tso->label != NULL) {
    
    1056 1056
             markQueuePushClosure_(queue, (StgClosure *) tso->label);
    
    1057 1057
         }
    
    1058
    -    switch (ACQUIRE_LOAD(&tso->why_blocked)) {
    
    1059
    -    case BlockedOnMVar:
    
    1060
    -    case BlockedOnMVarRead:
    
    1061
    -    case BlockedOnBlackHole:
    
    1062
    -    case BlockedOnMsgThrowTo:
    
    1063
    -    case NotBlocked:
    
    1058
    +    if (IsBlockInfoClosure(ACQUIRE_LOAD(&tso->why_blocked))) {
    
    1059
    +        /* This also follows the block_info.prev back-link in
    
    1060
    +         * the NotBlocked case, which may not be necessary. */
    
    1064 1061
             markQueuePushClosure_(queue, tso->block_info.closure);
    
    1065
    -        break;
    
    1066
    -    default:
    
    1067
    -        break;
    
    1068 1062
         }
    
    1069 1063
     }
    
    1070 1064
     
    

  • rts/sm/Sanity.c
    ... ... @@ -779,13 +779,45 @@ checkTSO(StgTSO *tso)
    779 779
                info == &stg_WHITEHOLE_info); // used to happen due to STM doing
    
    780 780
                                              // lockTSO(), might not happen now
    
    781 781
     
    
    782
    -    if (   tso->why_blocked == BlockedOnMVar
    
    783
    -        || tso->why_blocked == BlockedOnMVarRead
    
    784
    -        || tso->why_blocked == BlockedOnBlackHole
    
    785
    -        || tso->why_blocked == BlockedOnMsgThrowTo
    
    786
    -        || tso->why_blocked == NotBlocked
    
    787
    -        ) {
    
    782
    +    unsigned why_blocked = ACQUIRE_LOAD(&tso->why_blocked);
    
    783
    +    switch (why_blocked) {
    
    784
    +    case NotBlocked:
    
    785
    +    case BlockedOnMVar:
    
    786
    +    case BlockedOnMVarRead:
    
    787
    +    case BlockedOnBlackHole:
    
    788
    +    case BlockedOnMsgThrowTo:
    
    789
    +    case BlockedOnRead:
    
    790
    +    case BlockedOnWrite:
    
    791
    +    case BlockedOnDelay:
    
    792
    +        //TODO: we could be more specific and check BlockedOnMVar has an MVar,
    
    793
    +        // BlockedOnBlackHole has a message, BlockedOnRead has an AIOP etc.
    
    794
    +        ASSERT(IsBlockInfoClosure(why_blocked));
    
    788 795
             ASSERT(LOOKS_LIKE_CLOSURE_PTR(tso->block_info.closure));
    
    796
    +        break;
    
    797
    +
    
    798
    +    case BlockedOnSTM:
    
    799
    +    case BlockedOnCCall:
    
    800
    +    case BlockedOnCCall_Interruptible:
    
    801
    +    case ThreadMigrating:
    
    802
    +#if defined(mingw32_HOST_OS) && !defined(THREADED_RTS)
    
    803
    +    case BlockedOnDoProc:
    
    804
    +#endif
    
    805
    +        ASSERT(!IsBlockInfoClosure(why_blocked));
    
    806
    +        ASSERT(tso->block_info.unused == END_TSO_QUEUE);
    
    807
    +        break;
    
    808
    +
    
    809
    +#if !defined(THREADED_RTS)
    
    810
    +    // Only these three can use BlockInfoForceNonClosure
    
    811
    +    case BlockedOnRead  | BlockInfoForceNonClosure:
    
    812
    +    case BlockedOnWrite | BlockInfoForceNonClosure:
    
    813
    +    case BlockedOnDelay | BlockInfoForceNonClosure:
    
    814
    +        ASSERT(!IsBlockInfoClosure(why_blocked));
    
    815
    +        break;
    
    816
    +#endif
    
    817
    +
    
    818
    +    default:
    
    819
    +        barf("checkTSO: strange tso->why_blocked: %d for TSO %"
    
    820
    +             FMT_StgThreadID " (%p)", why_blocked, tso->id, tso);
    
    789 821
         }
    
    790 822
     
    
    791 823
         ASSERT(LOOKS_LIKE_CLOSURE_PTR(tso->bq));
    

  • rts/sm/Scav.c
    ... ... @@ -138,21 +138,9 @@ scavengeTSO (StgTSO *tso)
    138 138
             evacuate((StgClosure **)&tso->label);
    
    139 139
         }
    
    140 140
     
    
    141
    -    switch (ACQUIRE_LOAD(&tso->why_blocked)) {
    
    142
    -    case BlockedOnMVar:
    
    143
    -    case BlockedOnMVarRead:
    
    144
    -    case BlockedOnBlackHole:
    
    145
    -    case BlockedOnMsgThrowTo:
    
    146
    -    case NotBlocked:
    
    141
    +    if (IsBlockInfoClosure(ACQUIRE_LOAD(&tso->why_blocked))) {
    
    147 142
             evacuate(&tso->block_info.closure);
    
    148
    -        break;
    
    149
    -    case BlockedOnRead:
    
    150
    -    case BlockedOnWrite:
    
    151
    -    case BlockedOnDelay:
    
    152
    -    case BlockedOnDoProc:
    
    153
    -        scavengeTSOIOManager(tso);
    
    154
    -        break;
    
    155
    -    default:
    
    143
    +    } else {
    
    156 144
     #if defined(THREADED_RTS)
    
    157 145
         // in the THREADED_RTS, block_info.closure must always point to a
    
    158 146
         // valid closure, because we assume this in throwTo().  In the
    
    ... ... @@ -160,7 +148,6 @@ scavengeTSO (StgTSO *tso)
    160 148
         // BlockedOnRead/BlockedOnWrite) or a time value (BlockedOnDelay)
    
    161 149
             ASSERT(tso->block_info.unused == END_TSO_QUEUE);
    
    162 150
     #endif
    
    163
    -        break;
    
    164 151
         }
    
    165 152
     
    
    166 153
         tso->dirty = gct->failed_to_evac;
    

  • rts/win32/AsyncMIO.c
    ... ... @@ -318,8 +318,6 @@ start:
    318 318
                             }
    
    319 319
     
    
    320 320
                             // Terminates the run queue + this inner for-loop.
    
    321
    -                        tso->_link = END_TSO_QUEUE;
    
    322
    -                        tso->why_blocked = NotBlocked;
    
    323 321
                             // For stg_block_async frames (read/write/doProc),
    
    324 322
                             // write len and errCode directly to the stack.
    
    325 323
                             // For stg_block_noregs frames (delay), nothing
    
    ... ... @@ -329,14 +327,14 @@ start:
    329 327
                                 tso->stackobj->sp[2] = (W_)errCode;
    
    330 328
                             }
    
    331 329
                             pushOnRunQueue(&MainCapability, tso);
    
    330
    +                        RELEASE_STORE(&tso->why_blocked, NotBlocked);
    
    332 331
                             break;
    
    333 332
                         }
    
    334 333
                         break;
    
    335
    -                default:
    
    336
    -                    if (tso->why_blocked != NotBlocked) {
    
    337
    -                        barf("awaitRequests: odd thread state");
    
    338
    -                    }
    
    334
    +                case NotBlocked:
    
    339 335
                         break;
    
    336
    +                default:
    
    337
    +                    barf("awaitRequests: odd thread state");
    
    340 338
                     }
    
    341 339
     
    
    342 340
                     prev = tso;