stop m5 from leaking like a sieve
authorAli Saidi <saidi@eecs.umich.edu>
Thu, 8 Mar 2007 23:57:15 +0000 (18:57 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Thu, 8 Mar 2007 23:57:15 +0000 (18:57 -0500)
don't create a new physPort/virtPort every time activateContext() is called
add the ability to tell a memory object to delete it's reference to a port and a method to have a port call deletePortRefs()
on the port owner as well as delete it's peer
still need to stop calling connectMemoPorts() every time activateContext() is called or we'll overflow the bus id and panic

src/cpu/thread_state.cc:
    if we hav ea (phys|virt)Port don't create a new on, have it delete it's peer and then reuse it
src/mem/bus.cc:
src/mem/bus.hh:
    add ability to delete a port by usig a hash_map instead of an array to store port ids
    add a function to do deleting
src/mem/cache/cache.hh:
src/mem/cache/cache_impl.hh:
src/mem/mem_object.cc:
src/mem/mem_object.hh:
    adda function to delete port references from a memory object
src/mem/port.cc:
src/mem/port.hh:
    add a removeConn function that tell the owener to delete any references to the port and then deletes its peer

--HG--
extra : convert_revision : 272f0c8f80e1cf1ab1750d8be5a6c9aa110b06a4

src/cpu/thread_state.cc
src/mem/bus.cc
src/mem/bus.hh
src/mem/cache/cache.hh
src/mem/cache/cache_impl.hh
src/mem/mem_object.cc
src/mem/mem_object.hh
src/mem/port.cc
src/mem/port.hh

index 93dd1e2eb0252830abd14d1a443d9d86c12c2068..4b65ca4b8bc4c456ea19ffb775cbd5bd6754c1a6 100644 (file)
@@ -125,7 +125,10 @@ ThreadState::connectPhysPort()
     // @todo: For now this disregards any older port that may have
     // already existed.  Fix this memory leak once the bus port IDs
     // for functional ports is resolved.
-    physPort = new FunctionalPort(csprintf("%s-%d-funcport",
+    if (physPort)
+        physPort->removeConn();
+    else
+        physPort = new FunctionalPort(csprintf("%s-%d-funcport",
                                            baseCpu->name(), tid));
     connectToMemFunc(physPort);
 }
@@ -136,7 +139,10 @@ ThreadState::connectVirtPort()
     // @todo: For now this disregards any older port that may have
     // already existed.  Fix this memory leak once the bus port IDs
     // for functional ports is resolved.
-    virtPort = new VirtualPort(csprintf("%s-%d-vport",
+    if (virtPort)
+        virtPort->removeConn();
+    else
+        virtPort = new VirtualPort(csprintf("%s-%d-vport",
                                         baseCpu->name(), tid));
     connectToMemFunc(virtPort);
 }
index cc2137e660a479add450a0b7bfbb25c38bad3258..4988df3c56e82dd60557ba1c3a893c444a1c782f 100644 (file)
@@ -34,6 +34,8 @@
  */
 
 
+#include <limits>
+
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "mem/bus.hh"
@@ -52,20 +54,30 @@ Bus::getPort(const std::string &if_name, int idx)
     }
 
     // if_name ignored?  forced to be empty?
-    int id = interfaces.size();
+    int id = maxId++;
+    assert(maxId < std::numeric_limits<typeof(maxId)>::max());
     BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
-    interfaces.push_back(bp);
+    interfaces[id] = bp;
     return bp;
 }
 
+void
+Bus::deletePortRefs(Port *p)
+{
+    BusPort *bp =  dynamic_cast<BusPort*>(p);
+    if (bp == NULL)
+        panic("Couldn't convert Port* to BusPort*\n");
+    interfaces.erase(bp->getId());
+}
+
 /** Get the ranges of anyone other buses that we are connected to. */
 void
 Bus::init()
 {
-    std::vector<BusPort*>::iterator intIter;
+    m5::hash_map<short,BusPort*>::iterator intIter;
 
     for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
-        (*intIter)->sendStatusChange(Port::RangeChange);
+        intIter->second->sendStatusChange(Port::RangeChange);
 }
 
 Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus)
@@ -186,7 +198,7 @@ Bus::recvTiming(PacketPtr pkt)
             return false;
         }
     } else {
-        assert(dest >= 0 && dest < interfaces.size());
+        assert(dest >= 0 && dest < maxId);
         assert(dest != pkt->getSrc()); // catch infinite loops
         port = interfaces[dest];
     }
