bug 939: EmuNetDevice uses too much memory
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Mon, 16 Aug 2010 08:30:29 -0700
changeset 6613 29512368dd2e
parent 6612 8ec3cfe04aa6
child 6614 bcf8ecccfe23
bug 939: EmuNetDevice uses too much memory
src/devices/emu/emu-net-device.cc
src/devices/emu/emu-net-device.h
--- a/src/devices/emu/emu-net-device.cc	Mon Aug 16 10:55:27 2010 -0400
+++ b/src/devices/emu/emu-net-device.cc	Mon Aug 16 08:30:29 2010 -0700
@@ -48,6 +48,7 @@
 #include <errno.h>
 #include <limits>
 #include <stdlib.h>
+#include <time.h>
 
 NS_LOG_COMPONENT_DEFINE ("EmuNetDevice");
 
@@ -106,6 +107,14 @@
                    MakePointerAccessor (&EmuNetDevice::m_queue),
                    MakePointerChecker<Queue> ())
 
+    .AddAttribute ("RxQueueSize", "Maximum size of the read queue.  "
+                   "This value limits number of packets that have been read "
+                   "from the network into a memory buffer but have not yet "
+                   "been processed by the simulator.",
+                   UintegerValue (1000),
+                   MakeUintegerAccessor (&EmuNetDevice::m_maxPendingReads),
+                   MakeUintegerChecker<uint32_t> ())
+
     //
     // Trace sources at the "top" of the net device, where packets transition
     // to/from higher layers.  These points do not really correspond to the 
@@ -184,7 +193,8 @@
   m_ifIndex (std::numeric_limits<uint32_t>::max ()),  // absurdly large value
   m_sll_ifindex (-1),
   m_isBroadcast (true),
-  m_isMulticast (false)
+  m_isMulticast (false),
+  m_pendingReadCount (0)
 {
   NS_LOG_FUNCTION (this);
   m_packetBuffer = new uint8_t[65536];
@@ -626,6 +636,12 @@
   free (buf);
   buf = 0;
 
+  {
+    CriticalSection cs (m_pendingReadMutex);
+    //std::cerr << std::endl << "EmuNetDevice main thread: m_pendingReadCount is " << m_pendingReadCount << std::endl;
+    --m_pendingReadCount;
+  }
+
   //
   // Trace sinks will expect complete packets, not packets without some of the
   // headers.
@@ -755,6 +771,31 @@
   for (;;) 
     {
       //
+      // Too many pending reads at the same time leads to excessive memory allocations.  This counter prevents it.
+      // 
+      bool skip = false;
+      
+      {
+        CriticalSection cs (m_pendingReadMutex);            
+        //std::cerr << std::endl << "EmuNetDevice read thread: m_pendingReadCount is " << m_pendingReadCount << std::endl;
+        if (m_pendingReadCount >= m_maxPendingReads)
+          {
+            skip = true;
+          }
+        else
+          {
+            ++m_pendingReadCount;
+          }
+      }
+
+      if (skip)  
+        {           
+          struct timespec time = { 0, 100000000L }; // 100 ms
+          nanosleep (&time, NULL);
+          continue;
+        }
+
+      //
       // to avoid any issues with a shared reference counted packet, we allocate a buffer on the heap and pass that
       // buffer into the ns-3 context thread where it will create the packet, copy the buffer and then free it.
       //
--- a/src/devices/emu/emu-net-device.h	Mon Aug 16 10:55:27 2010 -0400
+++ b/src/devices/emu/emu-net-device.h	Mon Aug 16 08:30:29 2010 -0700
@@ -32,6 +32,7 @@
 #include "ns3/ptr.h"
 #include "ns3/mac48-address.h"
 #include "ns3/system-thread.h"
+#include "ns3/system-mutex.h"
 #include "ns3/realtime-simulator-impl.h"
 
 namespace ns3 {
@@ -520,6 +521,10 @@
    * multithreaded apps is not a good thing.
    */
   uint32_t m_nodeId;
+
+  uint32_t m_maxPendingReads;
+  uint32_t m_pendingReadCount;
+  SystemMutex m_pendingReadMutex;
 };
 
 } // namespace ns3