Rodrigo Mesquita pushed to branch wip/romes/27729 at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • rts/Messages.c
    ... ... @@ -84,27 +84,41 @@ owns, racing with its actual owner mutating it, since it is no longer the owner.
    84 84
     
    
    85 85
     The message meant for a TSO should only be executed when the receiving
    
    86 86
     Capability is still the owner of that TSO. Otherwise, it must be forwarded to
    
    87
    -the new owner. The pseudo code for handling a message that targets a particular
    
    88
    -TSO will look something like:
    
    87
    +the new owner.
    
    88
    +
    
    89
    +The general pattern is one where there's a top-level function which assumes can
    
    90
    +be called by capabilities other than the TSO's owner. The function checks
    
    91
    +whether the current capability is the TSO owner. If yes, execute the action. If
    
    92
    +not, then it sends a message to the current TSO's owner. On receiving the
    
    93
    +message, the new capability will just call that top-level function, which will
    
    94
    +ensure the message is forwarded again if the TSO owner changed.
    
    95
    +It will look something like:
    
    96
    +
    
    97
    +  runMyMsg(Capability *from, StgTSO *target, ...) {
    
    98
    +
    
    99
    +#if defined(THREADED_RTS)
    
    100
    +    Capability *owner = RELAXED_LOAD(&target->cap)
    
    101
    +    if (owner != from) {
    
    102
    +      MessageMyMsg* msg = ...
    
    103
    +      sendMessage(cap, owner, msg)
    
    104
    +      return
    
    105
    +    }
    
    106
    +#endif
    
    107
    +
    
    108
    +    actuallyDoTheWork(...)
    
    109
    +  }
    
    89 110
     
    
    90 111
       executeMessage(...) {
    
    91 112
     
    
    92 113
         if (i == &stg_MY_MSG_info) {
    
    93 114
     
    
    94 115
           MessageMyMsg* msg = (MessageMyMsg*) m
    
    95
    -
    
    96
    -      Capability *owner = RELAXED_LOAD(&msg->tso->cap);
    
    97
    -      if (owner != cap) {
    
    98
    -        sendMessage(cap, owner, (Message *)msg);
    
    99
    -        return;
    
    100
    -      }
    
    101
    -
    
    102
    -      actuallyExecute(...)
    
    116
    +      runMyMsg(cap, m->tso, ...)
    
    103 117
     
    
    104 118
         }
    
    105 119
       }
    
    106 120
     
    
    107
    -See `executeMessage`'s `stg_MSG_UPD_TSO_FLAG_info` and
    
    121
    +See example `updThreadFlag` and `executeMessage`'s `stg_MSG_UPD_TSO_FLAG_info`, or
    
    108 122
     `stg_MSG_CLONE_STACK_info` for two live examples.
    
    109 123
     */
    
    110 124
     
    
    ... ... @@ -185,18 +199,8 @@ loop:
    185 199
         else if(i == &stg_MSG_UPD_TSO_FLAG_info){
    
    186 200
             MessageUpdTSOFlag *u = (MessageUpdTSOFlag*) m;
    
    187 201
     
    
    188
    -        // We must check that the current owner of the thread is still this capability.
    
    189
    -        // See Note [TSO owner may change in between Msg being sent and received]
    
    190
    -        Capability *owner = RELAXED_LOAD(&u->tso->cap);
    
    191
    -        if (owner != cap) {
    
    192
    -          sendMessage(cap, owner, (Message *)u);
    
    193
    -          return;
    
    194
    -        }
    
    195
    -
    
    196
    -        if (u->set) { u->tso->flags |= u->flag;  }
    
    197
    -        else        { u->tso->flags &= ~u->flag; }
    
    198
    -
    
    199
    -        return;
    
    202
    +        StgTSO *tso = RELAXED_LOAD(&u->tso);
    
    203
    +        updThreadFlag(cap, tso, u->flag, u->set);
    
    200 204
         }
    
    201 205
         else
    
    202 206
         {
    

  • rts/Threads.c
    ... ... @@ -379,23 +379,25 @@ migrateThread (Capability *from, StgTSO *tso, Capability *to)
    379 379
        sets or unsets a flag in a given TSO
    
    380 380
        ------------------------------------------------------------------------- */
    
    381 381
     
    
    382
    -static void
    
    383
    -updThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag, StgBool set);
    
    384
    -
    
    385 382
     void setThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag)
    
    386 383
     {
    
    387
    -    updThreadFlag(from, tso, flag, 1);
    
    384
    +    updThreadFlag(from, tso, flag, true);
    
    388 385
     }
    
    389 386
     
    
    390 387
     void unsetThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag)
    
    391 388
     {
    
    392
    -    updThreadFlag(from, tso, flag, 0);
    
    389
    +    updThreadFlag(from, tso, flag, false);
    
    393 390
     }
    
    394 391
     
    
    395
    -static void
    
    396
    -updThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag, StgBool set /* true=set, false=unset */)
    
    392
    +void
    
    393
    +updThreadFlag(Capability *from USED_IF_THREADS, StgTSO *tso, StgWord32 flag, StgBool set /* true=set, false=unset */)
    
    397 394
     {
    
    398 395
     #if defined(THREADED_RTS)
    
    396
    +    // If we're the current owner of the thread we want to modify, do it.
    
    397
    +    // Otherwise, we must forward the message to the actual owner.
    
    398
    +    // When executing the upd message, we check again that we're still the TSO
    
    399
    +    // owner (which may have changed since the message was queued on this cap.)
    
    400
    +    // See Note [TSO owner may change in between Msg being sent and received]
    
    399 401
         Capability *tso_owner = RELAXED_LOAD(&tso->cap);
    
    400 402
         if (from != tso_owner) {
    
    401 403
           MessageUpdTSOFlag *msg;
    
    ... ... @@ -407,8 +409,6 @@ updThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag, StgBool set /* true
    407 409
           sendMessage(from, tso_owner, (Message*)msg);
    
    408 410
           return;
    
    409 411
         }
    
    410
    -#else
    
    411
    -    (void)from; // unused in non-threaded case
    
    412 412
     #endif
    
    413 413
     
    
    414 414
         if (set) {
    

  • rts/Threads.h
    ... ... @@ -21,6 +21,7 @@ void migrateThread (Capability *from, StgTSO *tso, Capability *to);
    21 21
     
    
    22 22
     void setThreadFlag       (Capability *from, StgTSO *tso, StgWord32 flag);
    
    23 23
     void unsetThreadFlag     (Capability *from, StgTSO *tso, StgWord32 flag);
    
    24
    +void updThreadFlag       (Capability *from, StgTSO *tso, StgWord32 flag, StgBool set);
    
    24 25
     
    
    25 26
     // Wakes up a thread on a Capability (probably a different Capability
    
    26 27
     // from the one held by the current Task).