Branch data Line data Source code
1 : : //- Class: MemoryManager
2 : : //- Owner: Jim Hipp
3 : : //- Description: MemoryManager provides object information and stack
4 : : //- storage pointer management used in association with
5 : : //- MemoryBlock and MemoryAllocation classes.
6 : : //- Checked By:
7 : : //- Version:
8 : : // Modified 5/7/96 R W Ostensen: Fixed operator_new function as per recommendation
9 : : // from J Hipp. Eliminated assignment of headOfFreeList to wild pointer loaction when
10 : : // memAllocatnSize=1.
11 : :
12 : :
13 : : #include "MemoryBlock.hpp"
14 : : #include "MemoryManager.hpp"
15 : : #include "CubitMessage.hpp"
16 : : #include "ArrayBasedContainer.hpp"
17 : : #include "AppUtil.hpp"
18 : : #include <cassert>
19 : : #include <cstring>
20 : : #include <iostream>
21 : : #ifndef _WIN32
22 : : #include <unistd.h>
23 : : #endif
24 : :
25 : :
26 : : MemoryManager* MemoryManager::memoryManagerListHead = NULL;
27 : :
28 : : // constructors
29 : 0 : MemoryManager::MemoryManager() : useNew(false), objectName(NULL)
30 : : {
31 : : // do not allow default constructor (must assign objectSize)
32 : 0 : assert(0);
33 : : }
34 : :
35 : 0 : MemoryManager::MemoryManager(const MemoryManager&) : useNew(false), objectName(NULL)
36 : : {
37 : : // do not allow copy
38 : 0 : assert(0);
39 : : }
40 : :
41 : 17985 : MemoryManager::MemoryManager(const char* name, size_t size, int mem_size,
42 : : int static_flag)
43 : 17985 : : useNew(true)
44 : : {
45 : : // allocate space for name and copy into buffer
46 [ + - ]: 17985 : if (name)
47 : : {
48 : 17985 : objectName = new char[std::strlen(name) + 1];
49 : 17985 : std::strcpy(objectName, name);
50 : : }
51 : : else
52 : 0 : objectName = NULL;
53 : :
54 : : // initialize manager parameters
55 : 17985 : staticManager = static_flag;
56 : 17985 : memBlockStack = NULL;
57 : 17985 : headOfFreeList = NULL;
58 : :
59 [ - + ]: 17985 : assert(size >= sizeof(char*));
60 : 17985 : objectSize = size;
61 : :
62 : 17985 : set_memory_allocation_increment(mem_size);
63 : :
64 : : // attach new manager to static stack
65 : 17985 : next = memoryManagerListHead;
66 : 17985 : memoryManagerListHead = this;
67 : 17985 : }
68 : :
69 : : // destructor
70 : 17985 : MemoryManager::~MemoryManager()
71 : : {
72 : : // delete objectName space and destroy block memory
73 [ + - ]: 17985 : delete [] objectName;
74 : 17985 : objectName = NULL;
75 : 17985 : destroy_memory(staticManager);
76 : :
77 : : // find 'prev' manager pointer
78 : 17985 : MemoryManager* prev = NULL;
79 : 17985 : MemoryManager* mem_manager = memoryManagerListHead;
80 : 17985 : bool first = true;
81 [ + - ][ - + ]: 17985 : while (mem_manager && mem_manager != this)
82 : : {
83 [ # # ][ # # ]: 0 : if (!first && mem_manager == memoryManagerListHead)
84 : : {
85 : : // XXX: We aren't in the list!?
86 : 0 : std::cerr << "MemoryManager: corrupted list?" << std::endl;
87 : 0 : return;
88 : : }
89 : 0 : first = false;
90 : 0 : prev = mem_manager;
91 : 0 : mem_manager = mem_manager->next;
92 : : }
93 : :
94 : : // remove memory manager from static list
95 : :
96 [ + + ]: 17985 : if (!next)
97 : : {
98 [ + - ]: 1635 : if (!prev)
99 : : {
100 : : // no memory managers left
101 : :
102 : 1635 : memoryManagerListHead = NULL;
103 : : }
104 : : else
105 : : {
106 : : // remove tail node
107 : :
108 : 1635 : prev->next = NULL;
109 : : }
110 : : }
111 : : else
112 : : {
113 [ + - ]: 16350 : if (!prev)
114 : : {
115 : : // remove head node
116 : :
117 : 16350 : memoryManagerListHead = next;
118 : : }
119 : : else
120 : : {
121 : : // remove intermediate node
122 : :
123 : 0 : prev->next = next;
124 : : }
125 : : }
126 : 17985 : }
127 : :
128 : : // set memory block allocation increment
129 : 17985 : void MemoryManager::set_memory_allocation_increment(int mem_size)
130 : : {
131 : : // set memory allocation increment
132 : :
133 [ - + ]: 17985 : if (mem_size <= 0)
134 : : {
135 : 0 : memAllocatnSize = DEFAULT_MEMORY_ALLOC_SIZE;
136 : : }
137 : : else
138 : : {
139 : 17985 : memAllocatnSize = mem_size;
140 : : }
141 : 17985 : }
142 : :
143 : : // destroy allocated block memory
144 : 17985 : void MemoryManager::destroy_memory(int static_flag)
145 : : {
146 : : // assert if this is not a static memory manager and some of it's objects
147 : : // are still in use
148 [ - + ]: 17985 : if (!static_flag) {
149 [ # # ]: 0 : assert (!get_used_objects());
150 : : }
151 : :
152 : : // else delete block memory if any was allocated
153 [ - + ][ # # ]: 17985 : if (memBlockStack) delete memBlockStack;
154 : :
155 : : // reset stack pointers to empty
156 : 17985 : headOfFreeList = NULL;
157 : 17985 : memBlockStack = NULL;
158 : 17985 : }
159 : :
160 : : // return number of objects allocated
161 : 0 : int MemoryManager::get_allocated_objects()
162 : : {
163 : : // return total number of objects allocated for this memory manager
164 : :
165 [ # # ]: 0 : if (memBlockStack)
166 : : {
167 : 0 : return (memBlockStack->get_memory_allocation() / objectSize);
168 : : }
169 : : else
170 : : {
171 : 0 : return 0;
172 : : }
173 : : }
174 : :
175 : : // return free objects
176 : 0 : int MemoryManager::get_free_objects()
177 : : {
178 : : // return total number of free objects (allocated but not used) for this
179 : : // memory manager
180 : :
181 [ # # ]: 0 : if (headOfFreeList)
182 : : {
183 : 0 : int i = 0;
184 : 0 : char* list_ptr = headOfFreeList;
185 [ # # ]: 0 : while (list_ptr)
186 : : {
187 : 0 : i++;
188 : 0 : list_ptr = *((char**) list_ptr);
189 : : }
190 : :
191 : 0 : return i;
192 : : }
193 : : else
194 : : {
195 : 0 : return 0;
196 : : }
197 : : }
198 : :
199 : : // return used objects
200 : 0 : int MemoryManager::get_used_objects()
201 : : {
202 : : // return total number of used objects for this memory manager
203 : :
204 : 0 : return (get_allocated_objects() - get_free_objects());
205 : : }
206 : :
207 : : // print allocation information to the command line
208 : 0 : void MemoryManager::show_object_memory(const char* name)
209 : : {
210 : 0 : int instance = 0;
211 : :
212 : : // find all instances of memory managers for object: name
213 : :
214 : 0 : MemoryManager* mem_manager = memoryManagerListHead;
215 [ # # ]: 0 : while (mem_manager)
216 : : {
217 [ # # ]: 0 : if (!std::strcmp(mem_manager->objectName, name))
218 : : {
219 : : // if found then print pertinent memory allocation information
220 : :
221 : 0 : instance++;
222 [ # # ]: 0 : if (instance > 1)
223 : : {
224 [ # # ][ # # ]: 0 : PRINT_INFO("\nObject Name(%d): %s\n\n", instance, name);
225 : : }
226 : : else
227 : : {
228 [ # # ][ # # ]: 0 : PRINT_INFO("\nObject Name: %s\n\n", name);
229 : : }
230 : :
231 : 0 : int a_obj = mem_manager->get_allocated_objects();
232 : 0 : int f_obj = mem_manager->get_free_objects();
233 : 0 : int u_obj = a_obj - f_obj;
234 : :
235 [ # # ]: 0 : PRINT_INFO(" Object Size: %lu Allocation Increment: %d\n\n",
236 [ # # ]: 0 : (unsigned long)mem_manager->objectSize, mem_manager->memAllocatnSize);
237 [ # # ]: 0 : PRINT_INFO(" Allocated Objects: %d (bytes) %d\n", a_obj,
238 [ # # ]: 0 : a_obj * (int)(mem_manager->objectSize));
239 [ # # ]: 0 : if (a_obj)
240 : : {
241 [ # # ]: 0 : PRINT_INFO(" Free Objects: %d (bytes) %d (%d%%)\n", f_obj,
242 : : f_obj * (int)(mem_manager->objectSize),
243 [ # # ]: 0 : (100*f_obj)/a_obj);
244 [ # # ]: 0 : PRINT_INFO(" Used Objects: %d (bytes) %d (%d%%)\n", u_obj,
245 : : u_obj * (int)(mem_manager->objectSize),
246 [ # # ]: 0 : (100*u_obj)/a_obj);
247 : : }
248 : : }
249 : :
250 : : // get next memory manager
251 : :
252 : 0 : mem_manager = mem_manager->next;
253 : : }
254 : :
255 : : // if none were found then announce
256 : :
257 [ # # ]: 0 : if (!instance)
258 : : {
259 [ # # ][ # # ]: 0 : PRINT_INFO("\nObject: %s was not found ...\n", name);
260 : : }
261 : 0 : }
262 : :
263 : :
264 : : // show allocation for all memory manager objects
265 : 0 : void MemoryManager::show_all_object_memory()
266 : : {
267 : :
268 : : #if defined(MACOSX)
269 : :
270 : : pid_t PID = getpid();
271 : : char command1[60];
272 : : unsigned long rss=0, vm=0;
273 : :
274 : : FILE *pipe;
275 : : char buf[1024];
276 : :
277 : : //get size of real memory
278 : : sprintf(command1,"ps -o rss -p %d | grep -v RSS",PID);
279 : : pipe = popen(command1, "r");
280 : : if (pipe)
281 : : {
282 : : fgets(buf, 1024, pipe);
283 : : rss = strtoul(buf, NULL, 0);
284 : : pclose(pipe);
285 : : }
286 : :
287 : : //get size of virtual memory
288 : : sprintf(command1,"ps -o vsz -p %d | grep -v VSZ",PID);
289 : : pipe = popen(command1, "r");
290 : : if (pipe)
291 : : {
292 : : fgets(buf, 1024, pipe);
293 : : vm = strtoul(buf, NULL, 0);
294 : : pclose(pipe);
295 : : }
296 : :
297 : : PRINT_INFO("Total memory = %lu\n", (unsigned long)vm );
298 : : PRINT_INFO("Resident memory = %lu\n", (unsigned long)rss );
299 : :
300 : :
301 : : /*
302 : : struct rusage my_rusage;
303 : : int ret_val = getrusage( RUSAGE_CHILDREN, &my_rusage );
304 : :
305 : : if( ret_val == 0 )
306 : : {
307 : : PRINT_INFO("It was a success\n");
308 : : PRINT_INFO("Memory size = %d\n", my_rusage.ru_maxrss );
309 : : PRINT_INFO("Unshared data size = %d\n", my_rusage.ru_idrss);
310 : : PRINT_INFO("Integeral unshared data size = %d\n", my_rusage.ru_isrss);
311 : : PRINT_INFO("more values: %d %d %d %d %d %d %d %d %d %d %d \n",
312 : : my_rusage.ru_ixrss, my_rusage.ru_minflt, my_rusage.ru_majflt, my_rusage.ru_nswap,
313 : : my_rusage.ru_inblock, my_rusage.ru_oublock, my_rusage.ru_msgsnd, my_rusage.ru_msgrcv,
314 : : my_rusage.ru_nsignals, my_rusage.ru_nvcsw, my_rusage.ru_nivcsw );
315 : : }
316 : : else
317 : : PRINT_INFO("It was a failure\n");
318 : : */
319 : :
320 : :
321 : : /*
322 : : int i, mib[4];
323 : : size_t len;
324 : : struct kinfo_proc kp;
325 : :
326 : : len = 4;
327 : : sysctlnametomib("kern.proc.pid", mib, &len);
328 : : len = sizeof(kp);
329 : : int pid = getpid();
330 : : mib[3] = pid;
331 : : if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
332 : : {
333 : : perror("sysctl");
334 : : PRINT_INFO("Got problems\n");
335 : : }
336 : : else if (len > 0)
337 : : {
338 : : PRINT_INFO("The call was successful!!!\n");
339 : : }
340 : : */
341 : :
342 : : /*
343 : : int i, mib[4];
344 : : size_t len;
345 : : struct kinfo_proc kp;
346 : :
347 : : len = 4;
348 : : sysctlnametomib("kern.proc.pid", mib, &len);
349 : :
350 : : for (i = 0; i < 100; i++)
351 : : {
352 : : mib[3] = i;
353 : : len = sizeof(kp);
354 : : if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
355 : : perror("sysctl");
356 : : else if (len > 0)
357 : : PRINT_INFO("Call was successful!\n");
358 : : }
359 : : */
360 : :
361 : : #endif
362 : :
363 : :
364 : : #if defined(CUBIT_LINUX)
365 : : unsigned long vm, rss;
366 [ # # ]: 0 : process_mem_usage( vm, rss );
367 : :
368 : : unsigned long read, write;
369 [ # # ]: 0 : process_file_io( read, write );
370 : :
371 [ # # ][ # # ]: 0 : PRINT_INFO("Total memory = %lu\n", vm );
[ # # ][ # # ]
372 [ # # ][ # # ]: 0 : PRINT_INFO("Resident memory = %lu\n", rss );
[ # # ][ # # ]
373 [ # # ][ # # ]: 0 : PRINT_INFO("Bytes read = %lu\n", read );
[ # # ][ # # ]
374 [ # # ][ # # ]: 0 : PRINT_INFO("Bytes written = %lu\n", write );
[ # # ][ # # ]
375 : : #endif
376 : :
377 : : /*
378 : : long int a_obj_byte_total = 0;
379 : : long int f_obj_byte_total = 0;
380 : : long int u_obj_byte_total = 0;
381 : :
382 : : // loop over all memory managers
383 : :
384 : : PRINT_INFO("\nDynamic Memory Allocation per Object\n\n");
385 : :
386 : : MemoryManager* mem_manager = memoryManagerListHead;
387 : : while (mem_manager) {
388 : : long int a_obj = mem_manager->get_allocated_objects();
389 : : long int f_obj = mem_manager->get_free_objects();
390 : : long int u_obj = a_obj - f_obj;
391 : : if (a_obj) {
392 : : // sum total allocated memory parameters (bytes)
393 : : a_obj_byte_total += a_obj * mem_manager->objectSize;
394 : : f_obj_byte_total += f_obj * mem_manager->objectSize;
395 : : u_obj_byte_total += u_obj * mem_manager->objectSize;
396 : : }
397 : : mem_manager = mem_manager->next;
398 : : }
399 : :
400 : : mem_manager = memoryManagerListHead;
401 : : while (mem_manager)
402 : : {
403 : : // print pertinent memory allocation information
404 : :
405 : : long int a_obj = mem_manager->get_allocated_objects();
406 : : long int f_obj = mem_manager->get_free_objects();
407 : : long int u_obj = a_obj - f_obj;
408 : :
409 : : if (a_obj)
410 : : {
411 : : PRINT_INFO("\nObject Name: %s\n\n", mem_manager->objectName);
412 : :
413 : : PRINT_INFO(" Object Size: %d Allocation Increment: %d\n\n",
414 : : mem_manager->objectSize, mem_manager->memAllocatnSize);
415 : : if (a_obj_byte_total != 0)
416 : : {
417 : : PRINT_INFO(" Allocated Objects: %ld (bytes) %ld (%d%% of Total)\n",
418 : : a_obj, a_obj * mem_manager->objectSize,
419 : : int((100.0*a_obj * mem_manager->objectSize)/a_obj_byte_total));
420 : : PRINT_INFO(" Free Objects: %ld (bytes) %ld (%d%%)\n", f_obj,
421 : : f_obj * mem_manager->objectSize,
422 : : int((100.0*f_obj)/a_obj));
423 : : PRINT_INFO(" Used Objects: %ld (bytes) %ld (%d%%)\n", u_obj,
424 : : u_obj * mem_manager->objectSize,
425 : : int((100.0*u_obj)/a_obj));
426 : : }
427 : : else
428 : : {
429 : : PRINT_INFO(" Allocated Objects: %ld (bytes) %ld (100%% of Total)\n",
430 : : a_obj, a_obj * mem_manager->objectSize);
431 : : PRINT_INFO(" Free Objects: %ld (bytes) %ld (100%%)\n", f_obj,
432 : : f_obj * mem_manager->objectSize);
433 : : PRINT_INFO(" Used Objects: %ld (bytes) %ld (100%%)\n", u_obj,
434 : : u_obj * mem_manager->objectSize);
435 : : }
436 : : }
437 : :
438 : : mem_manager = mem_manager->next;
439 : : }
440 : :
441 : : // print total memory allocation information
442 : :
443 : : char sizechar;
444 : :
445 : : PRINT_INFO("\nTotal Memory Allocation Information\n\n");
446 : : int divisor;
447 : : if (a_obj_byte_total > 10000000) {
448 : : sizechar = 'M';
449 : : divisor = 1000000;
450 : : }
451 : : else {
452 : : sizechar = 'K';
453 : : divisor = 1000;
454 : : }
455 : :
456 : : PRINT_INFO(" Allocated Memory: %ld%c (%ld bytes)\n", a_obj_byte_total/divisor,
457 : : sizechar, a_obj_byte_total);
458 : :
459 : : if (a_obj_byte_total)
460 : : {
461 : : PRINT_INFO(" Free Memory: %ld%c (%d%%)\n", f_obj_byte_total/divisor, sizechar,
462 : : int((100.0*f_obj_byte_total)/a_obj_byte_total));
463 : : PRINT_INFO(" Used Memory: %ld%c (%d%%)\n", u_obj_byte_total/divisor,
464 : : sizechar,
465 : : int((100.0*u_obj_byte_total)/a_obj_byte_total));
466 : : }
467 : :
468 : : #ifndef JANUS
469 : : #ifndef _WIN32
470 : : struct rusage r_usage;
471 : : AppUtil::instance()->apputil_getrusage(r_usage);
472 : : PRINT_INFO(" (System reports %ld%c used, incl. executable)\n",
473 : : r_usage.ru_maxrss*getpagesize()/divisor, sizechar);
474 : : #else
475 : : PRINT_INFO("\n");
476 : : #endif // _WIN32
477 : : #endif // JANUS
478 : :
479 : : // print DLList non-Pool allocation information
480 : : PRINT_INFO("\nTotal non-pool ArrayBasedContainer memory allocation = %u%c\n"
481 : : "Maximum non-pool ArrayBasedContainer memory allocated = %u%c\n",
482 : : ArrayBasedContainer::current_allocated_memory()/divisor, sizechar,
483 : : ArrayBasedContainer::maximum_allocated_memory()/divisor, sizechar);
484 : : */
485 : :
486 : :
487 : :
488 : : #if 0
489 : : // print HOOPS memory usage
490 : : long allocated = 0;
491 : : long in_use = 0;
492 : : // DrawingTool::instance()->show_memory(allocated, in_use);
493 : : if (allocated != 0)
494 : : PRINT_INFO("\nGraphics subsystem memory: Allocated = %u%c (%d bytes)\n"
495 : : " In-Use = %u%c (%d%%)\n",
496 : : allocated/divisor, sizechar, allocated,
497 : : in_use/divisor, sizechar, int((100.0*in_use)/allocated));
498 : : else
499 : : PRINT_INFO("\nGraphics subsystem memory: Allocated = %u%c (%d bytes)\n"
500 : : " In-Use = %u%c (100%%)\n",
501 : : allocated/divisor, sizechar, allocated,
502 : : in_use/divisor, sizechar);
503 : : #endif
504 : 0 : }
505 : :
506 : : // compress memory for the requested object
507 : 0 : int MemoryManager::compress_object_memory(const char* name)
508 : : {
509 : : // find all instances of memory managers for object: name
510 : :
511 : 0 : int found = 0;
512 : 0 : int saved_memory = 0;
513 : 0 : MemoryManager* mem_manager = memoryManagerListHead;
514 [ # # ]: 0 : while (mem_manager)
515 : : {
516 [ # # ]: 0 : if (!std::strcmp(mem_manager->objectName, name))
517 : : {
518 : : // if found then compress memory
519 : :
520 : 0 : saved_memory += mem_manager->compress_memory();
521 : 0 : found = 1;
522 : : }
523 : :
524 : 0 : mem_manager = mem_manager->next;
525 : : }
526 : :
527 : 0 : return found;
528 : : }
529 : :
530 : : // compress all object memory
531 : 0 : int MemoryManager::compress_all_object_memory()
532 : : {
533 : : // find all instances of memory managers
534 : 0 : int saved_memory = 0;
535 : 0 : MemoryManager* mem_manager = memoryManagerListHead;
536 : 0 : MemoryManager* block_manager = NULL;
537 [ # # ]: 0 : while (mem_manager)
538 : : {
539 [ # # ]: 0 : if (!std::strcmp(mem_manager->objectName, "MemoryBlock"))
540 : : {
541 : : // save block_manager until end
542 : :
543 : 0 : block_manager = mem_manager;
544 : : }
545 : : else
546 : : {
547 : : // compress memory
548 : :
549 : 0 : saved_memory += mem_manager->compress_memory();
550 : : }
551 : :
552 : 0 : mem_manager = mem_manager->next;
553 : : }
554 : :
555 [ # # ]: 0 : if (block_manager)
556 : : {
557 : 0 : saved_memory += block_manager->compress_memory();
558 : : }
559 : :
560 : 0 : return saved_memory;
561 : : }
562 : :
563 : : // generic operator new call
564 : 8362 : void* MemoryManager::operator_new(size_t size)
565 : : {
566 : :
567 [ + - ]: 8362 : if (useNew) return malloc(size);
568 : :
569 : : // send requests of "wrong" size to ::new
570 : :
571 : : try
572 : : {
573 [ # # ][ # # ]: 0 : if (size != objectSize) return ::new char[size];
574 : : }
575 : 0 : catch(...)
576 : : {
577 : 0 : return (void*) NULL;
578 : : }
579 : : // get new element from head of free list
580 : :
581 : 0 : char* p = headOfFreeList;
582 : :
583 : : try
584 : : {
585 [ # # ]: 0 : if(!p)
586 : : {
587 : : // allocate new block
588 : :
589 : 0 : int block_size = memAllocatnSize * size;
590 [ # # ]: 0 : char* new_block = ::new char[block_size];
591 [ # # ]: 0 : if (!new_block) return (void*) NULL;
592 : :
593 : : // link new elements to form the free list
594 : :
595 : 0 : int fill_limit = (memAllocatnSize - 1) * size;
596 [ # # ]: 0 : for (int j = 0; j < fill_limit; j += size)
597 : : {
598 : 0 : *((char**) &new_block[j]) = &new_block[j + size];
599 : : }
600 : 0 : *((char**) &new_block[fill_limit]) = (char*) NULL;
601 : :
602 : : // assign new element
603 : :
604 : 0 : p = new_block;
605 : :
606 : : // save new block to memory block stack
607 : :
608 [ # # ][ # # ]: 0 : memBlockStack = new MemoryBlock(memBlockStack, new_block, block_size);
609 : : }
610 : : }
611 : 0 : catch(...)
612 : : {
613 : 0 : return (void*) NULL;
614 : : }
615 : : //assign head of free list and return p
616 : :
617 : 0 : headOfFreeList = *((char**) p);
618 : 8362 : return (void*) p;
619 : : }
620 : :
621 : : // generic operator delete call
622 : 2736 : void MemoryManager::operator_delete(void *deadObject, size_t size)
623 : : {
624 [ + - ]: 2736 : if (useNew)
625 : : {
626 : 2736 : free(deadObject);
627 : 2736 : return;
628 : : }
629 : :
630 : : // requests of "wrong" size to ::delete
631 : :
632 [ # # ]: 0 : if (size != objectSize)
633 : : {
634 [ # # ]: 0 : ::delete [] ((char*) deadObject);
635 : 0 : return;
636 : : }
637 : :
638 : : // attach dead element to head of free list
639 : :
640 : 0 : char* delete_object = (char*) deadObject;
641 : 0 : *((char**) delete_object) = headOfFreeList;
642 : 0 : headOfFreeList = delete_object;
643 : : }
644 : :
645 : : // compress memory blocks
646 : 0 : int MemoryManager::compress_memory()
647 : : {
648 : : // if free objects exist then begin compression algorithm
649 : :
650 [ # # ]: 0 : if (headOfFreeList)
651 : : {
652 : : // find total number of memory blocks attached to stack
653 : :
654 : 0 : int n_blocks = 0;
655 : 0 : MemoryBlock* mem_block = memBlockStack;
656 [ # # ]: 0 : while (mem_block)
657 : : {
658 : 0 : n_blocks++;
659 : 0 : mem_block = mem_block->next_block();
660 : : }
661 : :
662 [ # # ]: 0 : if (n_blocks == 0)
663 : : {
664 : : // no available memory to free ... return 0
665 : : // this is here for safety ... n_blocks should never be zero if
666 : : // headOfFreeList is not Null
667 : :
668 : 0 : return 0;
669 : : }
670 : : else
671 : : {
672 : : // first determine if all objects are free ... if so then perform
673 : : // the easy compression routine
674 : :
675 [ # # ][ # # ]: 0 : if (!get_used_objects())
676 : : {
677 : : // all objects are free ... delete all blocks
678 : :
679 [ # # ]: 0 : int n_bytes = memBlockStack->get_memory_allocation();
680 [ # # ]: 0 : destroy_memory(staticManager);
681 : :
682 : : // return freed memory
683 : :
684 : 0 : return n_bytes;
685 : : }
686 : :
687 : : // else perform the complex routine to remove those memory blocks that
688 : : // have all free elements
689 : :
690 : : // begin by constructing an integer array for each memory block to
691 : : // tally the number of free objects that each block contains
692 : :
693 : : // if there are a lot of blocks, we can save a huge amount of
694 : : // time by looking in the last few blocks that contained an
695 : : // element.
696 : 0 : const int use_cache = n_blocks > 8;
697 : : int i, j, k;
698 : 0 : i = j = k = 0;
699 : 0 : const int cache_size = 4;
700 : : MemoryBlock* mem_block_sav[cache_size];
701 : : int i_sav[cache_size];
702 [ # # ]: 0 : for ( i = cache_size; i--; )
703 : : {
704 : 0 : mem_block_sav[i] = NULL;
705 : 0 : i_sav[i] = 0;
706 : : }
707 : 0 : int found = 0;
708 : :
709 : 0 : mem_block = NULL;
710 : 0 : char* list_ptr = NULL;
711 : :
712 [ # # ][ # # ]: 0 : unsigned int* free_tally = new unsigned int [n_blocks];
713 [ # # ]: 0 : for (i = 0; i < n_blocks; i++) free_tally[i] = 0;
714 : :
715 : : // loop through free list tallying free elements
716 : :
717 : 0 : list_ptr = headOfFreeList;
718 [ # # ]: 0 : while (list_ptr)
719 : : {
720 : : // find memory block that owns this element
721 : :
722 : : // check last few blocks for speed
723 : 0 : found = CUBIT_FALSE;
724 [ # # ]: 0 : if ( use_cache )
725 : : {
726 [ # # ]: 0 : for ( i = 0; i < cache_size; i++ )
727 : : {
728 : 0 : mem_block = mem_block_sav[i];
729 [ # # ][ # # ]: 0 : if ( mem_block &&
730 [ # # ][ # # ]: 0 : list_ptr >= mem_block->get_block() &&
[ # # ]
731 [ # # ]: 0 : list_ptr < (mem_block->get_block() +
732 [ # # ]: 0 : mem_block->block_size()) )
733 : : {
734 : 0 : k = i_sav[i];
735 : 0 : free_tally[k]++;
736 : 0 : found = CUBIT_TRUE;
737 : 0 : break;
738 : : }
739 : : }
740 : : }
741 [ # # ]: 0 : if ( !found )
742 : : {
743 : : // search through all blocks
744 : 0 : mem_block = memBlockStack;
745 [ # # ]: 0 : for (i = 0; i < n_blocks; i++)
746 : : {
747 [ # # ][ # # ]: 0 : if ((list_ptr >= mem_block->get_block()) &&
[ # # ][ # # ]
748 [ # # ][ # # ]: 0 : (list_ptr < (mem_block->get_block() + mem_block->block_size())))
749 : : {
750 : : // increment tally and exit
751 : :
752 : 0 : free_tally[i]++;
753 : : // save
754 [ # # ][ # # ]: 0 : if ( use_cache && mem_block_sav[j] != mem_block )
755 : : {
756 : 0 : mem_block_sav[j] = mem_block;
757 : 0 : i_sav[j] = i;
758 [ # # ]: 0 : if ( ++j >= cache_size )
759 : 0 : j = 0;
760 : : }
761 : 0 : break;
762 : : }
763 : :
764 : : // get next memory block
765 [ # # ]: 0 : mem_block = mem_block->next_block();
766 : : }
767 : : }
768 : :
769 : : // get next element
770 : 0 : list_ptr = *((char**) list_ptr);
771 : : }
772 : :
773 : : // zero tally for memory blocks that cannot be removed ... those that
774 : : // have some used elements
775 : :
776 : 0 : int all_blocks = 0;
777 : 0 : mem_block = memBlockStack;
778 [ # # ]: 0 : for (i = 0; i < n_blocks; i++)
779 : : {
780 [ # # ][ # # ]: 0 : if (free_tally[i] != (mem_block->block_size() / objectSize))
781 : : {
782 : 0 : free_tally[i] = 0;
783 : 0 : all_blocks++;
784 : : }
785 : :
786 [ # # ]: 0 : mem_block = mem_block->next_block();
787 : : }
788 : :
789 [ # # ]: 0 : if (all_blocks == n_blocks)
790 : : {
791 : : // no memory can be saved ... all blocks have some used elements
792 : : // return 0
793 : :
794 [ # # ]: 0 : delete [] free_tally;
795 : 0 : return 0;
796 : : }
797 : :
798 : : // adjust free list pointers to remove those that belong to
799 : : // memory blocks that can be deleted
800 : 0 : char* prev_ptr = NULL;
801 : 0 : list_ptr = headOfFreeList;
802 [ # # ]: 0 : while (list_ptr)
803 : : {
804 : : // find memory block that owns this element
805 : : // check last few blocks for speed
806 : 0 : found = CUBIT_FALSE;
807 [ # # ]: 0 : if ( use_cache )
808 : : {
809 [ # # ]: 0 : for ( i = 0; i < cache_size; i++ )
810 : : {
811 : 0 : mem_block = mem_block_sav[i];
812 [ # # ][ # # ]: 0 : if ( mem_block &&
813 [ # # ][ # # ]: 0 : list_ptr >= mem_block->get_block() &&
[ # # ]
814 [ # # ]: 0 : list_ptr < (mem_block->get_block() +
815 [ # # ]: 0 : mem_block->block_size()) )
816 : : {
817 : 0 : k = i_sav[i];
818 : 0 : found = CUBIT_TRUE;
819 : 0 : break;
820 : : }
821 : : }
822 : : }
823 [ # # ]: 0 : if ( !found )
824 : : {
825 : 0 : mem_block = memBlockStack;
826 [ # # ]: 0 : for (i = 0; i < n_blocks; i++)
827 : : {
828 [ # # ][ # # ]: 0 : if ((list_ptr >= mem_block->get_block()) &&
[ # # ][ # # ]
829 [ # # ][ # # ]: 0 : (list_ptr < (mem_block->get_block() + mem_block->block_size())))
830 : : {
831 : 0 : k = i;
832 : : // save
833 [ # # ][ # # ]: 0 : if ( use_cache && mem_block_sav[j] != mem_block )
834 : : {
835 : 0 : mem_block_sav[j] = mem_block;
836 : 0 : i_sav[j] = i;
837 [ # # ]: 0 : if ( ++j >= cache_size )
838 : 0 : j = 0;
839 : : }
840 : 0 : break;
841 : : }
842 : : // get next memory block
843 [ # # ]: 0 : mem_block = mem_block->next_block();
844 : : }
845 : : }
846 : :
847 [ # # ]: 0 : if (free_tally[k])
848 : : {
849 : : // remove element
850 : :
851 [ # # ]: 0 : if (prev_ptr)
852 : : {
853 : 0 : *((char**) prev_ptr) = *((char**) list_ptr);
854 : : }
855 : : else
856 : : {
857 : 0 : headOfFreeList = *((char**) list_ptr);
858 : : }
859 : : }
860 : : else
861 : : {
862 : : // advance prev_ptr
863 : 0 : prev_ptr = list_ptr;
864 : : }
865 : :
866 : : // get next element
867 : 0 : list_ptr = *((char**) list_ptr);
868 : : }
869 : :
870 : : // delete all memory blocks that have free_tally[i] > 0
871 : :
872 : 0 : i = 0;
873 : 0 : int save_bytes = 0;
874 : 0 : MemoryBlock* prev_block = NULL;
875 : 0 : mem_block = memBlockStack;
876 [ # # ]: 0 : while (mem_block)
877 : : {
878 [ # # ]: 0 : if (free_tally[i])
879 : : {
880 : : // set previous MemoryBlocks next pointer to skip this block
881 : :
882 [ # # ]: 0 : if (prev_block)
883 : : {
884 [ # # ][ # # ]: 0 : prev_block->next_block(mem_block->next_block());
885 : : }
886 : : else
887 : : {
888 [ # # ]: 0 : memBlockStack = mem_block->next_block();
889 : : }
890 : :
891 : : // set MemoryBlock next pointer to NULL to avoid recusive delete
892 : : // update saved memory and delete mem_block
893 : :
894 [ # # ]: 0 : mem_block->next_block((MemoryBlock*) NULL);
895 [ # # ]: 0 : save_bytes += mem_block->block_size();
896 [ # # ][ # # ]: 0 : delete mem_block;
897 : :
898 : : // update mem_block to point to new current MemoryBlock
899 : :
900 [ # # ]: 0 : if (prev_block)
901 : : {
902 [ # # ]: 0 : mem_block = prev_block->next_block();
903 : : }
904 : : else
905 : : {
906 : 0 : mem_block = memBlockStack;
907 : : }
908 : : }
909 : : else
910 : : {
911 : : // if block wasn't removed then update previous and current blocks
912 : :
913 : 0 : prev_block = mem_block;
914 [ # # ]: 0 : mem_block = mem_block->next_block();
915 : : }
916 : :
917 : : // increment to next block (used by free_tally array)
918 : :
919 : 0 : ++i;
920 : : }
921 : :
922 : : // return freed memory (bytes)
923 : :
924 [ # # ]: 0 : delete [] free_tally;
925 : 0 : return save_bytes;
926 : : }
927 : : }
928 : : else
929 : : {
930 : : // no memory allocated ... return 0
931 : :
932 : 0 : return 0;
933 : : }
934 : : }
935 : :
936 : :
937 : 0 : void MemoryManager::process_mem_usage(unsigned long &vm_usage, unsigned long &resident_set)
938 : : {
939 : :
940 : : #if defined(CUBIT_LINUX)
941 : : using std::ios_base;
942 : : using std::ifstream;
943 : : using std::string;
944 : :
945 : 0 : vm_usage = 0;
946 : 0 : resident_set = 0;
947 : :
948 : : // 'file' stat seems to give the most reliable results
949 : : //
950 [ # # ]: 0 : ifstream stat_stream("/proc/self/stat",ios_base::in);
951 : :
952 : : // dummy vars for leading entries in stat that we don't care about
953 : : //
954 [ # # ][ # # ]: 0 : string pid, comm, state, ppid, pgrp, session, tty_nr;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
955 [ # # ][ # # ]: 0 : string tpgid, flags, minflt, cminflt, majflt, cmajflt;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
956 [ # # ][ # # ]: 0 : string utime, stime, cutime, cstime, priority, nice;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
957 [ # # ][ # # ]: 0 : string O, itrealvalue, starttime;
[ # # # # ]
[ # # ][ # # ]
958 : :
959 : : // the two fields we want...virtual memory size and resident memory size
960 : : //
961 : : unsigned long vsize;
962 : : long rss;
963 : :
964 [ # # ][ # # ]: 0 : stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
965 [ # # ][ # # ]: 0 : >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
[ # # ][ # # ]
[ # # ][ # # ]
966 [ # # ][ # # ]: 0 : >> utime >> stime >> cutime >> cstime >> priority >> nice
[ # # ][ # # ]
[ # # ][ # # ]
967 [ # # ][ # # ]: 0 : >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
[ # # ][ # # ]
[ # # ]
968 : :
969 : 0 : long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
970 : 0 : vm_usage = vsize / 1024;
971 [ # # ]: 0 : resident_set = rss * page_size_kb;
972 : : #else
973 : : vm_usage = 0;
974 : : resident_set = 0;
975 : : #endif
976 : 0 : }
977 : :
978 : :
979 : 0 : void MemoryManager::process_file_io(unsigned long &read, unsigned long &write )
980 : : {
981 : : #if defined(CUBIT_LINUX)
982 : : using std::ios_base;
983 : : using std::ifstream;
984 : : using std::string;
985 : :
986 : 0 : read = 0;
987 : 0 : write = 0;
988 : :
989 : : // 'file' stat seems to give the most reliable results
990 : : //
991 [ # # ]: 0 : ifstream stat_stream("/proc/self/io",ios_base::in);
992 : :
993 : : // dummy vars for leading entries in stat that we don't care about
994 : : //
995 [ # # ][ # # ]: 0 : string char1, char2;
[ # # ][ # # ]
996 : :
997 : : //----------------------Getting two numbers out of this file
998 : : // I/O counter: chars read
999 : : //The number of bytes which this task has caused to be read from storage. This
1000 : : //is simply the sum of bytes which this process passed to read() and pread().
1001 : : //It includes things like tty IO and it is unaffected by whether or not actual
1002 : : //physical disk IO was required (the read might have been satisfied from
1003 : : //pagecache)
1004 : :
1005 : : // I/O counter: chars written
1006 : : //The number of bytes which this task has caused, or shall cause to be written
1007 : : //to disk. Similar caveats apply here as with rchar.
1008 : :
1009 : : unsigned long tmp_read, tmp_write;
1010 : :
1011 [ # # ][ # # ]: 0 : stat_stream >> char1 >> tmp_read >> char2 >> tmp_write; //don't care about the rest
[ # # ][ # # ]
1012 : :
1013 : 0 : read = tmp_read;
1014 [ # # ]: 0 : write = tmp_write;
1015 : : #else
1016 : : read = 0;
1017 : : write = 0;
1018 : : #endif
1019 [ + - ][ + - ]: 6540 : }
1020 : :
1021 : :
1022 : :
|