@@ -435,7 +447,6 @@ Bus::recvStatusChange(Port::Status status, int id)
 {
     AddrRangeList ranges;
     AddrRangeList snoops;
-    int x;
     AddrRangeIter iter;
 
     assert(status == Port::RangeChange &&
@@ -457,7 +468,7 @@ Bus::recvStatusChange(Port::Status status, int id)
         }
     } else {
 
-        assert((id < interfaces.size() && id >= 0) || id == defaultId);
+        assert((id < maxId && id >= 0) || id == defaultId);
         Port *port = interfaces[id];
         range_map<Addr,int>::iterator portIter;
         std::vector<DevMap>::iterator snoopIter;
@@ -502,9 +513,11 @@ Bus::recvStatusChange(Port::Status status, int id)
 
     // tell all our peers that our address range has changed.
     // Don't tell the device that caused this change, it already knows
-    for (x = 0; x < interfaces.size(); x++)
-        if (x != id)
-            interfaces[x]->sendStatusChange(Port::RangeChange);
+    m5::hash_map<short,BusPort*>::iterator intIter;
+
+    for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
+        if (intIter->first != id)
+            intIter->second->sendStatusChange(Port::RangeChange);
 
     if (id != defaultId && defaultPort)
         defaultPort->sendStatusChange(Port::RangeChange);
index 350a67b435f1dee3ddb561406cddccb8850bf425..6706b6c7752a1b981ce058262b9a6df241dc0157 100644 (file)
@@ -42,6 +42,7 @@
 #include <inttypes.h>
 
 #include "base/range.hh"
+#include "base/hashmap.hh"
 #include "base/range_map.hh"
 #include "mem/mem_object.hh"
 #include "mem/packet.hh"
@@ -212,9 +213,12 @@ class Bus : public MemObject
 
     bool inRetry;
 
+    /** max number of bus ids we've handed out so far */
+    short maxId;
+
     /** An array of pointers to the peer port interfaces
         connected to this bus.*/
-    std::vector<BusPort*> interfaces;
+    m5::hash_map<short,BusPort*> interfaces;
 
     /** An array of pointers to ports that retry should be called on because the
      * original send failed for whatever reason.*/
@@ -252,6 +256,7 @@ class Bus : public MemObject
 
     /** A function used to return the port associated with this bus object. */
     virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual void deletePortRefs(Port *p);
 
     virtual void init();
 
@@ -261,7 +266,7 @@ class Bus : public MemObject
         bool responder_set)
         : MemObject(n), busId(bus_id), clock(_clock), width(_width),
           tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
-          defaultPort(NULL), responderSet(responder_set)
+          maxId(0), defaultPort(NULL), responderSet(responder_set)
     {
         //Both the width and clock period must be positive
         if (width <= 0)
index 26dab2179a6ccd71cf1b1f0225330d7b0661c675..722ce216b5768f70a2d3e6227454b60dbbbfc381 100644 (file)
@@ -331,6 +331,7 @@ class Cache : public BaseCache
     Cache(const std::string &_name, Params &params);
 
     virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual void deletePortRefs(Port *p);
 
     virtual void recvStatusChange(Port::Status status, bool isCpuSide);
 
index dac2b93a43f63c96389674deffa1ea39b6d82eee..056f6033f84f2127f25cc79a43e0db5d6ebae83f 100644 (file)
@@ -1100,7 +1100,7 @@ Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
     }
     else if (if_name == "functional")
     {
-        return new CpuSidePort(name() + "-cpu_side_port", this);
+        return new CpuSidePort(name() + "-cpu_side_funcport", this);
     }
     else if (if_name == "cpu_side")
     {
@@ -1121,6 +1121,15 @@ Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
     else panic("Port name %s unrecognized\n", if_name);
 }
 
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::deletePortRefs(Port *p)
+{
+    if (cpuSidePort == p || memSidePort == p)
+        panic("Can only delete functional ports\n");
+    // nothing else to do
+}
+
 
 template<class TagStore, class Coherence>
 bool
index d4d3fd283eb227cd8d2470d194794d80809b59a5..ef31cf999deaf2cb75a272e262421f7452dc3131 100644 (file)
@@ -35,5 +35,10 @@ MemObject::MemObject(const std::string &name)
     : SimObject(name)
 {
 }
+void
+MemObject::deletePortRefs(Port *p)
+{
+    panic("This object does not support port deletion\n");
+}
 
 DEFINE_SIM_OBJECT_CLASS_NAME("MemObject", MemObject)
index d12eeffe062a3c7e4a2ce87356ee4bcff78170b7..ec6fa2b2aea0230e2b78d1288b7cde5605ddc6d5 100644 (file)
@@ -51,6 +51,10 @@ class MemObject : public SimObject
   public:
     /** Additional function to return the Port of a memory object. */
     virtual Port *getPort(const std::string &if_name, int idx = -1) = 0;
+
+    /** Tell object that this port is about to disappear, so it should remove it
+     * from any structures that it's keeping it in. */
+    virtual void deletePortRefs(Port *p) ;
 };
 
 #endif //__MEM_MEM_OBJECT_HH__
index 048d7cf6d63b4a50eef6a857af89a063b9092ab3..e75e50e4d43ec4e1460c0c1c8ccec88645ab2529 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "base/chunk_generator.hh"
 #include "base/trace.hh"
+#include "mem/mem_object.hh"
 #include "mem/port.hh"
 
 void
@@ -45,6 +46,15 @@ Port::setPeer(Port *port)
     peer = port;
 }
 
+void
+Port::removeConn()
+{
+    if (peer->getOwner())
+        peer->getOwner()->deletePortRefs(peer);
+    delete peer;
+    peer = NULL;
+}
+
 void
 Port::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd)
 {
index fdb5bfab41b0737b468d4490ee7b821b496b1b90..52162bf7640db6a63972f9010619be460e394838 100644 (file)
@@ -131,6 +131,11 @@ class Port
     /** Function to return the owner of this port. */
     MemObject *getOwner() { return owner; }
 
+    /** Inform the peer port to delete itself and notify it's owner about it's
+     * demise. */
+    void removeConn();
+
+
   protected:
 
     /** These functions are protected because they should only be