ruby: mesi coherence protocol: invalidate lock
authorDibakar Gope ext:(%2C%20Nilay%20Vaish%20%3Cnilay%40cs.wisc.edu%3E) <gope@wisc.edu>
Thu, 28 Feb 2013 16:04:26 +0000 (10:04 -0600)
committerDibakar Gope ext:(%2C%20Nilay%20Vaish%20%3Cnilay%40cs.wisc.edu%3E) <gope@wisc.edu>
Thu, 28 Feb 2013 16:04:26 +0000 (10:04 -0600)
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>

src/mem/protocol/MESI_CMP_directory-L1cache.sm
src/mem/protocol/RubySlicc_Types.sm
src/mem/ruby/system/Sequencer.cc
src/mem/ruby/system/Sequencer.hh

index 113421842cae66fd236eeb5aa008dc95648f3b78..f8d731ee1aa99c54f3b8c19f2adab21ab929f84d 100644 (file)
@@ -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;
index 096215386fd48ebb4ac8cf245be83bc14e8b36fb..c94020792d344f222fe4c7e2387f2f753aa93c84 100644 (file)
@@ -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") {
index f00f8407ad188328cefd2e97166e100e0ea7d0f4..54fb83dd0daf66464224d8ad118ee048119d03ef 100644 (file)
@@ -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.
index b3ec4d10aa45917c8fee2c500b08f49ed4c266f2..782b776f9fa306a02abdb9ee2108ea4521e0d9e2 100644 (file)
@@ -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);