In MSI and MESI a remote read of an M line ends with S/S, and settled S/S requires memory to be current, so H writes memory on every M-to-S downgrade. MOESI lets C0 go from M to O instead: C0 keeps dirty responsibility, C1 gets S, and memory stays stale. The trace of that first dirty read is in MOESI and Dirty Sharing. This lesson continues it into a second round and counts.
MESI writes memory once per dirty read. MOESI writes once, when C0's PutM finally leaves, so R rounds of write-then-read save R - 1 writes. A single dirty read followed by eviction saves nothing. The cost is that memory can no longer answer: every later reader must be forwarded to C0, and C0 must eventually send PutM so that H writes memory once.
Continue the pilot trace with the same roles: C0 is the producer, C1 the consumer. Checkpoint after round 1: C0 O / 1, C1 S / 1, H O: C0, sharers {C1}, memory = 0. C0 stores 2, then C1 reads again. OM^D is the O analogue of SM^D: was O, wants M, waiting for Data, loads hit and stores stall.
Step | C0 state / value | C1 state / value | H directory | Memory | Newest data |
|---|---|---|---|---|---|
Checkpoint | O / 1 | S / 1 | O: C0, sharers {C1} | 0 | C0 and C1: 1 |
1. GetM at H | OM^D / 1 | S / 1 | O: C0, sharers {C1}, pend GetM C0, acks 0/1 | 0 | C0 and C1: 1 |
2. Inv at C1 | OM^D / 1 | I / - | O: C0, sharers {C1}, pend GetM C0, acks 0/1 | 0 | C0: 1 |
3. Inv-Ack at H | OM^D / 1 | I / - | O: C0, pend GetM C0, acks 1/1 | 0 | C0: 1 |
4. Data at C0 | M / 1 | I / - | O: C0, pend GetM C0, acks 1/1 | 0 | C0: 1 |
(assumed) grant delivered | M / 1 | I / - | exclusive(C0) | 0 | C0: 1 |
L2. Local store | M / 2 | I / - | exclusive(C0) | 0 | C0: 2 |
5. GetS at H | M / 2 | IS^D / - | exclusive(C0), pend GetS C1 | 0 | C0: 2 |
6. Fwd-GetS at C0 | O / 2 | IS^D / - | exclusive(C0), pend GetS C1 | 0 | C0: 2, Data(2) in flight to H |
7. Data at H | O / 2 | IS^D / - | O: C0, pend GetS C1 | 0 | C0 and H buffer: 2, Data(2) in flight to C1 |
8. Data at C1 | O / 2 | S / 2 | O: C0, pend GetS C1 | 0 | C0 and C1: 2, C0 dirty-responsible |
(assumed) grant delivered | O / 2 | S / 2 | O: C0, sharers {C1} | 0 | C0 and C1: 2, C0 dirty-responsible |
Memory still holds 0 after two write epochs. Under MESI the same round sends the same eight messages (the S upgrade of Upgrade from Shared, then the dirty read of MSI Protocol), but H writes memory at step 7, once per round.
Two-core pattern (illustrative) | MESI messages | MESI memory writes | MOESI messages | MOESI memory writes |
|---|---|---|---|---|
Round 1: cold store, one dirty read | 2 + 4 | 1 | 2 + 4 | 0 |
Each later round: upgrade, store, dirty read | 4 + 4 | 1 | 4 + 4 | 0 |
End: C0 evicts (PutS or PutM, Put-Ack) | 2 | 0 | 2 | 1 |
Total for 3 rounds | 24 | 3 | 24 | 1 |
With one consumer, O is a pure saving: the same messages, and R memory writes become one. The R writes are coalesced into one: R - 1 never happen, and the last is deferred to C0's PutM, so only the final value reaches memory.
O breaks even or loses when the dirty read is not followed by another read or write before eviction: C0 stores, C1 reads, C0 evicts. MESI writes memory at the read and C0 leaves with a clean PutS. MOESI skips that write, then C0's PutM writes it. One memory write each, but MOESI also carried a dirty-responsible copy and its eviction carried data. O also adds traffic when there are several readers: through H, each later reader is a four-leg forwarded read instead of a two-leg memory read. That is good when memory bandwidth is scarce, and bad when the interconnect is.
One each. MESI writes memory at the dirty read and C0 later evicts its S copy with PutS, which writes nothing. MOESI skips the write at the read, but C0 leaves O with PutM and H writes memory then. O only moved the write.