00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #if ! CMK_MEMORY_BUILD_OS
00016
00017 #include "memory-gnu.c"
00018 #endif
00019 #include "tracec.h"
00020 #include <sys/mman.h>
00021
00022
00023 #include "ckhashtable.h"
00024
00025
00026
00027 #include "crc32.h"
00028
00029 typedef struct _Slot Slot;
00030 typedef struct _SlotStack SlotStack;
00031
00032 int nextChareID;
00033 extern int memory_chare_id;
00034
00039 struct _Slot {
00040
00041 Slot *next;
00042 Slot *prev;
00043
00044
00045 int userSize;
00046
00047 #define FLAGS_MASK 0xF
00048 #define LEAK_FLAG 0x8
00049 #define UNKNOWN_TYPE 0x0
00050 #define SYSTEM_TYPE 0x1
00051 #define USER_TYPE 0x2
00052 #define CHARE_TYPE 0x3
00053 #define MESSAGE_TYPE 0x4
00054
00055
00056
00057 #define SLOTMAGIC 0x8402a5e0
00058 #define SLOTMAGIC_VALLOC 0x7402a5e0
00059 #define SLOTMAGIC_FREED 0xDEADBEEF
00060 int magic;
00061
00062 int chareID;
00063
00064
00065
00066 int stackLen;
00067 void **from;
00068
00069
00070 SlotStack *extraStack;
00071
00072
00073 unsigned int slotCRC;
00074 unsigned int userCRC;
00075 };
00076
00077 struct _SlotStack {
00078 char *protectedMemory;
00079 int protectedMemoryLength;
00080
00081 };
00082
00083
00084 static char *SlotToUser(Slot *s) {
00085 return ((char *)s)+sizeof(Slot);
00086 }
00087
00088
00089
00090 static Slot *UserToSlot(void *user) {
00091 char *cu=(char *)user;
00092 Slot *s=(Slot *)(cu-sizeof(Slot));
00093 return s;
00094 }
00095
00096 static int isLeakSlot(Slot *s) {
00097 return s->magic & LEAK_FLAG;
00098 }
00099
00100 static void printSlot(Slot *s) {
00101 CmiPrintf("[%d] Leaked block of %d bytes at %p:\n",
00102 CmiMyPe(), s->userSize, SlotToUser(s));
00103 CmiBacktracePrint(s->from,s->stackLen);
00104 }
00105
00106
00107
00108
00109 Slot slot_first_storage = {&slot_first_storage, &slot_first_storage};
00110 Slot *slot_first = &slot_first_storage;
00111
00112 int memory_allocated_user_total;
00113 int get_memory_allocated_user_total() {return memory_allocated_user_total;}
00114
00115
00116
00117 int cpd_memory_length(void *lenParam) {
00118 int n=0;
00119 Slot *cur = slot_first->next;
00120 while (cur != slot_first) {
00121 n++;
00122 cur = cur->next;
00123 }
00124 return n;
00125 }
00126
00127 void cpd_memory_single_pup(Slot* list, pup_er p) {
00128 Slot *cur = list->next;
00129
00130
00131 if (pup_isPacking(p)) cur = cur->next;
00132 while (cur != list) {
00133 int i;
00134 int flags;
00135 void *loc = (void*)(cur+1);
00136 CpdListBeginItem(p, 0);
00137 pup_comment(p, "loc");
00138 pup_pointer(p, &loc);
00139 pup_comment(p, "size");
00140 pup_int(p, &cur->userSize);
00141 pup_comment(p, "flags");
00142 flags = cur->magic & FLAGS_MASK;
00143 pup_int(p, &flags);
00144 pup_comment(p, "chare");
00145 pup_int(p, &cur->chareID);
00146 pup_comment(p, "stack");
00147
00148
00149
00150
00151
00152 pup_pointers(p, cur->from, cur->stackLen);
00153 cur = cur->next;
00154 }
00155 }
00156
00157 void cpd_memory_pup(void *itemParam, pup_er p, CpdListItemsRequest *req) {
00158 CpdListBeginItem(p, 0);
00159 pup_comment(p, "name");
00160 pup_chars(p, "memory", strlen("memory"));
00161 pup_comment(p, "slots");
00162 pup_syncComment(p, pup_sync_begin_array, 0);
00163 cpd_memory_single_pup(slot_first, p);
00164 pup_syncComment(p, pup_sync_end_array, 0);
00165 }
00166
00167 void check_memory_leaks(CpdListItemsRequest *);
00168 void cpd_memory_leak(void *iterParam, pup_er p, CpdListItemsRequest *req) {
00169 if (pup_isSizing(p)) {
00170
00171
00172
00173 check_memory_leaks(req);
00174 }
00175 cpd_memory_pup(iterParam, p, req);
00176 }
00177
00178 int cpd_memory_getLength(void *lenParam) { return 1; }
00179 void cpd_memory_get(void *iterParam, pup_er p, CpdListItemsRequest *req) {
00180 void *userData = (void*)(((unsigned int)req->lo) + (((unsigned long)req->hi)<<32));
00181 Slot *sl = ((Slot*)userData)-1;
00182 CpdListBeginItem(p, 0);
00183 pup_comment(p, "size");
00184
00185 if ((sl->magic&~FLAGS_MASK) != SLOTMAGIC) {
00186 int zero = 0;
00187 pup_int(p, &zero);
00188 } else {
00189 pup_int(p, &sl->userSize);
00190 pup_comment(p, "value");
00191 pup_bytes(p, userData, sl->userSize);
00192 }
00193 }
00194
00195
00196
00197 int charmEnvelopeSize = 0;
00198
00199
00200 void check_memory_leaks(CpdListItemsRequest *req) {
00201 FILE* fd=fopen("check_memory_leaks", "w");
00202
00203
00204 CkHashtable_c table;
00205 Slot leaking, inProgress;
00206 Slot *sl, **fnd, *found;
00207 char *scanner;
00208 char *begin_stack, *end_stack;
00209 char *begin_data, *end_data;
00210 char *begin_bss, *end_bss;
00211 int growing_dimension = 0;
00212
00213
00214 slot_first->next->prev = &leaking;
00215 slot_first->prev->next = &leaking;
00216 leaking.prev = slot_first->prev;
00217 leaking.next = slot_first->next;
00218 slot_first->next = slot_first;
00219 slot_first->prev = slot_first;
00220
00221 table = CkCreateHashtable_pointer(sizeof(char *), 10000);
00222 for (sl = leaking.next; sl != &leaking; sl = sl->next) {
00223
00224 char *ptr;
00225 sl->magic |= LEAK_FLAG;
00226 if (req->lo > 0) {
00227
00228
00229 ptr = ((char*)sl)+sizeof(Slot);
00230 char **object = (char**)CkHashtablePut(table, &ptr);
00231 *object = (char*)sl;
00232 ptr += 4;
00233 object = (char**)CkHashtablePut(table, &ptr);
00234 *object = (char*)sl;
00235
00236 ptr += sizeof(CmiChunkHeader) - 4;
00237 if (ptr < ((char*)sl)+2*sizeof(Slot)+sl->userSize) {
00238 object = (char**)CkHashtablePut(table, &ptr);
00239 *object = (char*)sl;
00240 }
00241
00242 ptr += CmiReservedHeaderSize;
00243 if (ptr < ((char*)sl)+2*sizeof(Slot)+sl->userSize) {
00244 object = (char**)CkHashtablePut(table, &ptr);
00245 *object = (char*)sl;
00246 }
00247
00248 ptr += charmEnvelopeSize - CmiReservedHeaderSize;
00249 if (ptr < ((char*)sl)+2*sizeof(Slot)+sl->userSize) {
00250 object = (char**)CkHashtablePut(table, &ptr);
00251 *object = (char*)sl;
00252 }
00253 } else {
00254
00255
00256 for (ptr = ((char*)sl)+sizeof(Slot); ptr < ((char*)sl)+sizeof(Slot)+sl->userSize; ptr+=sizeof(char*)) {
00257
00258
00259
00260 char **object = (char**)CkHashtablePut(table, &ptr);
00261 *object = (char*)sl;
00262 }
00263 }
00264 }
00265
00266
00267
00268
00269
00270
00271
00272 inProgress.prev = &inProgress;
00273 inProgress.next = &inProgress;
00274 begin_stack = (char*)&table;
00275 end_stack = (char*)memory_stack_top;
00276 if (req->extraLen != 4*4) {
00277 CmiPrintf("requested for a memory leak check with wrong information! %d bytes\n",req->extraLen);
00278 }
00279
00280
00281 begin_data = (char*)ntohl(((int*)(req->extra))[0]);
00282 end_data = (char*)ntohl(((int*)(req->extra))[1]) - sizeof(char*) + 1;
00283 begin_bss = (char*)ntohl(((int*)(req->extra))[2]);
00284 end_bss = (char*)ntohl(((int*)(req->extra))[3]) - sizeof(char*) + 1;
00285
00286
00287
00288
00289
00290
00291
00292 printf("scanning stack from %p (%d) to %p (%d)\n",begin_stack,begin_stack,end_stack,end_stack);
00293 for (scanner = begin_stack; scanner < end_stack; scanner+=sizeof(char*)) {
00294 fnd = (Slot**)CkHashtableGet(table, scanner);
00295
00296 if (fnd != NULL && isLeakSlot(*fnd)) {
00297 found = *fnd;
00298
00299
00300 found->magic &= ~LEAK_FLAG;
00301
00302 found->next->prev = found->prev;
00303 found->prev->next = found->next;
00304 found->next = inProgress.next;
00305 found->prev = &inProgress;
00306 found->next->prev = found;
00307 found->prev->next = found;
00308 }
00309 }
00310 printf("scanning data from %p (%d) to %p (%d)\n",begin_data,begin_data,end_data,end_data);
00311 for (scanner = begin_data; scanner < end_data; scanner+=sizeof(char*)) {
00312
00313 fflush(fd);
00314 fnd = (Slot**)CkHashtableGet(table, scanner);
00315
00316 if (fnd != NULL && isLeakSlot(*fnd)) {
00317 found = *fnd;
00318
00319
00320 found->magic &= ~LEAK_FLAG;
00321
00322 found->next->prev = found->prev;
00323 found->prev->next = found->next;
00324 found->next = inProgress.next;
00325 found->prev = &inProgress;
00326 found->next->prev = found;
00327 found->prev->next = found;
00328 }
00329 }
00330 printf("scanning bss from %p (%d) to %p (%d)\n",begin_bss,begin_bss,end_bss,end_bss);
00331 for (scanner = begin_bss; scanner < end_bss; scanner+=sizeof(char*)) {
00332
00333 fnd = (Slot**)CkHashtableGet(table, scanner);
00334
00335 if (fnd != NULL && isLeakSlot(*fnd)) {
00336 found = *fnd;
00337
00338
00339 found->magic &= ~LEAK_FLAG;
00340
00341 found->next->prev = found->prev;
00342 found->prev->next = found->next;
00343 found->next = inProgress.next;
00344 found->prev = &inProgress;
00345 found->next->prev = found;
00346 found->prev->next = found;
00347 }
00348 }
00349
00350
00351
00352
00353 while (inProgress.next != &inProgress) {
00354 sl = inProgress.next;
00355 printf("scanning memory %p of size %d\n",sl,sl->userSize);
00356
00357 sl->next->prev = sl->prev;
00358 sl->prev->next = sl->next;
00359 sl->next = slot_first->next;
00360 sl->prev = slot_first;
00361 sl->next->prev = sl;
00362 sl->prev->next = sl;
00363
00364
00365 if (sl->extraStack != NULL && sl->extraStack->protectedMemory != NULL) mprotect(sl->extraStack->protectedMemory, sl->extraStack->protectedMemoryLength, PROT_READ);
00366 for (scanner = ((char*)sl)+sizeof(Slot); scanner < ((char*)sl)+sizeof(Slot)+sl->userSize-sizeof(char*)+1; scanner+=sizeof(char*)) {
00367 fnd = (Slot**)CkHashtableGet(table, scanner);
00368
00369 if (fnd != NULL && isLeakSlot(*fnd)) {
00370 found = *fnd;
00371
00372
00373 found->magic &= ~LEAK_FLAG;
00374
00375 found->next->prev = found->prev;
00376 found->prev->next = found->next;
00377 found->next = inProgress.next;
00378 found->prev = &inProgress;
00379 found->next->prev = found;
00380 found->prev->next = found;
00381 }
00382 }
00383 if (sl->extraStack != NULL && sl->extraStack->protectedMemory != NULL) mprotect(sl->extraStack->protectedMemory, sl->extraStack->protectedMemoryLength, PROT_NONE);
00384 }
00385
00386
00387
00388 if (leaking.next != &leaking) {
00389 leaking.next->prev = slot_first;
00390 leaking.prev->next = slot_first->next;
00391 slot_first->next->prev = leaking.prev;
00392 slot_first->next = leaking.next;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 CkDeleteHashtable(table);
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 typedef struct _AllocationPoint AllocationPoint;
00422
00423 struct _AllocationPoint {
00424
00425 void * key;
00426
00427 AllocationPoint * parent;
00428
00429 AllocationPoint * firstChild;
00430
00431 AllocationPoint * sibling;
00432
00433
00434
00435 AllocationPoint * next;
00436
00437 int size;
00438
00439 int count;
00440
00441 char flags;
00442 };
00443
00444
00445 void pupAllocationPointSingle(pup_er p, AllocationPoint *node, int *numChildren) {
00446 pup_pointer(p, &node->key);
00447 pup_int(p, &node->size);
00448 pup_int(p, &node->count);
00449 pup_char(p, &node->flags);
00450 if (pup_isUnpacking(p)) {
00451 node->parent = NULL;
00452 node->firstChild = NULL;
00453 node->sibling = NULL;
00454 node->next = NULL;
00455 }
00456 *numChildren = 0;
00457 AllocationPoint *child;
00458 for (child = node->firstChild; child != NULL; child = child->sibling) (*numChildren) ++;
00459 pup_int(p, numChildren);
00460
00461 }
00462
00463
00464 void pupAllocationPoint(pup_er p, void *data) {
00465 AllocationPoint *node = (AllocationPoint*)data;
00466 int numChildren;
00467 pupAllocationPointSingle(p, node, &numChildren);
00468 AllocationPoint *child;
00469 for (child = node->firstChild; child != NULL; child = child->sibling) {
00470 pupAllocationPoint(p, child);
00471 }
00472 }
00473
00474 void deleteAllocationPoint(void *ptr) {
00475 AllocationPoint *node = (AllocationPoint*)ptr;
00476 AllocationPoint *child;
00477 for (child = node->firstChild; child != NULL; child = child->sibling) deleteAllocationPoint(child);
00478 mm_free(node);
00479 }
00480
00481 void printAllocationTree(AllocationPoint *node, FILE *fd, int depth) {
00482 int i;
00483 if (node==NULL) return;
00484 int numChildren = 0;
00485 AllocationPoint *child;
00486 for (child = node->firstChild; child != NULL; child = child->sibling) numChildren ++;
00487 for (i=0; i<depth; ++i) fprintf(fd, " ");
00488 fprintf(fd, "node %p: bytes=%d, count=%d, child=%d\n",node->key,node->size,node->count,numChildren);
00489 printAllocationTree(node->sibling, fd, depth);
00490 printAllocationTree(node->firstChild, fd, depth+2);
00491 }
00492
00493 AllocationPoint * CreateAllocationTree(int *nodesCount) {
00494 Slot *scanner;
00495 CkHashtable_c table;
00496 int i, isnew;
00497 AllocationPoint *parent, **start, *cur;
00498 AllocationPoint *root = NULL;
00499 int numNodes = 0;
00500
00501 scanner=slot_first->next;
00502 table = CkCreateHashtable_pointer(sizeof(char *), 10000);
00503
00504 root = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00505 *(AllocationPoint**)CkHashtablePut(table, &numNodes) = root;
00506 numNodes ++;
00507 root->key = 0;
00508 root->parent = NULL;
00509 root->size = 0;
00510 root->count = 0;
00511 root->flags = 0;
00512 root->firstChild = NULL;
00513 root->sibling = NULL;
00514 root->next = root;
00515
00516 for ( ; scanner!=slot_first; scanner=scanner->next) {
00517 parent = root;
00518 for (i=scanner->stackLen-1; i>=0; --i) {
00519 isnew = 0;
00520 start = (AllocationPoint**)CkHashtableGet(table, &scanner->from[i]);
00521 if (start == NULL) {
00522 cur = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00523 numNodes ++;
00524 isnew = 1;
00525 cur->next = cur;
00526 *(AllocationPoint**)CkHashtablePut(table, &scanner->from[i]) = cur;
00527 } else {
00528 for (cur = (*start)->next; cur != *start && cur->parent != parent; cur = cur->next);
00529 if (cur->parent != parent) {
00530 cur = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00531 numNodes ++;
00532 isnew = 1;
00533 cur->next = (*start)->next;
00534 (*start)->next = cur;
00535 }
00536 }
00537
00538 if (isnew) {
00539 cur->key = scanner->from[i];
00540 cur->parent = parent;
00541 cur->size = 0;
00542 cur->count = 0;
00543 cur->flags = 0;
00544 cur->firstChild = NULL;
00545
00546
00547
00548
00549
00550 cur->sibling = parent->firstChild;
00551 parent->firstChild = cur;
00552
00553 }
00554 cur->size += scanner->userSize;
00555 cur->count ++;
00556 cur->flags |= isLeakSlot(scanner);
00557 parent = cur;
00558 }
00559 }
00560
00561 char filename[100];
00562 sprintf(filename, "allocationTree_%d", CmiMyPe());
00563 FILE *fd = fopen(filename, "w");
00564 fprintf(fd, "digraph %s {\n", filename);
00565 CkHashtableIterator_c it = CkHashtableGetIterator(table);
00566 AllocationPoint **startscan, *scan;
00567 while ((startscan=(AllocationPoint**)CkHashtableIteratorNext(it,NULL))!=NULL) {
00568 fprintf(fd, "\t\"n%p\" [label=\"%p\\nsize=%d\\ncount=%d\"];\n",*startscan,(*startscan)->key,
00569 (*startscan)->size,(*startscan)->count);
00570 for (scan = (*startscan)->next; scan != *startscan; scan = scan->next) {
00571 fprintf(fd, "\t\"n%p\" [label=\"%p\\nsize=%d\\ncount=%d\"];\n",scan,scan->key,scan->size,scan->count);
00572 }
00573 }
00574 CkHashtableIteratorSeekStart(it);
00575 while ((startscan=(AllocationPoint**)CkHashtableIteratorNext(it,NULL))!=NULL) {
00576 fprintf(fd, "\t\"n%p\" -> \"n%p\";\n",(*startscan)->parent,(*startscan));
00577 for (scan = (*startscan)->next; scan != *startscan; scan = scan->next) {
00578 fprintf(fd, "\t\"n%p\" -> \"n%p\";\n",scan->parent,scan);
00579 }
00580 }
00581 fprintf(fd, "}\n");
00582 fclose(fd);
00583
00584 sprintf(filename, "allocationTree_%d.tree", CmiMyPe());
00585 fd = fopen(filename, "w");
00586 printAllocationTree(root, fd, 0);
00587 fclose(fd);
00588
00589 CkDeleteHashtable(table);
00590 if (nodesCount != NULL) *nodesCount = numNodes;
00591 return root;
00592 }
00593
00594 void MergeAllocationTreeSingle(AllocationPoint *node, AllocationPoint *remote, int numChildren, pup_er p) {
00595 AllocationPoint child;
00596 int numChildChildren;
00597 int i;
00598
00599
00600 node->size += remote->size;
00601 node->count += remote->count;
00602 node->flags |= remote->flags;
00603
00604 for (i=0; i<numChildren; ++i) {
00605 AllocationPoint *localChild;
00606 pupAllocationPointSingle(p, &child, &numChildChildren);
00607
00608 for (localChild = node->firstChild; localChild != NULL; localChild = localChild->sibling) {
00609 if (localChild->key == child.key) {
00610 break;
00611 }
00612 }
00613 if (localChild == NULL) {
00614
00615 localChild = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00616 localChild->key = child.key;
00617 localChild->flags = 0;
00618 localChild->count = 0;
00619 localChild->size = 0;
00620 localChild->firstChild = NULL;
00621 localChild->next = NULL;
00622 localChild->parent = node;
00623 localChild->sibling = node->firstChild;
00624 node->firstChild = localChild;
00625 }
00626 MergeAllocationTreeSingle(localChild, &child, numChildChildren, p);
00627 }
00628 }
00629
00630 void * MergeAllocationTree(void *data, void **remoteData, int numRemote) {
00631 int i;
00632 for (i=0; i<numRemote; ++i) {
00633 pup_er p = pup_new_fromMem(remoteData[i]);
00634 AllocationPoint root;
00635 int numChildren;
00636 pupAllocationPointSingle(p, &root, &numChildren);
00637 MergeAllocationTreeSingle((AllocationPoint*)data, &root, numChildren, p);
00638 }
00639 return data;
00640 }
00641
00642
00643 int checkSlotCRC(void *userPtr) {
00644 Slot *sl = UserToSlot(userPtr);
00645 unsigned int crc = crc32((unsigned char*)sl, sizeof(Slot)-2*sizeof(unsigned int));
00646 crc = crc32_update((unsigned char*)sl->from, sl->stackLen*sizeof(void*), crc);
00647 return sl->slotCRC == crc;
00648 }
00649
00650 int checkUserCRC(void *userPtr) {
00651 Slot *sl = UserToSlot(userPtr);
00652 return sl->userCRC == crc32((unsigned char*)userPtr, sl->userSize);
00653 }
00654
00655 void resetUserCRC(void *userPtr) {
00656 Slot *sl = UserToSlot(userPtr);
00657 sl->userCRC = crc32((unsigned char*)userPtr, sl->userSize);
00658 }
00659
00660 void checkAllCRC(int report) {
00661 Slot *cur;
00662 unsigned int crc1, crc2;
00663
00664 for (cur = slot_first->next; cur != slot_first; cur = cur->next) {
00665 crc1 = crc32((unsigned char*)cur, sizeof(Slot)-2*sizeof(unsigned int));
00666 crc1 = crc32_update((unsigned char*)cur->from, cur->stackLen*sizeof(void*), crc1);
00667 crc2 = crc32((unsigned char*)SlotToUser(cur), cur->userSize);
00668
00669 if (report && cur->slotCRC != crc1) CmiPrintf("Object %d modified slot for %p\n",memory_chare_id,SlotToUser(cur));
00670 cur->slotCRC = crc1;
00671 if (report && cur->userCRC != crc2 && memory_chare_id != cur->chareID)
00672 CmiPrintf("Object %d modified memory of object %d for %p\n",memory_chare_id,cur->chareID,SlotToUser(cur));
00673 cur->userCRC = crc2;
00674 }
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 static int memoryTraceDisabled = 0;
00733 #define MAX_STACK_FRAMES 2048
00734 static int numStackFrames;
00735 static void *stackFrames[MAX_STACK_FRAMES];
00736
00737
00738 static void *setSlot(Slot *s,int userSize) {
00739 char *user=SlotToUser(s);
00740
00741
00742 s->next=slot_first->next;
00743 s->prev=slot_first;
00744 s->next->prev=s;
00745 s->prev->next=s;
00746
00747
00748 s->magic=SLOTMAGIC + (memory_status_info>0? USER_TYPE : SYSTEM_TYPE);
00749
00750 s->chareID = memory_chare_id;
00751 s->userSize=userSize;
00752 s->extraStack=(SlotStack *)0;
00753
00754
00755 s->stackLen=numStackFrames;
00756 s->from=(void**)(user+userSize);
00757 memcpy(s->from, &stackFrames[4], numStackFrames*sizeof(void*));
00758
00759 unsigned int crc = crc32((unsigned char*)s, sizeof(Slot)-2*sizeof(unsigned int));
00760 s->slotCRC = crc32_update((unsigned char*)s->from, numStackFrames*sizeof(void*), crc);
00761 s->userCRC = crc32((unsigned char*)user, userSize);
00762 return (void *)user;
00763 }
00764
00765
00766 static void freeSlot(Slot *s) {
00767
00768 s->next->prev=s->prev;
00769 s->prev->next=s->next;
00770 s->prev=s->next=(Slot *)0;
00771
00772 s->magic=SLOTMAGIC_FREED;
00773 s->userSize=-1;
00774 }
00775
00776 void dumpStackFrames() {
00777 numStackFrames=MAX_STACK_FRAMES;
00778 if (memoryTraceDisabled==0) {
00779 memoryTraceDisabled = 1;
00780 CmiBacktraceRecordHuge(stackFrames,&numStackFrames);
00781 memoryTraceDisabled = 0;
00782 numStackFrames-=4;
00783 if (numStackFrames < 0) numStackFrames = 0;
00784 } else {
00785 numStackFrames=0;
00786 stackFrames[0] = (void*)0;
00787 }
00788 }
00789
00790
00791
00792
00793 static int meta_getpagesize(void) {
00794 static int cache=0;
00795 #if defined(CMK_GETPAGESIZE_AVAILABLE)
00796 if (cache==0) cache=getpagesize();
00797 #else
00798 if (cache==0) cache=8192;
00799 #endif
00800 return cache;
00801 }
00802
00803
00804 static void status(char *msg) {
00805 if (CmiMyPe()==0 && !CmiArgGivingUsage()) {
00806 CmiPrintf("%s",msg);
00807 }
00808 }
00809
00810 extern int getCharmEnvelopeSize();
00811
00812 static void meta_init(char **argv) {
00813 status("Converse -memory mode: charmdebug\n");
00814 char buf[100];
00815 sprintf(buf,"slot size %d\n",sizeof(Slot));
00816 status(buf);
00817 charmEnvelopeSize = getCharmEnvelopeSize();
00818 CpdDebugGetAllocationTree = (void* (*)(int*))CreateAllocationTree;
00819 CpdDebug_pupAllocationPoint = pupAllocationPoint;
00820 CpdDebug_deleteAllocationPoint = deleteAllocationPoint;
00821 CpdDebug_MergeAllocationTree = MergeAllocationTree;
00822 memory_allocated_user_total = 0;
00823 nextChareID = 1;
00824 }
00825
00826 static void *meta_malloc(size_t size) {
00827 dumpStackFrames();
00828 Slot *s=(Slot *)mm_malloc(sizeof(Slot)+size+numStackFrames*sizeof(void*));
00829 char *user = (char*)s;
00830 if (s!=NULL) {
00831 user = (char*)setSlot(s,size);
00832 memory_allocated_user_total += size;
00833 traceMalloc_c(user, size, s->from, s->stackLen);
00834 }
00835 return user;
00836 }
00837
00838 static void meta_free(void *mem) {
00839 Slot *s;
00840 if (mem==NULL) return;
00841 #if CMK_MEMORY_BUILD_OS
00842
00843
00844 s=((Slot *)mem)-1;
00845 if ((s->magic&~FLAGS_MASK) != SLOTMAGIC_VALLOC &&
00846 (s->magic&~FLAGS_MASK) != SLOTMAGIC) {
00847 mm_free(mem);
00848 return;
00849 }
00850 #endif
00851 int memSize = 0;
00852 if (mem!=NULL) memSize = (((Slot*)mem)-1)->userSize;
00853