-
- // Actual target device (typ. PhysicalMemory) will delete the
- // packet on reception, so we need to save a copy here.
- PacketPtr cp_pkt = new Packet(pkt, true);
- targets->add(cp_pkt, curTick(), _order, Target::FromSnoop,
- downstreamPending && targets->needsExclusive);
- ++ntargets;
-
- if (isPendingDirty()) {
- pkt->assertMemInhibit();
- pkt->setSupplyExclusive();
+
+ // Start by determining if we will eventually respond or not,
+ // matching the conditions checked in Cache::handleSnoop
+ bool will_respond = isPendingModified() && pkt->needsResponse() &&
+ !pkt->isClean();
+
+ // 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, blkSize, pkt->id);
+
+ if (will_respond) {
+ // we are the ordering point, and will consequently
+ // respond, and depending on whether the packet
+ // needsWritable or not we either pass a Shared line or a
+ // Modified line
+ pkt->setCacheResponding();
+
+ // inform the cache hierarchy that this cache had the line
+ // in the Modified state, even if the response is passed
+ // as Shared (and thus non-writable)
+ pkt->setResponderHadWritable();
+
+ // in the case of an uncacheable request there is no need
+ // to set the responderHadWritable flag, but since the
+ // recipient does not care there is no harm in doing so