Ruby: Fix RubyPort evict packet memory leak
authorJoel Hestness <jthestness@gmail.com>
Tue, 9 Apr 2013 21:25:30 +0000 (16:25 -0500)
committerJoel Hestness <jthestness@gmail.com>
Tue, 9 Apr 2013 21:25:30 +0000 (16:25 -0500)
When using the o3 or inorder CPUs with many Ruby protocols, the caches may
need to forward invalidations to the CPUs. The RubyPort was instantiating a
packet to be sent to the CPUs to signal the eviction, but the packets were
not being freed by the CPUs. Consistent with the classic memory model, stack
allocate the packet and heap allocate the request so on
ruby_eviction_callback() completion, the packet deconstructor is called, and
deletes the request (*Note: stack allocating the request causes double
deletion, since it will be deleted in the packet destructor). This results in
the least memory allocations without memory errors.

src/mem/ruby/system/RubyPort.cc

index 4cfc1f252440916cbd7f1ccc97a75e21b00b03f6..1ebc1b0f64a9c7ff196f15bf71a75474f468e010 100644 (file)
@@ -496,14 +496,19 @@ void
 RubyPort::ruby_eviction_callback(const Address& address)
 {
     DPRINTF(RubyPort, "Sending invalidations.\n");
-    // should this really be using funcMasterId?
-    Request req(address.getAddress(), 0, 0, Request::funcMasterId);
+    // This request is deleted in the stack-allocated packet destructor
+    // when this function exits
+    // TODO: should this really be using funcMasterId?
+    RequestPtr req =
+            new Request(address.getAddress(), 0, 0, Request::funcMasterId);
+    // Use a single packet to signal all snooping ports of the invalidation.
+    // This assumes that snooping ports do NOT modify the packet/request
+    Packet pkt(req, MemCmd::InvalidationReq);
     for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) {
         // check if the connected master port is snooping
         if ((*p)->isSnooping()) {
-            Packet *pkt = new Packet(&req, MemCmd::InvalidationReq);
             // send as a snoop request
-            (*p)->sendTimingSnoopReq(pkt);
+            (*p)->sendTimingSnoopReq(&pkt);
         }
     }
 }