C0 has read X. C1 now wants to store 1. Is sending an invalidation enough? No: the old reader must lose permission before the new writer receives it. Prerequisite: S is read-only, I has no usable value, and write permission excludes other usable copies. This example selects MSI, so the first cold read grants S rather than MESI's optional E.
Reset the course machine: memory holds X = 0 and neither cache has a copy. H serializes conflicting transactions for X. Transaction A completes before B starts; the local store follows B's Data delivery.
Step | C0 state / value | C1 state / value | H directory | Memory | Newest data |
|---|---|---|---|---|---|
Initial | I / - | I / - | U | 0 | Memory: 0 |
1. GetS received | IS^D / - | I / - | U, pend GetS C0 | 0 | Memory: 0 |
2. Data received | S / 0 | I / - | U, pend GetS C0 | 0 | C0 and memory: 0 |
(assumed) grant delivered | S / 0 | I / - | S{C0} | 0 | C0 and memory: 0 |
3. GetM received | S / 0 | IM^D / - | S{C0}, pend GetM C1, acks 0/1 | 0 | C0 and memory: 0 |
4. Inv received | I / - | IM^D / - | S{C0}, pend GetM C1, acks 0/1 | 0 | Memory: 0 |
5. Inv-Ack received | I / - | IM^D / - | U, pend GetM C1, acks 1/1 | 0 | Memory: 0 |
6. Data received | I / - | M / 0 | U, pend GetM C1, acks 1/1 | 0 | C1 and memory: 0 |
(assumed) grant delivered | I / - | M / 0 | exclusive(C1) | 0 | C1 and memory: 0 |
L. Local store | I / - | M / 1 | exclusive(C1) | 0 | C1: 1 |
C1 is in IM^D ('was I, wants M, waiting for Data') from step 3 to step 6: it waits only for Data, because H collects the acknowledgement. While H awaits C0's acknowledgement its recorded sharer can conservatively outlive C0's actual copy (step 4). At step 5 H has no sharers left (U), but the pending GetM keeps it busy; it is not free for another request. H keeps that pending entry in the step-6 row and records exclusive(C1) only in the '(assumed) grant delivered' row: it starts no conflicting transaction for X until the step-6 grant has been delivered.
Step 4 removes C0's permission. Step 5 tells H it has been removed. Only then may H send step 6. This causal wait establishes safety without relying on any message order. No core can write in the initial idle/read epoch; C1 cannot write during its pending request. M / 0 at step 6 is a conservative dirty-responsibility state even though the stored bits still match memory; L makes the difference visible.
If C1 had already held a valid S copy, the upgrade would still wait for the required acknowledgement and end with permission-only Data, as in Epochs and Serialization. Real controllers track the same outstanding work in transient states: compare the descriptions in the gem5 MESI Two Level documentation.
No. H has the evidence, but C1 is still in IM^D and has no usable value or write permission. C1 must receive Data with M permission at step 6 before the local store.