diff --git a/cache/coherence.hpp b/cache/coherence.hpp index a44b070..1c7b01c 100644 --- a/cache/coherence.hpp +++ b/cache/coherence.hpp @@ -163,16 +163,10 @@ class OuterCohPortT : public OPUC CMDataBase *data = nullptr; if constexpr (EnMT) { - while(true) { - hit = cache->hit(addr, &ai, &s, &w, XactPrio::probe, true); - if(hit) { - std::tie(meta, data) = cache->access_line(ai, s, w); meta->lock(); - if(!meta->match(addr)) { // cache line is invalidated by transactions with higher priority - meta->unlock(); meta = nullptr; data = nullptr; - cache->reset_mt_state(ai, s, XactPrio::probe); continue; // redo the hit check - } - } - break; + hit = cache->hit(addr, &ai, &s, &w, XactPrio::probe, true); + if(hit) { + std::tie(meta, data) = cache->access_line(ai, s, w); meta->lock(); + assert(meta->match(addr)); // probe is the highest priority and nobody should intercept a probe after it locked a set } } else { hit = cache->hit(addr, &ai, &s, &w); @@ -187,11 +181,9 @@ class OuterCohPortT : public OPUC if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); } - // writeback if dirty - if((writeback = Policy::probe_need_writeback(outer_cmd, meta))) { - if(data_outer) data_outer->copy(data); - } - if constexpr (EnMT) meta_outer->lock(); + // now we should be able to safely operate on the cache line + if constexpr (EnMT) {assert(meta->match(addr)); meta_outer->lock(); } + if((writeback = Policy::probe_need_writeback(outer_cmd, meta))) { if(data_outer) data_outer->copy(data); } // writeback if dirty Policy::meta_after_probe(outer_cmd, meta, meta_outer, coh_id, writeback); // alway update meta cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(outer_cmd), writeback, meta, data, delay); if constexpr (EnMT) { meta_outer->unlock(); meta->unlock(); cache->reset_mt_state(ai, s, XactPrio::probe); } @@ -402,7 +394,7 @@ class InnerCohPortT : public IPUC auto [valid, forward, meta, ai, s] = pending_xact.read(addr, outer_cmd.id); if(valid) { // avoid probe to the same cache line happens between a grant and a finish, - // unlock the cache line until a finish is received (only needed for coherent inner cache) + // do not unlock the cache line until a finish is received (only needed for coherent inner cache) if constexpr (EnMT) { meta->unlock(); cache->reset_mt_state(ai, s, XactPrio::acquire); } pending_xact.remove(addr, outer_cmd.id); if(forward) outer->finish_req(addr);