cgma
MemoryManager.cpp
Go to the documentation of this file.
00001 //-       Class: MemoryManager
00002 //-       Owner: Jim Hipp
00003 //- Description: MemoryManager provides object information and stack
00004 //-              storage pointer management used in association with
00005 //-              MemoryBlock and MemoryAllocation classes.
00006 //- Checked By: 
00007 //-    Version:
00008 //  Modified 5/7/96 R W Ostensen:  Fixed operator_new function as per recommendation
00009 //  from J Hipp.  Eliminated assignment of headOfFreeList to wild pointer loaction when
00010 //  memAllocatnSize=1.
00011 
00012 
00013 #include "MemoryBlock.hpp"
00014 #include "MemoryManager.hpp"
00015 #include "CubitMessage.hpp"
00016 #include "ArrayBasedContainer.hpp"
00017 #include "AppUtil.hpp"
00018 #include <cassert>
00019 #include <cstring>
00020 #include <iostream>
00021 #ifndef _WIN32
00022 #include <unistd.h>
00023 #endif
00024 
00025 
00026 MemoryManager* MemoryManager::memoryManagerListHead = NULL;
00027 
00028 // constructors
00029 MemoryManager::MemoryManager() : useNew(false), objectName(NULL)
00030 {
00031   // do not allow default constructor (must assign objectSize)
00032   assert(0);
00033 }
00034 
00035 MemoryManager::MemoryManager(const MemoryManager&) : useNew(false), objectName(NULL)
00036 {
00037   // do not allow copy
00038   assert(0);
00039 }
00040 
00041 MemoryManager::MemoryManager(const char* name, size_t size, int mem_size,
00042                              int static_flag)
00043   : useNew(true)
00044 {
00045     // allocate space for name and copy into buffer
00046   if (name) 
00047   {
00048     objectName = new char[std::strlen(name) + 1];
00049     std::strcpy(objectName, name);
00050   }
00051   else
00052     objectName = NULL;
00053   
00054     // initialize manager parameters
00055   staticManager   = static_flag;
00056   memBlockStack   = NULL;
00057   headOfFreeList  = NULL;
00058   
00059   assert(size >= sizeof(char*));
00060   objectSize = size;
00061   
00062   set_memory_allocation_increment(mem_size);
00063   
00064     // attach new manager to static stack
00065   next = memoryManagerListHead;
00066   memoryManagerListHead = this;
00067 }
00068 
00069 // destructor
00070 MemoryManager::~MemoryManager()
00071 {
00072   // delete objectName space and destroy block memory
00073   delete [] objectName;
00074   objectName = NULL;
00075   destroy_memory(staticManager);
00076   
00077   // find 'prev' manager pointer
00078   MemoryManager* prev        = NULL;
00079   MemoryManager* mem_manager = memoryManagerListHead;
00080   bool first = true;
00081   while (mem_manager && mem_manager != this)
00082   {
00083     if (!first && mem_manager == memoryManagerListHead)
00084     {
00085       // XXX: We aren't in the list!?
00086       std::cerr << "MemoryManager: corrupted list?" << std::endl;
00087       return;
00088     }
00089     first = false;
00090     prev        = mem_manager;
00091     mem_manager = mem_manager->next;
00092   }
00093 
00094   // remove memory manager from static list
00095 
00096   if (!next)
00097   {
00098     if (!prev)
00099     {
00100       // no memory managers left
00101 
00102       memoryManagerListHead = NULL;
00103     }
00104     else
00105     {
00106       // remove tail node
00107 
00108       prev->next = NULL;
00109     }
00110   }
00111   else
00112   {
00113     if (!prev)
00114     {
00115       // remove head node
00116 
00117       memoryManagerListHead = next;
00118     }
00119     else
00120     {
00121       // remove intermediate node
00122 
00123       prev->next = next;
00124     }
00125   }
00126 }
00127 
00128 // set memory block allocation increment
00129 void MemoryManager::set_memory_allocation_increment(int mem_size)
00130 {
00131   // set memory allocation increment
00132 
00133   if (mem_size <= 0)
00134   {
00135      memAllocatnSize = DEFAULT_MEMORY_ALLOC_SIZE;
00136   }
00137   else
00138   {
00139     memAllocatnSize = mem_size;
00140   }
00141 }
00142 
00143 // destroy allocated block memory
00144 void MemoryManager::destroy_memory(int static_flag)
00145 {
00146   // assert if this is not a static memory manager and some of it's objects
00147   // are still in use
00148   if (!static_flag) {
00149     assert (!get_used_objects());
00150   }
00151 
00152   // else delete block memory if any was allocated
00153   if (memBlockStack) delete memBlockStack;
00154 
00155   // reset stack pointers to empty
00156   headOfFreeList = NULL;
00157   memBlockStack  = NULL;
00158 }
00159 
00160 // return number of objects allocated
00161 int MemoryManager::get_allocated_objects()
00162 {
00163   // return total number of objects allocated for this memory manager
00164 
00165   if (memBlockStack)
00166   {
00167     return (memBlockStack->get_memory_allocation() / objectSize);
00168   }
00169   else
00170   {
00171     return 0;
00172   }
00173 }
00174 
00175 // return free objects
00176 int MemoryManager::get_free_objects()
00177 {
00178   // return total number of free objects (allocated but not used) for this
00179   // memory manager
00180 
00181   if (headOfFreeList)
00182   {
00183     int i = 0;
00184     char* list_ptr = headOfFreeList;
00185     while (list_ptr)
00186     {
00187       i++;
00188       list_ptr = *((char**) list_ptr);
00189     }
00190 
00191     return i;
00192   }
00193   else
00194   {
00195     return 0;
00196   }
00197 }
00198 
00199 // return used objects
00200 int MemoryManager::get_used_objects()
00201 {
00202   // return total number of used objects for this memory manager
00203 
00204   return (get_allocated_objects() - get_free_objects());
00205 }
00206 
00207 // print allocation information to the command line
00208 void MemoryManager::show_object_memory(const char* name)
00209 {
00210   int instance = 0;
00211 
00212   // find all instances of memory managers for object: name
00213 
00214   MemoryManager* mem_manager = memoryManagerListHead;
00215   while (mem_manager)
00216   {
00217     if (!std::strcmp(mem_manager->objectName, name))
00218     {
00219       // if found then print pertinent memory allocation information
00220 
00221       instance++;
00222       if (instance > 1)
00223       {
00224         PRINT_INFO("\nObject Name(%d): %s\n\n", instance, name);
00225       }
00226       else
00227       {
00228         PRINT_INFO("\nObject Name: %s\n\n", name);
00229       }
00230 
00231       int a_obj = mem_manager->get_allocated_objects();
00232       int f_obj = mem_manager->get_free_objects();
00233       int u_obj = a_obj - f_obj;
00234 
00235       PRINT_INFO("  Object Size: %lu     Allocation Increment: %d\n\n",
00236       (unsigned long)mem_manager->objectSize, mem_manager->memAllocatnSize);
00237       PRINT_INFO("  Allocated Objects: %d  (bytes) %d\n", a_obj,
00238          a_obj * (int)(mem_manager->objectSize));
00239       if (a_obj)
00240       {
00241         PRINT_INFO("       Free Objects: %d  (bytes) %d (%d%%)\n", f_obj,
00242            f_obj * (int)(mem_manager->objectSize),
00243            (100*f_obj)/a_obj);
00244         PRINT_INFO("       Used Objects: %d  (bytes) %d (%d%%)\n", u_obj,
00245            u_obj * (int)(mem_manager->objectSize),
00246            (100*u_obj)/a_obj);
00247       }
00248     }
00249 
00250     // get next memory manager
00251 
00252     mem_manager = mem_manager->next;
00253   }
00254 
00255   // if none were found then announce
00256 
00257   if (!instance)
00258   {
00259     PRINT_INFO("\nObject: %s was not found ...\n",  name);
00260   }
00261 }
00262 
00263 
00264 // show allocation for all memory manager objects
00265 void MemoryManager::show_all_object_memory()
00266 {
00267 
00268 #if defined(MACOSX)
00269     
00270   pid_t PID = getpid();
00271   char command1[60];
00272   unsigned long rss=0, vm=0;
00273 
00274   FILE *pipe;
00275   char buf[1024];
00276   
00277   //get size of real memory
00278   sprintf(command1,"ps -o rss -p %d | grep -v RSS",PID);
00279   pipe = popen(command1, "r");
00280   if (pipe) 
00281   {
00282     fgets(buf, 1024, pipe);
00283     rss = strtoul(buf, NULL, 0);
00284     pclose(pipe);
00285   }
00286 
00287   //get size of virtual memory
00288   sprintf(command1,"ps -o vsz -p %d | grep -v VSZ",PID);
00289   pipe = popen(command1, "r");
00290   if (pipe) 
00291   {
00292     fgets(buf, 1024, pipe);
00293     vm = strtoul(buf, NULL, 0);
00294     pclose(pipe);
00295   }
00296 
00297   PRINT_INFO("Total memory = %lu\n", (unsigned long)vm );
00298   PRINT_INFO("Resident memory = %lu\n", (unsigned long)rss );
00299 
00300 
00301 /*
00302   struct rusage my_rusage;
00303   int ret_val = getrusage( RUSAGE_CHILDREN, &my_rusage ); 
00304 
00305   if( ret_val == 0 )
00306   {
00307     PRINT_INFO("It was a success\n");
00308     PRINT_INFO("Memory size = %d\n", my_rusage.ru_maxrss );
00309     PRINT_INFO("Unshared data size = %d\n", my_rusage.ru_idrss);
00310     PRINT_INFO("Integeral unshared data size = %d\n", my_rusage.ru_isrss);
00311     PRINT_INFO("more values: %d %d %d %d %d %d %d %d %d %d %d \n",
00312         my_rusage.ru_ixrss, my_rusage.ru_minflt, my_rusage.ru_majflt, my_rusage.ru_nswap, 
00313                 my_rusage.ru_inblock, my_rusage.ru_oublock, my_rusage.ru_msgsnd, my_rusage.ru_msgrcv, 
00314                 my_rusage.ru_nsignals, my_rusage.ru_nvcsw, my_rusage.ru_nivcsw ); 
00315   }
00316   else
00317     PRINT_INFO("It was a failure\n");
00318  */  
00319 
00320  
00321 /* 
00322   int i, mib[4];
00323   size_t len;
00324   struct kinfo_proc kp;
00325 
00326   len = 4;
00327   sysctlnametomib("kern.proc.pid", mib, &len);
00328   len = sizeof(kp);
00329   int pid = getpid();
00330   mib[3] = pid;
00331   if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
00332   {
00333     perror("sysctl");
00334     PRINT_INFO("Got problems\n");
00335   }
00336   else if (len > 0)
00337   {
00338     PRINT_INFO("The call was successful!!!\n");
00339   }
00340 */
00341 
00342 /*
00343   int i, mib[4];
00344   size_t len;
00345   struct kinfo_proc kp;
00346  
00347   len = 4; 
00348   sysctlnametomib("kern.proc.pid", mib, &len);
00349 
00350   for (i = 0; i < 100; i++) 
00351   {         
00352     mib[3] = i;         
00353     len = sizeof(kp);         
00354     if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
00355       perror("sysctl");         
00356     else if (len > 0)   
00357       PRINT_INFO("Call was successful!\n"); 
00358   }
00359 */ 
00360 
00361 #endif
00362 
00363 
00364 #if defined(CUBIT_LINUX)
00365   unsigned long vm, rss;
00366   process_mem_usage( vm, rss );
00367 
00368   unsigned long read, write;
00369   process_file_io( read, write );
00370 
00371   PRINT_INFO("Total memory = %lu\n", vm );
00372   PRINT_INFO("Resident memory = %lu\n", rss );
00373   PRINT_INFO("Bytes read = %lu\n", read );
00374   PRINT_INFO("Bytes written = %lu\n", write );
00375 #endif
00376 
00377   /*
00378   long int a_obj_byte_total = 0;
00379   long int f_obj_byte_total = 0;
00380   long int u_obj_byte_total = 0;
00381 
00382   // loop over all memory managers
00383 
00384   PRINT_INFO("\nDynamic Memory Allocation per Object\n\n");
00385 
00386   MemoryManager* mem_manager = memoryManagerListHead;
00387   while (mem_manager) {
00388     long int a_obj = mem_manager->get_allocated_objects();
00389     long int f_obj = mem_manager->get_free_objects();
00390     long int u_obj = a_obj - f_obj;
00391     if (a_obj) {
00392       // sum total allocated memory parameters (bytes)
00393       a_obj_byte_total += a_obj * mem_manager->objectSize;
00394       f_obj_byte_total += f_obj * mem_manager->objectSize;
00395       u_obj_byte_total += u_obj * mem_manager->objectSize;
00396     }
00397     mem_manager = mem_manager->next;
00398   }
00399 
00400   mem_manager = memoryManagerListHead;
00401   while (mem_manager)
00402   {
00403     // print pertinent memory allocation information 
00404 
00405     long int a_obj = mem_manager->get_allocated_objects();
00406     long int f_obj = mem_manager->get_free_objects();
00407     long int u_obj = a_obj - f_obj;
00408 
00409     if (a_obj)
00410     {
00411       PRINT_INFO("\nObject Name: %s\n\n", mem_manager->objectName);
00412 
00413       PRINT_INFO("  Object Size: %d     Allocation Increment: %d\n\n",
00414              mem_manager->objectSize, mem_manager->memAllocatnSize);
00415       if (a_obj_byte_total != 0)
00416       {
00417          PRINT_INFO("  Allocated Objects: %ld  (bytes) %ld (%d%% of Total)\n",
00418                     a_obj, a_obj * mem_manager->objectSize,
00419                     int((100.0*a_obj * mem_manager->objectSize)/a_obj_byte_total));
00420          PRINT_INFO("       Free Objects: %ld  (bytes) %ld (%d%%)\n", f_obj,
00421                     f_obj * mem_manager->objectSize,
00422                     int((100.0*f_obj)/a_obj));
00423          PRINT_INFO("       Used Objects: %ld  (bytes) %ld (%d%%)\n", u_obj,
00424                     u_obj * mem_manager->objectSize,
00425                     int((100.0*u_obj)/a_obj));
00426       }
00427       else
00428       {
00429          PRINT_INFO("  Allocated Objects: %ld  (bytes) %ld (100%% of Total)\n",
00430                     a_obj, a_obj * mem_manager->objectSize);
00431          PRINT_INFO("       Free Objects: %ld  (bytes) %ld (100%%)\n", f_obj,
00432                     f_obj * mem_manager->objectSize);
00433          PRINT_INFO("       Used Objects: %ld  (bytes) %ld (100%%)\n", u_obj,
00434                     u_obj * mem_manager->objectSize);
00435       }
00436     }
00437 
00438     mem_manager = mem_manager->next;
00439   }
00440 
00441   // print total memory allocation information
00442 
00443   char sizechar;
00444 
00445   PRINT_INFO("\nTotal Memory Allocation Information\n\n");
00446   int divisor;
00447   if (a_obj_byte_total > 10000000) {
00448     sizechar = 'M';
00449     divisor = 1000000;
00450   }
00451   else {
00452     sizechar = 'K';
00453     divisor = 1000;
00454   }
00455   
00456   PRINT_INFO("  Allocated Memory: %ld%c (%ld bytes)\n", a_obj_byte_total/divisor, 
00457              sizechar, a_obj_byte_total);
00458 
00459   if (a_obj_byte_total)
00460   {
00461     PRINT_INFO("       Free Memory: %ld%c (%d%%)\n", f_obj_byte_total/divisor, sizechar,
00462            int((100.0*f_obj_byte_total)/a_obj_byte_total));
00463     PRINT_INFO("       Used Memory: %ld%c (%d%%)\n", u_obj_byte_total/divisor, 
00464                sizechar,
00465            int((100.0*u_obj_byte_total)/a_obj_byte_total));
00466   }
00467 
00468 #ifndef JANUS
00469 #ifndef _WIN32
00470   struct rusage r_usage;
00471   AppUtil::instance()->apputil_getrusage(r_usage);
00472   PRINT_INFO("       (System reports %ld%c used, incl. executable)\n", 
00473               r_usage.ru_maxrss*getpagesize()/divisor, sizechar);
00474 #else
00475   PRINT_INFO("\n");
00476 #endif // _WIN32
00477 #endif // JANUS
00478 
00479   // print DLList non-Pool allocation information
00480   PRINT_INFO("\nTotal non-pool ArrayBasedContainer memory allocation  = %u%c\n"
00481            "Maximum non-pool ArrayBasedContainer memory allocated = %u%c\n",
00482              ArrayBasedContainer::current_allocated_memory()/divisor, sizechar, 
00483              ArrayBasedContainer::maximum_allocated_memory()/divisor, sizechar);
00484 */
00485 
00486 
00487 
00488 #if 0
00489   // print HOOPS memory usage
00490   long allocated = 0;
00491   long in_use = 0;
00492     //  DrawingTool::instance()->show_memory(allocated, in_use);
00493   if (allocated != 0)
00494      PRINT_INFO("\nGraphics subsystem memory: Allocated = %u%c (%d bytes)\n"
00495                 "                           In-Use    = %u%c (%d%%)\n",
00496                 allocated/divisor, sizechar, allocated, 
00497                 in_use/divisor, sizechar, int((100.0*in_use)/allocated));
00498   else
00499      PRINT_INFO("\nGraphics subsystem memory: Allocated = %u%c (%d bytes)\n"
00500                 "                           In-Use    = %u%c (100%%)\n",
00501                 allocated/divisor, sizechar, allocated, 
00502                 in_use/divisor, sizechar);
00503 #endif
00504 }
00505 
00506 // compress memory for the requested object
00507 int MemoryManager::compress_object_memory(const char* name)
00508 {
00509   // find all instances of memory managers for object: name
00510 
00511   int found        = 0;
00512   int saved_memory = 0;
00513   MemoryManager* mem_manager = memoryManagerListHead;
00514   while (mem_manager)
00515   {
00516     if (!std::strcmp(mem_manager->objectName, name))
00517     {
00518       // if found then compress memory
00519 
00520       saved_memory += mem_manager->compress_memory();
00521       found         = 1;
00522     }
00523 
00524     mem_manager = mem_manager->next;
00525   }
00526 
00527   return found;
00528 }
00529 
00530 // compress all object memory
00531 int MemoryManager::compress_all_object_memory()
00532 {
00533   // find all instances of memory managers
00534   int saved_memory = 0;
00535   MemoryManager* mem_manager = memoryManagerListHead;
00536   MemoryManager* block_manager = NULL;
00537   while (mem_manager)
00538   {
00539     if (!std::strcmp(mem_manager->objectName, "MemoryBlock"))
00540     {
00541       // save block_manager until end
00542 
00543       block_manager = mem_manager;
00544     }
00545     else
00546     {
00547       // compress memory
00548 
00549       saved_memory += mem_manager->compress_memory();
00550     }
00551 
00552     mem_manager = mem_manager->next;
00553   }
00554 
00555   if (block_manager)
00556   {
00557     saved_memory += block_manager->compress_memory();
00558   }
00559 
00560   return saved_memory;
00561 }
00562       
00563 // generic operator new call
00564 void* MemoryManager::operator_new(size_t size)
00565 {
00566 
00567   if (useNew) return malloc(size);
00568 
00569   // send requests of "wrong" size to ::new
00570   
00571   try
00572   { 
00573     if (size != objectSize) return ::new char[size];
00574   }
00575   catch(...) 
00576   {
00577     return (void*) NULL;
00578   }
00579   // get new element from head of free list
00580 
00581   char* p = headOfFreeList;
00582 
00583   try
00584   {
00585     if(!p)
00586         {
00587         // allocate new block
00588 
00589         int block_size  = memAllocatnSize * size;
00590         char* new_block = ::new char[block_size];
00591         if (!new_block) return (void*) NULL;
00592 
00593         // link new elements to form the free list
00594 
00595         int fill_limit = (memAllocatnSize - 1) * size;
00596         for (int j = 0; j < fill_limit; j += size)
00597         {
00598           *((char**) &new_block[j]) = &new_block[j + size];
00599         }
00600         *((char**) &new_block[fill_limit]) = (char*) NULL;
00601 
00602         // assign new element
00603 
00604         p = new_block;
00605 
00606         // save new block to memory block stack
00607 
00608         memBlockStack = new MemoryBlock(memBlockStack, new_block, block_size);
00609       }
00610   }
00611   catch(...)
00612   {
00613     return (void*) NULL;
00614   }
00615   //assign head of free list and return p
00616 
00617   headOfFreeList = *((char**) p);
00618   return (void*) p;
00619 }
00620 
00621 // generic operator delete call
00622 void MemoryManager::operator_delete(void *deadObject, size_t size)
00623 {
00624   if (useNew) 
00625   {
00626     free(deadObject);
00627     return;
00628   }
00629 
00630   // requests of "wrong" size to ::delete
00631 
00632   if (size != objectSize)
00633   {
00634     ::delete [] ((char*) deadObject);
00635     return;
00636   }
00637 
00638   // attach dead element to head of free list
00639 
00640   char* delete_object = (char*) deadObject;
00641   *((char**) delete_object) = headOfFreeList;
00642   headOfFreeList = delete_object;
00643 }
00644 
00645 // compress memory blocks
00646 int MemoryManager::compress_memory()
00647 {
00648   // if free objects exist then begin compression algorithm
00649 
00650   if (headOfFreeList)
00651   {
00652     // find total number of memory blocks attached to stack
00653  
00654     int n_blocks = 0;
00655     MemoryBlock* mem_block = memBlockStack;
00656     while (mem_block)
00657     {
00658       n_blocks++;
00659       mem_block = mem_block->next_block();
00660     }
00661 
00662     if (n_blocks == 0)
00663     {
00664        // no available memory to free ... return 0
00665        // this is here for safety ... n_blocks should never be zero if
00666        // headOfFreeList is not Null
00667 
00668        return 0;
00669     }
00670     else
00671     {
00672       // first determine if all objects are free ... if so then perform
00673       // the easy compression routine
00674 
00675       if (!get_used_objects())
00676       {
00677         // all objects are free ... delete all blocks
00678 
00679         int n_bytes = memBlockStack->get_memory_allocation();
00680         destroy_memory(staticManager);
00681 
00682         // return freed memory
00683 
00684         return n_bytes;
00685       }
00686 
00687       // else perform the complex routine to remove those memory blocks that
00688       // have all free elements
00689 
00690       // begin by constructing an integer array for each memory block to
00691       // tally the number of free objects that each block contains
00692 
00693         // if there are a lot of blocks, we can save a huge amount of
00694         // time by looking in the last few blocks that contained an
00695         // element.
00696       const int use_cache = n_blocks > 8;
00697       int i, j, k;
00698       i = j = k = 0;
00699       const int cache_size = 4;
00700       MemoryBlock* mem_block_sav[cache_size];
00701       int i_sav[cache_size];
00702       for ( i = cache_size; i--; )
00703       {
00704         mem_block_sav[i] = NULL;
00705         i_sav[i] = 0;
00706       }
00707       int found = 0;
00708       
00709       mem_block = NULL;
00710       char* list_ptr = NULL;
00711       
00712       unsigned int* free_tally = new unsigned int [n_blocks];
00713       for (i = 0; i < n_blocks; i++) free_tally[i] = 0;
00714 
00715       // loop through free list tallying free elements
00716 
00717       list_ptr = headOfFreeList;
00718       while (list_ptr)
00719       {
00720         // find memory block that owns this element
00721         
00722           // check last few blocks for speed
00723         found = CUBIT_FALSE;
00724         if ( use_cache )
00725         {
00726           for ( i = 0; i < cache_size; i++ )
00727           {
00728             mem_block = mem_block_sav[i];
00729             if ( mem_block &&
00730                  list_ptr >= mem_block->get_block() &&
00731                  list_ptr < (mem_block->get_block() + 
00732                              mem_block->block_size()) )
00733             {
00734               k = i_sav[i];
00735               free_tally[k]++;
00736               found = CUBIT_TRUE;
00737               break;
00738             }
00739           }
00740         }
00741         if ( !found )
00742         {
00743             // search through all blocks
00744           mem_block = memBlockStack;
00745           for (i = 0; i < n_blocks; i++)
00746           {
00747             if ((list_ptr >= mem_block->get_block()) &&
00748                 (list_ptr < (mem_block->get_block() + mem_block->block_size())))
00749             {
00750                 // increment tally and exit
00751               
00752               free_tally[i]++;
00753                 // save
00754               if ( use_cache && mem_block_sav[j] != mem_block )
00755               {
00756                 mem_block_sav[j] = mem_block;
00757                 i_sav[j] = i;
00758                 if ( ++j >= cache_size )
00759                   j = 0;
00760               }
00761               break;
00762             }
00763             
00764               //  get next memory block
00765             mem_block = mem_block->next_block();
00766           }
00767         }
00768 
00769         // get next element
00770         list_ptr = *((char**) list_ptr);
00771       }
00772 
00773       // zero tally for memory blocks that cannot be removed ... those that
00774       // have some used elements
00775 
00776       int all_blocks = 0;
00777       mem_block = memBlockStack;
00778       for (i = 0; i < n_blocks; i++)
00779       {
00780         if (free_tally[i] != (mem_block->block_size() / objectSize))
00781     {
00782           free_tally[i] = 0;
00783           all_blocks++;
00784         }
00785 
00786         mem_block = mem_block->next_block();
00787       }
00788 
00789       if (all_blocks == n_blocks)
00790       {
00791         // no memory can be saved ... all blocks have some used elements
00792         // return 0
00793 
00794         delete [] free_tally;
00795         return 0;
00796       }
00797 
00798       // adjust free list pointers to remove those that belong to
00799       // memory blocks that can be deleted
00800       char* prev_ptr = NULL;
00801       list_ptr = headOfFreeList;
00802       while (list_ptr)
00803       {
00804         // find memory block that owns this element
00805           // check last few blocks for speed
00806         found = CUBIT_FALSE;
00807         if ( use_cache )
00808         {
00809           for ( i = 0; i < cache_size; i++ )
00810           {
00811             mem_block = mem_block_sav[i];
00812             if ( mem_block &&
00813                  list_ptr >= mem_block->get_block() &&
00814                  list_ptr < (mem_block->get_block() + 
00815                              mem_block->block_size()) )
00816             {
00817               k = i_sav[i];
00818               found = CUBIT_TRUE;
00819               break;
00820             }
00821           }
00822         }
00823         if ( !found )
00824         {
00825           mem_block = memBlockStack;
00826           for (i = 0; i < n_blocks; i++)
00827           {
00828             if ((list_ptr >= mem_block->get_block()) &&
00829                 (list_ptr < (mem_block->get_block() + mem_block->block_size())))
00830             {
00831               k = i;
00832                 // save
00833               if ( use_cache && mem_block_sav[j] != mem_block )
00834               {
00835                 mem_block_sav[j] = mem_block;
00836                 i_sav[j] = i;
00837                 if ( ++j >= cache_size )
00838                   j = 0;
00839               }
00840               break;
00841             }
00842               // get next memory block
00843             mem_block = mem_block->next_block();
00844           }
00845         }
00846         
00847         if (free_tally[k])
00848         {
00849             // remove element
00850           
00851           if (prev_ptr)
00852           {
00853             *((char**) prev_ptr) = *((char**) list_ptr);
00854           }
00855           else
00856           {
00857             headOfFreeList = *((char**) list_ptr);
00858           }
00859         }
00860         else
00861         {
00862             // advance prev_ptr  
00863           prev_ptr = list_ptr;
00864         }
00865 
00866         // get next element
00867         list_ptr = *((char**) list_ptr);
00868       }
00869 
00870       // delete all memory blocks that have free_tally[i] > 0
00871 
00872       i = 0;
00873       int save_bytes = 0;
00874       MemoryBlock* prev_block = NULL;
00875       mem_block               = memBlockStack;
00876       while (mem_block)
00877       {
00878         if (free_tally[i])
00879         {
00880           // set previous MemoryBlocks next pointer to skip this block
00881 
00882           if (prev_block)
00883           {
00884             prev_block->next_block(mem_block->next_block());
00885           }
00886           else
00887           {
00888             memBlockStack = mem_block->next_block();
00889           }
00890 
00891           // set MemoryBlock next pointer to NULL to avoid recusive delete
00892           // update saved memory and delete mem_block
00893 
00894           mem_block->next_block((MemoryBlock*) NULL);
00895           save_bytes += mem_block->block_size();
00896           delete mem_block;
00897 
00898           // update mem_block to point to new current MemoryBlock
00899 
00900           if (prev_block)
00901           {
00902             mem_block = prev_block->next_block();
00903           }
00904           else
00905           {
00906             mem_block = memBlockStack;
00907           }
00908         }
00909         else
00910         {
00911           // if block wasn't removed then update previous and current blocks
00912 
00913           prev_block = mem_block;
00914           mem_block = mem_block->next_block();
00915         }
00916 
00917         // increment to next block (used by free_tally array)
00918 
00919         ++i;
00920       }
00921 
00922       // return freed memory (bytes)
00923 
00924       delete [] free_tally;
00925       return save_bytes;
00926     }
00927   }
00928   else
00929   {
00930     // no memory allocated ... return 0
00931 
00932     return 0;
00933   }
00934 }
00935 
00936 
00937 void MemoryManager::process_mem_usage(unsigned long &vm_usage, unsigned long &resident_set)
00938 {
00939 
00940 #if defined(CUBIT_LINUX)
00941   using std::ios_base;
00942   using std::ifstream;
00943   using std::string;
00944 
00945   vm_usage     = 0;
00946   resident_set = 0;
00947 
00948   // 'file' stat seems to give the most reliable results
00949   //
00950   ifstream stat_stream("/proc/self/stat",ios_base::in);
00951   
00952   // dummy vars for leading entries in stat that we don't care about
00953   //
00954   string pid, comm, state, ppid, pgrp, session, tty_nr;
00955   string tpgid, flags, minflt, cminflt, majflt, cmajflt;
00956   string utime, stime, cutime, cstime, priority, nice;
00957   string O, itrealvalue, starttime;
00958   
00959   // the two fields we want...virtual memory size and resident memory size
00960   //
00961   unsigned long vsize;
00962   long rss;
00963   
00964   stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
00965               >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
00966               >> utime >> stime >> cutime >> cstime >> priority >> nice
00967               >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
00968               
00969   long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
00970   vm_usage     = vsize / 1024;
00971   resident_set = rss * page_size_kb;
00972 #else
00973   vm_usage = 0;
00974   resident_set = 0;
00975 #endif
00976 }
00977   
00978  
00979 void MemoryManager::process_file_io(unsigned long &read, unsigned long &write )
00980 {
00981 #if defined(CUBIT_LINUX)
00982   using std::ios_base;
00983   using std::ifstream;
00984   using std::string;
00985 
00986   read = 0;
00987   write = 0;
00988 
00989   // 'file' stat seems to give the most reliable results
00990   //
00991   ifstream stat_stream("/proc/self/io",ios_base::in);
00992   
00993   // dummy vars for leading entries in stat that we don't care about
00994   //
00995   string char1, char2;
00996 
00997   //----------------------Getting two numbers out of this file 
00998   // I/O counter: chars read
00999   //The number of bytes which this task has caused to be read from storage. This
01000   //is simply the sum of bytes which this process passed to read() and pread().
01001   //It includes things like tty IO and it is unaffected by whether or not actual
01002   //physical disk IO was required (the read might have been satisfied from
01003   //pagecache)
01004   
01005   // I/O counter: chars written
01006   //The number of bytes which this task has caused, or shall cause to be written
01007   //to disk. Similar caveats apply here as with rchar.
01008   
01009   unsigned long tmp_read, tmp_write;
01010   
01011   stat_stream >> char1 >> tmp_read >> char2 >> tmp_write; //don't care about the rest 
01012   
01013   read = tmp_read;
01014   write = tmp_write;
01015 #else
01016   read = 0;
01017   write = 0;
01018 #endif
01019 }
01020 
01021 
01022 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines