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

Commits:

2 changed files:

Changes:

  • rts/CloneStack.c
    ... ... @@ -88,6 +88,7 @@ void sendCloneStackMessage(StgTSO *tso, HsStablePtr mvar) {
    88 88
     void handleCloneStackMessage(Capability *cap, MessageCloneStack *msg){
    
    89 89
       // We must check that the current owner of the thread we want to clone the stack for
    
    90 90
       // is still this capability.
    
    91
    +  // See Note [TSO owner may change in between Msg being sent and received]
    
    91 92
       Capability *owner = RELAXED_LOAD(&msg->tso->cap);
    
    92 93
       if (owner != cap) {
    
    93 94
         // The target TSO may have migrated after the message was queued on the old
    

  • rts/Messages.c
    ... ... @@ -66,6 +66,48 @@ void sendMessage(Capability *from_cap, Capability *to_cap, Message *msg)
    66 66
        Handle a message
    
    67 67
        ------------------------------------------------------------------------- */
    
    68 68
     
    
    69
    +/*
    
    70
    +Note [TSO owner may change in between Msg being sent and received]
    
    71
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    72
    +When a message is sent from Capability (C1) to a target TSO (T2) (e.g.
    
    73
    +MessageUpdTSOFlag, MessageCloneStack, ...), it is queued on the TSO's owner
    
    74
    +Capability (C3) inbox (inboxes are owned by Capabilities, not TSOs).
    
    75
    +
    
    76
    +At a later point, the Capability (C3) will process its inbox. Upon receiving
    
    77
    +the message meant for a specific TSO (T2), it must first always check that the
    
    78
    +TSO's owner is *still* itself (C3).
    
    79
    +
    
    80
    +The target TSO (T2) may have migrated after the message was queued on its old
    
    81
    +capability (C3). In that case we must forward the request to the new owner
    
    82
    +(say, C4); otherwise the Capability C3 could be modifying a TSO it no longer
    
    83
    +owns, racing with its actual owner mutating it, since it is no longer the owner.
    
    84
    +
    
    85
    +The message meant for a TSO should only be executed when the receiving
    
    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:
    
    89
    +
    
    90
    +  executeMessage(...) {
    
    91
    +
    
    92
    +    if (i == &stg_MY_MSG_info) {
    
    93
    +
    
    94
    +      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(...)
    
    103
    +
    
    104
    +    }
    
    105
    +  }
    
    106
    +
    
    107
    +See `executeMessage`'s `stg_MSG_UPD_TSO_FLAG_info` and
    
    108
    +`stg_MSG_CLONE_STACK_info` for two live examples.
    
    109
    +*/
    
    110
    +
    
    69 111
     #if defined(THREADED_RTS)
    
    70 112
     
    
    71 113
     void
    
    ... ... @@ -142,12 +184,18 @@ loop:
    142 184
         }
    
    143 185
         else if(i == &stg_MSG_UPD_TSO_FLAG_info){
    
    144 186
             MessageUpdTSOFlag *u = (MessageUpdTSOFlag*) m;
    
    145
    -        if (u->set) {
    
    146
    -            u->tso->flags |= u->flag;
    
    147
    -        }
    
    148
    -        else {
    
    149
    -            u->tso->flags &= ~u->flag;
    
    187
    +
    
    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;
    
    150 194
             }
    
    195
    +
    
    196
    +        if (u->set) { u->tso->flags |= u->flag;  }
    
    197
    +        else        { u->tso->flags &= ~u->flag; }
    
    198
    +
    
    151 199
             return;
    
    152 200
         }
    
    153 201
         else