mem: Fix memory leak in handling of deferred snoops
This patch fixes a memory leak where deferred snoop packets never got deallocated. On the call to MSHR::handleSnoop these snoops were treated as if a response will be sent, as the MSHR was pendingModified. Consequently, a copy of the packet was created and added to the MSHR targets. However, an preceeding target to the same MSHR, originally from a CPU, was serviced before the snoop, and caused the block to be invalidated. This happens for ReadExReq and UpgradeReq. Note that the original snoop will receive a response, just not from the cache in question, but instead from the cache upstream that issued the ReadExReq or UpgradeReq. Change-Id: I4ac012fbc8a46cf693ca390fe9476105d444e6f4 Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
This commit is contained in:
parent
4d577ac8f1
commit
e3e808416f
1 changed files with 14 additions and 0 deletions
14
src/mem/cache/cache.cc
vendored
14
src/mem/cache/cache.cc
vendored
|
@ -1954,6 +1954,19 @@ Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blk || !blk->isValid()) {
|
if (!blk || !blk->isValid()) {
|
||||||
|
if (is_deferred) {
|
||||||
|
// we no longer have the block, and will not respond, but a
|
||||||
|
// packet was allocated in MSHR::handleSnoop and we have
|
||||||
|
// to delete it
|
||||||
|
assert(pkt->needsResponse());
|
||||||
|
|
||||||
|
// we have passed the block to a cache upstream, that
|
||||||
|
// cache should be responding
|
||||||
|
assert(pkt->cacheResponding());
|
||||||
|
|
||||||
|
delete pkt;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(CacheVerbose, "%s snoop miss for %s addr %#llx size %d\n",
|
DPRINTF(CacheVerbose, "%s snoop miss for %s addr %#llx size %d\n",
|
||||||
__func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize());
|
__func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize());
|
||||||
return snoop_delay;
|
return snoop_delay;
|
||||||
|
@ -2045,6 +2058,7 @@ Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
|
||||||
// responding, then we've made a copy of both the request and
|
// responding, then we've made a copy of both the request and
|
||||||
// the packet, delete them here
|
// the packet, delete them here
|
||||||
assert(pkt->needsResponse());
|
assert(pkt->needsResponse());
|
||||||
|
assert(!pkt->cacheResponding());
|
||||||
delete pkt->req;
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue