ruby: mesi coherence protocol: invalidate lock
The MESI CMP directory coherence protocol, while transitioning from SM to IM, did not invalidate the lock that it might have taken on a cache line. This patch adds an action for doing so. The problem was found by Dibakar, but I was not happy with his proposed solution. So I implemented a different solution. Committed by: Nilay Vaish <nilay@cs.wisc.edu>
This commit is contained in:
parent
82cf1565d0
commit
c636a09e83
|
@ -782,6 +782,11 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
|
|||
}
|
||||
}
|
||||
|
||||
action(dg_invalidate_sc, "dg",
|
||||
desc="Invalidate store conditional as the cache lost permissions") {
|
||||
sequencer.invalidateSC(address);
|
||||
}
|
||||
|
||||
action(h_load_hit, "h", desc="If not prefetch, notify sequencer the load completed.") {
|
||||
assert(is_valid(cache_entry));
|
||||
DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
|
||||
|
@ -1251,7 +1256,7 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
|
|||
}
|
||||
|
||||
// Transitions from IM
|
||||
transition({IM, SM}, Inv, IM) {
|
||||
transition(IM, Inv, IM) {
|
||||
fi_sendInvAck;
|
||||
l_popRequestQueue;
|
||||
}
|
||||
|
@ -1292,6 +1297,12 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
|
|||
}
|
||||
|
||||
// transitions from SM
|
||||
transition(SM, Inv, IM) {
|
||||
fi_sendInvAck;
|
||||
dg_invalidate_sc;
|
||||
l_popRequestQueue;
|
||||
}
|
||||
|
||||
transition({SM, IM, PF_SM, PF_IM}, Ack) {
|
||||
q_updateAckCount;
|
||||
o_popIncomingResponseQueue;
|
||||
|
|
|
@ -110,6 +110,7 @@ structure (Sequencer, external = "yes") {
|
|||
void evictionCallback(Address);
|
||||
void recordRequestType(SequencerRequestType);
|
||||
bool checkResourceAvailable(CacheResourceType, Address);
|
||||
void invalidateSC(Address);
|
||||
}
|
||||
|
||||
structure(RubyRequest, desc="...", interface="Message", external="yes") {
|
||||
|
|
|
@ -306,6 +306,20 @@ Sequencer::removeRequest(SequencerRequest* srequest)
|
|||
markRemoved();
|
||||
}
|
||||
|
||||
void
|
||||
Sequencer::invalidateSC(const Address& address)
|
||||
{
|
||||
RequestTable::iterator i = m_writeRequestTable.find(address);
|
||||
if (i != m_writeRequestTable.end()) {
|
||||
SequencerRequest* request = i->second;
|
||||
// The controller has lost the coherence permissions, hence the lock
|
||||
// on the cache line maintained by the cache should be cleared.
|
||||
if (request->m_type == RubyRequestType_Store_Conditional) {
|
||||
m_dataCache_ptr->clearLocked(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Sequencer::handleLlsc(const Address& address, SequencerRequest* request)
|
||||
{
|
||||
|
@ -392,7 +406,6 @@ Sequencer::writeCallback(const Address& address,
|
|||
(request->m_type == RubyRequestType_Locked_RMW_Write) ||
|
||||
(request->m_type == RubyRequestType_FLUSH));
|
||||
|
||||
|
||||
//
|
||||
// For Alpha, properly handle LL, SC, and write requests with respect to
|
||||
// locked cache blocks.
|
||||
|
|
|
@ -116,6 +116,7 @@ class Sequencer : public RubyPort
|
|||
void markRemoved();
|
||||
void removeRequest(SequencerRequest* request);
|
||||
void evictionCallback(const Address& address);
|
||||
void invalidateSC(const Address& address);
|
||||
|
||||
void recordRequestType(SequencerRequestType requestType);
|
||||
|
||||
|
|
Loading…
Reference in a new issue