Both requests can be in flight without both permissions being granted. Begin after completed reads from reset X = 0: C0 S / 0, C1 S / 0, H S{C0,C1}, memory = 0. Select MSI. H accepts A from C0 first and queues B from C1, rather than rejecting B. C0 writes first; C1 waits and writes next.
Both cores enter SM^D for their local store requests. The losing C1 must still process Inv while its own GetM is queued. It loses its S bytes, acknowledges and becomes IM^D with a pending store. H must then supply a current value for B, not a permission-only upgrade. C0 performs its store of 1 before it answers the Fwd-GetM for B, by the policy below. In the table, queued GetM C1 means B waits in H's queue for X.
Step | C0 state / value | C1 state / value | H directory | Memory | Newest data |
|---|---|---|---|---|---|
Initial | S / 0 | S / 0 | S{C0,C1} | 0 | C0, C1 and memory: 0 |
1. GetM A at H | SM^D / 0 | S / 0 | S{C0,C1}, pend GetM C0, acks 0/1 | 0 | C0, C1 and memory: 0 |
2. GetM B at H | SM^D / 0 | SM^D / 0 | S{C0,C1}, pend GetM C0, acks 0/1, queued GetM C1 | 0 | C0, C1 and memory: 0 |
3. Inv at C1 | SM^D / 0 | IM^D / - | S{C0,C1}, pend GetM C0, acks 0/1, queued GetM C1 | 0 | C0 and memory: 0 |
4. Inv-Ack at H | SM^D / 0 | IM^D / - | S{C0}, pend GetM C0, acks 1/1, queued GetM C1 | 0 | C0 and memory: 0 |
5. Data at C0 | M / 0 | IM^D / - | S{C0}, pend GetM C0, acks 1/1, queued GetM C1 | 0 | C0 and memory: 0 |
(assumed) grant delivered | M / 0 | IM^D / - | exclusive(C0), queued GetM C1 | 0 | C0 and memory: 0 |
L. Local store | M / 1 | IM^D / - | exclusive(C0), queued GetM C1 | 0 | C0: 1 |
6. Fwd-GetM at C0 | I / - | IM^D / - | exclusive(C0), pend GetM C1 | 0 | Data(1) in flight to H |
7. Data at H | I / - | IM^D / - | exclusive(C0), pend GetM C1 | 0 | H buffer: 1, Data(1) in flight to C1 |
8. Data at C1 | I / - | M / 1 | exclusive(C0), pend GetM C1 | 0 | C1: 1 |
(assumed) grant delivered | I / - | M / 1 | exclusive(C1) | 0 | C1: 1 |
L. Local store | I / - | M / 2 | exclusive(C1) | 0 | C1: 2 |
H knows C1's copy is gone through the matching Inv-Ack, not through B's arrival or C1's intention to write. H starts B only after A's grant has been delivered (the grant-delivery rule). Data(1) carries the value from step 6 to step 7, and H's buffer holds it until step 8. Memory stays stale legally because the final holder is dirty and exclusive.
If C1 refused Inv until B completed, A would wait for C1 while B waited behind A: a protocol dependency cycle. The chosen policy lets the Inv change C1's pending state without cancelling the processor store. This example uses a queue at H, not a NACK.
No. A is selected first and needs its old reader revoked. C1 acknowledges after losing that permission, retains its store intent, and later acquires a fresh current value for B.