cgma
|
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