summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2007-03-08 18:57:15 -0500
committerAli Saidi <saidi@eecs.umich.edu>2007-03-08 18:57:15 -0500
commit027dfa01e6ca7e9feed334eef5fab7cfbbb18c52 (patch)
tree84de535dac081acb439d1dc26d3872d478157f30
parent87fb0eb8de8bf66dfae5fc2d069cd17f420fc163 (diff)
downloadgem5-027dfa01e6ca7e9feed334eef5fab7cfbbb18c52.tar.xz
stop m5 from leaking like a sieve
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
-rw-r--r--src/cpu/thread_state.cc10
-rw-r--r--src/mem/bus.cc33
-rw-r--r--src/mem/bus.hh9
-rw-r--r--src/mem/cache/cache.hh1
-rw-r--r--src/mem/cache/cache_impl.hh11
-rw-r--r--src/mem/mem_object.cc5
-rw-r--r--src/mem/mem_object.hh4
-rw-r--r--src/mem/port.cc10
-rw-r--r--src/mem/port.hh5
9 files changed, 73 insertions, 15 deletions
diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc
index 93dd1e2eb..4b65ca4b8 100644
--- a/src/cpu/thread_state.cc
+++ b/src/cpu/thread_state.cc
@@ -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);
}
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index cc2137e66..4988df3c5 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -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);
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 350a67b43..6706b6c77 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -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)
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 26dab2179..722ce216b 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -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);
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index dac2b93a4..056f6033f 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -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
diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc
index d4d3fd283..ef31cf999 100644
--- a/src/mem/mem_object.cc
+++ b/src/mem/mem_object.cc
@@ -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)
diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh
index d12eeffe0..ec6fa2b2a 100644
--- a/src/mem/mem_object.hh
+++ b/src/mem/mem_object.hh
@@ -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__
diff --git a/src/mem/port.cc b/src/mem/port.cc
index 048d7cf6d..e75e50e4d 100644
--- a/src/mem/port.cc
+++ b/src/mem/port.cc
@@ -36,6 +36,7 @@
#include "base/chunk_generator.hh"
#include "base/trace.hh"
+#include "mem/mem_object.hh"
#include "mem/port.hh"
void
@@ -46,6 +47,15 @@ Port::setPeer(Port *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)
{
Request req;
diff --git a/src/mem/port.hh b/src/mem/port.hh
index fdb5bfab4..52162bf76 100644
--- a/src/mem/port.hh
+++ b/src/mem/port.hh
@@ -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