summaryrefslogtreecommitdiff
path: root/src/mem/cache/mshr.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-12-17 17:07:11 -0500
committerAndreas Hansson <andreas.hansson@arm.com>2015-12-17 17:07:11 -0500
commit97887eb6dc9e548c9b5719727fd4783ef157917c (patch)
tree65b928581be0e6135b1c7b3ca1ffecf63059e3b2 /src/mem/cache/mshr.cc
parent08754488a30da178effd0414f198462bf268d715 (diff)
downloadgem5-97887eb6dc9e548c9b5719727fd4783ef157917c.tar.xz
mem: Fix memory allocation bug in deferred snoop handling
This patch fixes a corner case in the deferred snoop handling, where requests ended up being used by multiple packets with different lifetimes, and inadvertently got deleted while they were still in use.
Diffstat (limited to 'src/mem/cache/mshr.cc')
-rw-r--r--src/mem/cache/mshr.cc37
1 files changed, 19 insertions, 18 deletions
diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc
index b58c256cd..1a97d5594 100644
--- a/src/mem/cache/mshr.cc
+++ b/src/mem/cache/mshr.cc
@@ -364,36 +364,37 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order)
if (isPendingDirty() || pkt->isInvalidate()) {
// We need to save and replay the packet in two cases:
// 1. We're awaiting an exclusive copy, so ownership is pending,
- // and we need to respond after we receive data.
+ // and we need to deal with the snoop after we receive data.
// 2. It's an invalidation (e.g., UpgradeReq), and we need
// to forward the snoop up the hierarchy after the current
// transaction completes.
-
- // Actual target device (typ. a memory) will delete the
- // packet on reception, so we need to save a copy here.
- // Clear flags and also allocate new data as the original
- // packet data storage may have been deleted by the time we
- // get to send this packet.
- PacketPtr cp_pkt = nullptr;
+ // Start by determining if we will eventually respond or not,
+ // matching the conditions checked in Cache::handleSnoop
+ bool will_respond = isPendingDirty() && pkt->needsResponse() &&
+ pkt->cmd != MemCmd::InvalidateReq;
+
+ // The packet we are snooping may be deleted by the time we
+ // actually process the target, and we consequently need to
+ // save a copy here. Clear flags and also allocate new data as
+ // the original packet data storage may have been deleted by
+ // the time we get to process this packet. In the cases where
+ // we are not responding after handling the snoop we also need
+ // to create a copy of the request to be on the safe side. In
+ // the latter case the cache is responsible for deleting both
+ // the packet and the request as part of handling the deferred
+ // snoop.
+ PacketPtr cp_pkt = will_respond ? new Packet(pkt, true, true) :
+ new Packet(new Request(*pkt->req), pkt->cmd);
if (isPendingDirty()) {
- // Case 1: The new packet will need to get the response from the
+ // The new packet will need to get the response from the
// MSHR already queued up here
- cp_pkt = new Packet(pkt, true, true);
pkt->assertMemInhibit();
// in the case of an uncacheable request there is no need
// to set the exclusive flag, but since the recipient does
// not care there is no harm in doing so
pkt->setSupplyExclusive();
- } else {
- // Case 2: We only need to buffer the packet for information
- // purposes; the original request can proceed without waiting
- // => Create a copy of the request, as that may get deallocated as
- // well
- cp_pkt = new Packet(new Request(*pkt->req), pkt->cmd);
- DPRINTF(Cache, "Copying packet %p -> %p and request %p -> %p\n",
- pkt, cp_pkt, pkt->req, cp_pkt->req);
}
targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
downstreamPending && targets.needsExclusive);