Commits

Anonymous committed 844c3c3

turned procmaps into a pseudo-singleton so that maps can be read only once. At the same time
added support for rereading maps when an address can not be located in loaded entries.

Comments (0)

Files changed (4)

+2009-01-23  Paolo Calafiura
+	* Tagging CxxUtils-00-00-14
+        * turned procmaps into a "pseudo-singleton" so that maps can be read only once. At the same time
+	added support for rereading maps when an address can not be located in loaded entries.
+
 2009-01-23  Paolo Calafiura
 	* Tagging CxxUtils-00-00-13
         * new class procmaps and its test

CxxUtils/procmaps.h

 #ifndef PROCMAPS_H 
 #define PROCMAPS_H 1
+#include <boost/pool/pool_alloc.hpp>
 #include <vector>
 /** @class procmaps 
  * @brief A simple API to access /proc/self/maps info
  *
  * @author Paolo Calafiura - LBNL, ATLAS Collaboration
- * $Id: procmaps.h,v 1.1 2009-01-23 23:57:27 calaf Exp $
+ * $Id: procmaps.h,v 1.2 2009-01-27 01:04:18 calaf Exp $
  **/
 class procmaps {
 public:
     bool executable;
     bool isPrivate; ///=true page is private(COW), =false page is shared
     unsigned int offset;
-    unsigned short dev[2]; /// dev[0] major, dev[1] minor
+    unsigned int dev[2]; /// dev[0] major, dev[1] minor
     unsigned int inode;
     char pathname[32];  ///truncated if needed
   };
 
-  procmaps(bool dump=false);
+  procmaps(size_t entries=1024);
   //not yet  procmaps(int pid);
 
-  typedef std::vector<Entry> procmaps_t;
+  typedef std::vector<Entry, boost::pool_allocator<Entry> > procmaps_t;
   typedef procmaps_t::const_iterator const_iterator;
   
   ///main entry point: get info for the page range containing address
-  const Entry* getEntry(const void* address) const;
+  /// by default tries to reload /proc/self/maps when address is not found
+  const Entry* getEntry(const void* address, bool tryReloadMaps=true);
 
   ///access underlying entries
-  const procmaps_t& pmaps() const { return m_pmaps; }
+  static const procmaps_t& pmaps() { return s_pmaps; }
   const_iterator begin() const { return pmaps().begin(); }
   const_iterator end() const { return pmaps().end(); }
 
   void loadMaps(bool dump=false); 
 
 private:
-  procmaps_t m_pmaps;
+  static bool s_pmapsLoaded;
+  static procmaps_t s_pmaps;
 };
 
 inline
 #include <cstdio>
 #include <cstdlib>
 #include "CxxUtils/procmaps.h"
-procmaps::Entry::Entry(const char* procMapsLine) 
+bool procmaps::s_pmapsLoaded(false);
+procmaps::procmaps_t procmaps::s_pmaps;
+procmaps::Entry::Entry(const char* procMapsLine) :
+  begAddress(0),endAddress(0),
+  readable(false), writable(false), executable(false), isPrivate(false),
+  offset(0), inode(0)
 {
+  dev[0]=0; dev[1]=0;
+  memset(pathname,' ',31);
   char pageProts[5];
+  memset(pageProts,' ', 4);
   sscanf(procMapsLine,
-	 "%8x-%8x %4s %x %2x:%2x %i %31s",
+	 "%8x-%8x %4s %x %2x:%2x %x %31s",
 	 &this->begAddress,
 	 &this->endAddress,
 	 &pageProts,
 	 &this->inode,
 	 &this->pathname
 	 );
+  //  printf("pageProts %s pathname <%s> \n", pageProts, pathname);
   this->readable = (pageProts[0] == 'r');
   this->writable = (pageProts[1] == 'w');
   this->executable = (pageProts[2] == 'x');
   this->isPrivate  = (pageProts[3] == 'p');
 }
 
-procmaps::procmaps(bool dump) {
-  loadMaps(dump);
+procmaps::procmaps(size_t entries) {
+  if (!s_pmapsLoaded) {
+     procmaps::s_pmaps.reserve(entries);
+     loadMaps();
+     s_pmapsLoaded=true;
+   }
 }
 
 void 
 procmaps::loadMaps(bool dump) {
+  procmaps::s_pmaps.clear();
   FILE* fp = fopen("/proc/self/maps", "r");
   if (fp) {
     char* line=0;
     size_t len=0;
     while (getline(&line, &len, fp)>0) {
       if (dump) printf("%s",line);
-      this->m_pmaps.push_back(Entry(line));
+      procmaps::s_pmaps.push_back(Entry(line));
       free(line);
       line=0;
     }
+    free(line);
     fclose(fp);
   }
 }
 
 const procmaps::Entry*
-procmaps::getEntry(const void * address) const {
+procmaps::getEntry(const void * address, bool refreshMaps) {
   //FIXME slow linear search. We'll make it faster...
   const_iterator i(this->begin()), e(this->end());
   bool found(false), done(false);
-  unsigned int toMatch((unsigned int)address);
+  long toMatch((long)address);
   while (!done && !found && i!=e) {
+    //    printf(" begAddress %x toMatch %x endAddress %x\n", i->begAddress, toMatch, i->endAddress);
     found = i->begAddress <= toMatch && toMatch <= i->endAddress; 
     done = !found && toMatch < i->begAddress; //entries sorted by begAddress
     if (!found && !done) ++i;
   }
-  return (found ? &*i : 0) ;
+  if (!found && refreshMaps) loadMaps();
+  //if ! found recurse once by calling getEntry with refreshMaps false
+  return (found ? &*i : getEntry(address,false)) ;
 }

test/procmaps_test.cxx

   assert(pHeapEntry->writable);
   assert(0 == pHeapEntry->inode);
 
-
+  delete pi;
   cout << "*** procmaps_test OK ***" <<endl;
   return 0;
 }