So let's look at the write-update snooping coherence first,
let's look at two caches only, each of which has two blocks, with a single
valid bit per block in the tag, and then the data, and both of these caches
are connected to the same bus, to which we also connect the memory.
So now let's say that the caches are initially empty, so
the value bits are all zero, and this processor reads something in block A.
We have a cache miss here, we send the request to memory.
This cache is always monitoring what's going on, on the bus, but
it's only interested in writes.
So this read is really going to be seen and ignored by this cache.
The data for A comes back from memory and now we put this block in the cache,
and the block becomes valid and
the title message just indicates that's this is the block A.
Now let's say that this processor writes to A.
So now we have a situation, where this processor,
even if it does a write through access directly to memory,
a read on this processor would still read the stale value of A.
Let's say that the value we read here was 0.
Now let's say that this processor writes 1 to A.
This write, even if we made it go all the way to memory,
would not result in coherent behavior for this cache,
because a subsequent read here will still hit in the cache and get the 0.
So this is when write update and snooping come into the picture.
We have a cache miss, but because it's a write we send
a request for the block along with an indication that it's a write, and
what is the value and what's the address.
So now what happens is this request goes to memory, and the memory writes 1 to A.
But more importantly this cache is monitoring the bus and
sees that block A is being updated.
It checks its internal state and sees that it has block A, and
then it takes the value that is being written.
So this part is the snooping part where we see what's going on on the bus.
So we cannot miss any of the writes happening on another core,
because we are monitoring the bus, and all writes have to go through the bus.
That's the snooping part.
The right update part is that when we see a write,
we update our copy of the data with the value that is being written.
So this cache now gets a 1 here, if we read A after this,
we're going to get this one, so this ensures correct behavior.
If there are multiple cores, they can not disagree about which right happened
first, which one happened last because all of the rights are sent through
the bus and because it's a single brotecuz bus, it happens one at a time.
So all of them see rights,
in exactly the same order, in the order in which writes go to the bus.
Now let's see what happens if both of these processors
tried to write to A at about the same time.
So this is a situation where they might disagree about whose write
happened first.
Let's say that this one is trying to write 2 and
this one is trying to write 3.
Well there is a single bus, so there is a single set of wires that can carry
the value and the address and so on.
So processors, when they want to send something on the bus,
first have to arbitrate for it, and this arbitration for
the bus basically decides who gets the bus next.
If this core won, then it sends its write first,
now both of the caches will have two.
This one because this is where the write happened.
This one because this is what we pick up from snooping, and
only then, after this is complete, this right here gets to occur, so
now we go to 3, broadcast that here, and it gets here.
So as you can see, both of them agree which write was first and
which was second.
Obviously, the one that wrote 3 was the second one,
because that's the last value we kept.
So the write update is ensuring that writes are seen
by reads on all cores, and the snooping of the common bus and
the serialization on that bus, basically going one at a time to the bus is
guaranteeing that everybody sees the same order of writes.