]> granicus.if.org Git - pdns/commitdiff
add max-mthread-stack metric to measure maximum mthread stack usage - 34 kilobytes...
authorBert Hubert <bert.hubert@netherlabs.nl>
Wed, 1 Dec 2010 15:55:46 +0000 (15:55 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Wed, 1 Dec 2010 15:55:46 +0000 (15:55 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1745 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/mtasker.cc
pdns/mtasker.hh
pdns/pdns_recursor.cc
pdns/rec_channel_rec.cc
pdns/syncres.hh

index 30db35b6b2ba128077a80f7b75a12c556f4c33e4..0ccd7385f69c06b4864c5e74ae3befcebfc788a4 100644 (file)
@@ -192,6 +192,9 @@ template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEven
   if(val && d_waitstatus==Answer) 
     *val=d_waitval;
   d_tid=w.tid;
+  if((char*)&w < d_threads[d_tid].highestStackSeen) {
+    d_threads[d_tid].highestStackSeen = (char*)&w;
+  }
   key=d_eventkey;
   return d_waitstatus;
 }
@@ -202,7 +205,7 @@ template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEven
 template<class Key, class Val>void MTasker<Key,Val>::yield()
 {
   d_runQueue.push(d_tid);
-  if(swapcontext(d_threads[d_tid] ,&d_kernel) < 0) { // give control to the kernel
+  if(swapcontext(d_threads[d_tid].context ,&d_kernel) < 0) { // give control to the kernel
     perror("swapcontext in  yield");
     exit(EXIT_FAILURE);
   }
@@ -271,7 +274,7 @@ template<class Key, class Val>void MTasker<Key,Val>::makeThread(tfunc_t *start,
 
   makecontext (uc, (void (*)(void))threadWrapper, 6, thispair.first, thispair.second, start, d_maxtid, valpair.first, valpair.second);
 
-  d_threads[d_maxtid]=uc;
+  d_threads[d_maxtid].context = uc;
   d_runQueue.push(d_maxtid++); // will run at next schedule invocation
 }
 
@@ -290,7 +293,7 @@ template<class Key, class Val>bool MTasker<Key,Val>::schedule(struct timeval*  n
 {
   if(!d_runQueue.empty()) {
     d_tid=d_runQueue.front();
-    if(swapcontext(&d_kernel, d_threads[d_tid])) {
+    if(swapcontext(&d_kernel, d_threads[d_tid].context)) {
       perror("swapcontext in schedule");
       exit(EXIT_FAILURE);
     }
@@ -299,8 +302,8 @@ template<class Key, class Val>bool MTasker<Key,Val>::schedule(struct timeval*  n
     return true;
   }
   if(!d_zombiesQueue.empty()) {
-    delete[] (char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp;
-    delete d_threads[d_zombiesQueue.front()];
+    delete[] (char *)d_threads[d_zombiesQueue.front()].context->uc_stack.ss_sp;
+    delete d_threads[d_zombiesQueue.front()].context;
     d_threads.erase(d_zombiesQueue.front());
     d_zombiesQueue.pop();
     return true;
@@ -369,11 +372,11 @@ template<class Key, class Val>void MTasker<Key,Val>::getEvents(std::vector<Key>&
   }
 }
 
-
 template<class Key, class Val>void MTasker<Key,Val>::threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2)
 {
   void* val = joinPtr(val1, val2); 
   MTasker* self = (MTasker*) joinPtr(self1, self2);
+  self->d_threads[self->d_tid].startOfStack = self->d_threads[self->d_tid].highestStackSeen = (char*)&val;
   (*tf)(val);
   self->d_zombiesQueue.push(tid);
   
@@ -388,3 +391,10 @@ template<class Key, class Val>int MTasker<Key,Val>::getTid()
 {
   return d_tid;
 }
+
+
+//! Returns the maximum stack usage so far of this MThread
+template<class Key, class Val>unsigned int MTasker<Key,Val>::getMaxStackUsage()
+{
+  return d_threads[d_tid].startOfStack - d_threads[d_tid].highestStackSeen;
+}
index 97354c903f62a74eb3e9ed8b33d29d532bc83c3c..226dbbf20b37374037f23cf195604940f0fd54e2 100644 (file)
@@ -50,8 +50,14 @@ private:
   std::queue<int> d_runQueue;
   std::queue<int> d_zombiesQueue;
 
+  struct ThreadInfo
+  {
+       ucontext_t* context;
+       char* startOfStack;
+       char* highestStackSeen;
+  };
 
-  typedef std::map<int, ucontext_t*> mthreads_t;
+  typedef std::map<int, ThreadInfo> mthreads_t;
   mthreads_t d_threads;
   int d_tid;
   int d_maxtid;
@@ -66,7 +72,7 @@ public:
     EventKey key;
     ucontext_t *context;
     struct timeval ttd;
-    int tid;
+    int tid;    
   };
 
   typedef multi_index_container<
@@ -99,6 +105,7 @@ public:
   bool noProcesses();
   unsigned int numProcesses();
   int getTid(); 
+  unsigned int getMaxStackUsage();
 
 private:
   static void threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2);
index 537ee7bcacabf2bd4ca0f7d483ec1de68209c033..f6c2c015aa7da9ce75f232a854ad6b299b1e4c79 100644 (file)
@@ -653,6 +653,8 @@ void startDoResolve(void *p)
   catch(...) {
     L<<Logger::Error<<"Any other exception in a resolver context"<<endl;
   }
+  
+  g_stats.maxMThreadStackUsage = max(MT->getMaxStackUsage(), g_stats.maxMThreadStackUsage);
 }
 
 void makeControlChannelSocket()
index 077e4ab3da4d1195b2ee7d11b034637cca73e7b9..8f196cc281e73aaa20a5d1842f0a85f0262184a9 100644 (file)
@@ -400,6 +400,7 @@ RecursorControlParser::RecursorControlParser()
   addGetStat("over-capacity-drops", &g_stats.overCapacityDrops);
   addGetStat("no-packet-error", &g_stats.noPacketError);
   addGetStat("dlg-only-drops", &SyncRes::s_nodelegated);
+  addGetStat("max-mthread-stack", &g_stats.maxMThreadStackUsage);
   
   addGetStat("negcache-entries", boost::bind(getNegCacheSize));
   addGetStat("throttle-entries", boost::bind(getThrottleSize)); 
index e3249d209848211814e1328445882ed1eea8d406..a1e5d2a9cb61616861f161e3bb7692da42942e6f 100644 (file)
@@ -477,6 +477,7 @@ struct RecursorStats
   uint64_t packetCacheHits;
   uint64_t noPacketError;
   time_t startupTime;
+  unsigned int maxMThreadStackUsage;
 };
 
 //! represents a running TCP/IP client session