-
- // 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;
-
- if (isPendingDirty()) {
- // Case 1: 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();
+
+ // 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(std::make_shared<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();
+