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 #if ! CMK_CHARMDEBUG
00030 #error "charmdebug is not enabled (e.g. when building with-production)"
00031 static void *meta_malloc(size_t size);
00032 static void *meta_calloc(size_t nelem, size_t size);
00033 static void *meta_realloc(void *oldBuffer, size_t newSize);
00034 static void *meta_memalign(size_t align, size_t size);
00035 static int meta_posix_memalign(void **outptr, size_t align, size_t size);
00036 static void *meta_aligned_alloc(size_t align, size_t size);
00037 static void *meta_valloc(size_t size);
00038 static void *meta_pvalloc(size_t size);
00039 #else
00040
00041 void CmiBacktraceRecordHuge(void **retPtrs,int *nLevels);
00042
00043 typedef struct _Slot Slot;
00044 typedef struct _SlotStack SlotStack;
00045
00046 int nextChareID;
00047 extern int memory_chare_id;
00048
00049 int memory_charmdebug_internal = 0;
00050
00055 struct _Slot {
00056 #ifdef CMK_SEPARATE_SLOT
00057 char *userData;
00058 #else
00059
00060 Slot *next;
00061 Slot *prev;
00062 #endif
00063
00064
00065 int userSize;
00066
00067 #define FLAGS_MASK 0xFF
00068 #define BLOCK_PROTECTED 0x80
00069 #define MODIFIED 0x40
00070 #define NEW_BLOCK 0x20
00071 #define LEAK_CLEAN 0x10
00072 #define LEAK_FLAG 0x8
00073 #define UNKNOWN_TYPE 0x0
00074 #define SYSTEM_TYPE 0x1
00075 #define USER_TYPE 0x2
00076 #define CHARE_TYPE 0x3
00077 #define MESSAGE_TYPE 0x4
00078
00079
00080
00081 #define SLOTMAGIC 0x8402a500
00082 #define SLOTMAGIC_VALLOC 0x7402a500
00083 #define SLOTMAGIC_FREED 0xDEADBEEF
00084 int magic;
00085
00086 int chareID;
00087
00088 int stackLen;
00089 void **from;
00090
00091
00092 SlotStack *extraStack;
00093
00094
00095 CmiUInt8 slotCRC;
00096 CmiUInt8 userCRC;
00097 };
00098
00099 struct _SlotStack {
00100 char *protectedMemory;
00101 int protectedMemoryLength;
00102
00103 };
00104
00105
00106
00107
00108 #ifdef CMK_SEPARATE_SLOT
00109 CkHashtable_c block_slots = NULL;
00110 #else
00111 Slot slot_first_storage = {&slot_first_storage, &slot_first_storage};
00112 Slot *slot_first = &slot_first_storage;
00113 #endif
00114
00115 int memory_allocated_user_total;
00116 int get_memory_allocated_user_total() {return memory_allocated_user_total;}
00117
00118 void *lastMemoryAllocated = NULL;
00119 Slot **allocatedSince = NULL;
00120 int allocatedSinceSize = 0;
00121 int allocatedSinceMaxSize = 0;
00122 int saveAllocationHistory = 0;
00123
00124
00125 static char *SlotToUser(Slot *s) {
00126 #ifdef CMK_SEPARATE_SLOT
00127 return s->userData;
00128 #else
00129 return ((char *)s)+sizeof(Slot);
00130 #endif
00131 }
00132
00133
00134
00135
00136 static Slot *UserToSlot(void *user) {
00137 #ifdef CMK_SEPARATE_SLOT
00138 return (Slot *)CkHashtableGet(block_slots, &user);
00139 #else
00140 char *cu=(char *)user;
00141 Slot *s=(Slot *)(cu-sizeof(Slot));
00142 return s;
00143 #endif
00144 }
00145
00146 static int isLeakSlot(Slot *s) {
00147 return s->magic & LEAK_FLAG;
00148 }
00149
00150 static int isProtected(Slot *s) {
00151 return s->magic & BLOCK_PROTECTED;
00152 }
00153
00154 int Slot_ChareOwner(void *s) {
00155 return ((Slot*)s)->chareID;
00156 }
00157
00158 int Slot_AllocatedSize(void *s) {
00159 return ((Slot*)s)->userSize;
00160 }
00161
00162 int Slot_StackTrace(void *s, void ***stack) {
00163 *stack = ((Slot*)s)->from;
00164 return ((Slot*)s)->stackLen;
00165 }
00166
00167 static void printSlot(Slot *s) {
00168 CmiPrintf("[%d] Leaked block of %d bytes at %p:\n",
00169 CmiMyPe(), s->userSize, (void *)SlotToUser(s));
00170 CmiBacktracePrint(s->from,s->stackLen);
00171 }
00172
00173
00174
00176 size_t cpd_memory_length(void *lenParam) {
00177 size_t n=0;
00178 #ifdef CMK_SEPARATE_SLOT
00179 n = CkHashtableSize(block_slots) - 1;
00180 #else
00181 Slot *cur = slot_first->next;
00182 while (cur != slot_first) {
00183 n++;
00184 cur = cur->next;
00185 }
00186 #endif
00187 return n;
00188 }
00189
00192 #ifdef CMK_SEPARATE_SLOT
00193 void cpd_memory_single_pup(CkHashtable_c h, pup_er p) {
00194 CkHashtableIterator_c hashiter;
00195 void *key;
00196 Slot *cur;
00197
00198
00199 memory_charmdebug_internal = 1;
00200 hashiter = CkHashtableGetIterator(h);
00201 while ((cur = (Slot *)CkHashtableIteratorNext(hashiter, &key)) != NULL) {
00202 if (pup_isPacking(p) && cur->userData == lastMemoryAllocated) continue;
00203
00204 #else
00205 void cpd_memory_single_pup(Slot* list, pup_er p) {
00206 Slot *cur = list->next;
00207
00208
00209 if (pup_isPacking(p)) cur = cur->next;
00210 for ( ; cur != list; cur = cur->next) {
00211 #endif
00212 {
00213 int i;
00214 int flags;
00215 void *loc = SlotToUser(cur);
00216 CpdListBeginItem(p, 0);
00217 pup_comment(p, "loc");
00218 pup_pointer(p, &loc);
00219 pup_comment(p, "size");
00220 pup_int(p, &cur->userSize);
00221 pup_comment(p, "flags");
00222 flags = cur->magic & FLAGS_MASK;
00223 pup_int(p, &flags);
00224 pup_comment(p, "chare");
00225 pup_int(p, &cur->chareID);
00226 pup_comment(p, "stack");
00227
00228
00229
00230
00231
00232 if (cur->from != NULL)
00233 pup_pointers(p, cur->from, cur->stackLen);
00234 else {
00235 void *myNULL = NULL;
00236 printf("Block %p has no stack!\n",(void *)cur);
00237 pup_pointer(p, &myNULL);
00238 }
00239 }
00240 }
00241
00242 memory_charmdebug_internal = 0;
00243 }
00244
00246 void cpd_memory_pup(void *itemParam, pup_er p, CpdListItemsRequest *req) {
00247 static char s_memory[] = "memory";
00248 CpdListBeginItem(p, 0);
00249 pup_comment(p, "name");
00250 pup_chars(p, s_memory, sizeof(s_memory)-1);
00251 pup_comment(p, "slots");
00252 pup_syncComment(p, pup_sync_begin_array, 0);
00253 #ifdef CMK_SEPARATE_SLOT
00254 cpd_memory_single_pup(block_slots, p);
00255 #else
00256 cpd_memory_single_pup(slot_first, p);
00257 #endif
00258 pup_syncComment(p, pup_sync_end_array, 0);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 size_t cpd_memory_getLength(void *lenParam) { return 1; }
00278 void cpd_memory_get(void *iterParam, pup_er p, CpdListItemsRequest *req) {
00279 void *userData = (void*)(uintptr_t)(((uint64_t)req->lo) + (((uint64_t)req->hi)<<32));
00280 Slot *sl = UserToSlot(userData);
00281 CpdListBeginItem(p, 0);
00282 pup_comment(p, "size");
00283
00284 if ((sl->magic&~FLAGS_MASK) != SLOTMAGIC) {
00285 int zero = 0;
00286 pup_int(p, &zero);
00287 } else {
00288 pup_int(p, &sl->userSize);
00289 pup_comment(p, "value");
00290 pup_bytes(p, userData, sl->userSize);
00291 }
00292 }
00293
00294
00295
00296 int charmEnvelopeSize = 0;
00297
00298 #include "pcqueue.h"
00299
00300 #ifdef CMK_SEPARATE_SLOT
00301 #define SLOTSPACE 0
00302 #define SLOT_ITERATE_START(scanner) \
00303 { \
00304 CkHashtableIterator_c hashiter = CkHashtableGetIterator(block_slots); \
00305 void *key; \
00306 while ((scanner = (Slot *)CkHashtableIteratorNext(hashiter, &key)) != NULL) {
00307 #define SLOT_ITERATE_END \
00308 } \
00309 CkHashtableDestroyIterator(hashiter); \
00310 }
00311 #else
00312 #define SLOTSPACE sizeof(Slot)
00313 #define SLOT_ITERATE_START(scanner) \
00314 for (scanner=slot_first->next; scanner!=slot_first; scanner=scanner->next) {
00315 #define SLOT_ITERATE_END }
00316 #endif
00317
00320
00321 void check_memory_leaks(LeakSearchInfo *info) {
00322
00323
00324
00325 CkHashtable_c table;
00326 PCQueue inProgress;
00327 Slot *sl, **fnd, *found;
00328 char *scanner;
00329 char *begin_stack, *end_stack;
00330
00331
00332 int growing_dimension = 0;
00333
00334
00335
00336 Slot *slold1=0, *slold2=0, *slold3=0;
00337
00338 memory_charmdebug_internal = 1;
00339
00340 inProgress = PCQueueCreate();
00341 table = CkCreateHashtable_pointer(sizeof(char *), 10000);
00342 SLOT_ITERATE_START(sl)
00343
00344
00345 char *ptr;
00346 sl->magic |= LEAK_FLAG;
00347 if (info->quick > 0) {
00348 char **object;
00349
00350
00351 ptr = SlotToUser(sl);
00352 object = (char**)CkHashtablePut(table, &ptr);
00353 *object = (char*)sl;
00354 ptr += 4;
00355 object = (char**)CkHashtablePut(table, &ptr);
00356 *object = (char*)sl;
00357
00358 ptr += sizeof(CmiChunkHeader) - 4;
00359 if (ptr < SlotToUser(sl)+sizeof(Slot)+sl->userSize) {
00360 object = (char**)CkHashtablePut(table, &ptr);
00361 *object = (char*)sl;
00362 }
00363
00364 ptr += CmiReservedHeaderSize;
00365 if (ptr < SlotToUser(sl)+sizeof(Slot)+sl->userSize) {
00366 object = (char**)CkHashtablePut(table, &ptr);
00367 *object = (char*)sl;
00368 }
00369
00370 ptr += charmEnvelopeSize - CmiReservedHeaderSize;
00371 if (ptr < SlotToUser(sl)+sizeof(Slot)+sl->userSize) {
00372 object = (char**)CkHashtablePut(table, &ptr);
00373 *object = (char*)sl;
00374 }
00375 } else {
00376
00377
00378 for (ptr = SlotToUser(sl); ptr <= SlotToUser(sl)+sl->userSize; ptr+=sizeof(char*)) {
00379
00380
00381
00382 char **object = (char**)CkHashtablePut(table, &ptr);
00383 *object = (char*)sl;
00384 }
00385 }
00386 slold3 = slold2;
00387 slold2 = slold1;
00388 slold1 = sl;
00389 SLOT_ITERATE_END
00390
00391
00392
00393
00394
00395
00396
00397 begin_stack = (char*)&table;
00398 end_stack = (char*)memory_stack_top;
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 printf("scanning stack from %p to %p\n", (void *)begin_stack, (void *)end_stack);
00416 for (scanner = begin_stack; scanner < end_stack; scanner+=sizeof(char*)) {
00417 fnd = (Slot**)CkHashtableGet(table, scanner);
00418
00419 if (fnd != NULL && isLeakSlot(*fnd)) {
00420 found = *fnd;
00421
00422
00423 found->magic &= ~LEAK_FLAG;
00424
00425 PCQueuePush(inProgress, (char*)found);
00426 }
00427 }
00428 printf("scanning data from %p to %p\n", (void *)info->begin_data, (void *)info->end_data);
00429 for (scanner = info->begin_data; scanner < info->end_data; scanner+=sizeof(char*)) {
00430
00431
00432 fnd = (Slot**)CkHashtableGet(table, scanner);
00433
00434 if (fnd != NULL && isLeakSlot(*fnd)) {
00435 found = *fnd;
00436
00437
00438 found->magic &= ~LEAK_FLAG;
00439
00440 PCQueuePush(inProgress, (char*)found);
00441 }
00442 }
00443 printf("scanning bss from %p to %p\n", (void *)info->begin_bss, (void *)info->end_bss);
00444 for (scanner = info->begin_bss; scanner < info->end_bss; scanner+=sizeof(char*)) {
00445
00446 fnd = (Slot**)CkHashtableGet(table, scanner);
00447
00448 if (fnd != NULL && isLeakSlot(*fnd)) {
00449 found = *fnd;
00450
00451
00452 found->magic &= ~LEAK_FLAG;
00453
00454 PCQueuePush(inProgress, (char*)found);
00455 }
00456 }
00457
00458
00459
00460
00461 while ((sl = (Slot *)PCQueuePop(inProgress)) != NULL) {
00462
00463
00464
00465 if (sl->extraStack != NULL && sl->extraStack->protectedMemory != NULL) mprotect(sl->extraStack->protectedMemory, sl->extraStack->protectedMemoryLength, PROT_READ);
00466 for (scanner = SlotToUser(sl); scanner < SlotToUser(sl)+sl->userSize-sizeof(char*)+1; scanner+=sizeof(char*)) {
00467 fnd = (Slot**)CkHashtableGet(table, scanner);
00468
00469 if (fnd != NULL && isLeakSlot(*fnd)) {
00470 found = *fnd;
00471
00472
00473 found->magic &= ~LEAK_FLAG;
00474
00475 PCQueuePush(inProgress, (char*)found);
00476 }
00477 }
00478 if (sl->extraStack != NULL && sl->extraStack->protectedMemory != NULL) mprotect(sl->extraStack->protectedMemory, sl->extraStack->protectedMemoryLength, PROT_NONE);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 PCQueueDestroy(inProgress);
00506 CkDeleteHashtable(table);
00507
00508 memory_charmdebug_internal = 0;
00509 }
00510
00511 void CpdMemoryMarkClean(char *msg) {
00512 Slot *sl;
00513
00514 if ((msg+CmiMsgHeaderSizeBytes)[0]) {
00515 SLOT_ITERATE_START(sl)
00516 sl->magic |= LEAK_CLEAN;
00517 SLOT_ITERATE_END
00518 } else {
00519 SLOT_ITERATE_START(sl)
00520 sl->magic &= ~LEAK_CLEAN;
00521 SLOT_ITERATE_END
00522 }
00523 CmiFree(msg);
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 typedef struct _AllocationPoint AllocationPoint;
00535
00536 struct _AllocationPoint {
00537
00538 void * key;
00539
00540 AllocationPoint * parent;
00541
00542 AllocationPoint * firstChild;
00543
00544 AllocationPoint * sibling;
00545
00546
00547
00548 AllocationPoint * next;
00549
00550 int size;
00551
00552 int count;
00553
00554 char flags;
00555 };
00556
00557
00558 void pupAllocationPointSingle(pup_er p, AllocationPoint *node, int *numChildren) {
00559 AllocationPoint *child;
00560 pup_pointer(p, &node->key);
00561 pup_int(p, &node->size);
00562 pup_int(p, &node->count);
00563 pup_char(p, &node->flags);
00564 if (pup_isUnpacking(p)) {
00565 node->parent = NULL;
00566 node->firstChild = NULL;
00567 node->sibling = NULL;
00568 node->next = NULL;
00569 }
00570 *numChildren = 0;
00571 for (child = node->firstChild; child != NULL; child = child->sibling) (*numChildren) ++;
00572 pup_int(p, numChildren);
00573
00574 }
00575
00576
00577 void pupAllocationPoint(pup_er p, void *data) {
00578 AllocationPoint *node = (AllocationPoint*)data;
00579 int numChildren;
00580 AllocationPoint *child;
00581 pupAllocationPointSingle(p, node, &numChildren);
00582 for (child = node->firstChild; child != NULL; child = child->sibling) {
00583 pupAllocationPoint(p, child);
00584 }
00585 }
00586
00587 void deleteAllocationPoint(void *ptr) {
00588 AllocationPoint *node = (AllocationPoint*)ptr;
00589 AllocationPoint *child;
00590 for (child = node->firstChild; child != NULL; child = child->sibling) deleteAllocationPoint(child);
00591 BEFORE_MALLOC_CALL;
00592 mm_free(node);
00593 AFTER_MALLOC_CALL;
00594 }
00595
00596 void printAllocationTree(AllocationPoint *node, FILE *fd, int depth) {
00597 int i;
00598 int numChildren = 0;
00599 AllocationPoint *child;
00600
00601 if (node==NULL) return;
00602 for (child = node->firstChild; child != NULL; child = child->sibling) numChildren ++;
00603 for (i=0; i<depth; ++i) fprintf(fd, " ");
00604 fprintf(fd, "node %p: bytes=%d, count=%d, child=%d\n",(void *)node->key,node->size,node->count,numChildren);
00605 printAllocationTree(node->sibling, fd, depth);
00606 printAllocationTree(node->firstChild, fd, depth+2);
00607 }
00608
00609 AllocationPoint * CreateAllocationTree(int *nodesCount) {
00610 Slot *scanner;
00611 CkHashtable_c table;
00612 int i, isnew;
00613 AllocationPoint *parent, **start, *cur;
00614 AllocationPoint *root = NULL;
00615 int numNodes = 0;
00616 char filename[100];
00617 FILE *fd;
00618 CkHashtableIterator_c it;
00619 AllocationPoint **startscan, *scan;
00620
00621 table = CkCreateHashtable_pointer(sizeof(char *), 10000);
00622
00623 BEFORE_MALLOC_CALL;
00624 root = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00625 AFTER_MALLOC_CALL;
00626 *(AllocationPoint**)CkHashtablePut(table, &numNodes) = root;
00627 numNodes ++;
00628 root->key = 0;
00629 root->parent = NULL;
00630 root->size = 0;
00631 root->count = 0;
00632 root->flags = 0;
00633 root->firstChild = NULL;
00634 root->sibling = NULL;
00635 root->next = root;
00636
00637 SLOT_ITERATE_START(scanner)
00638 parent = root;
00639 for (i=scanner->stackLen-1; i>=0; --i) {
00640 isnew = 0;
00641 start = (AllocationPoint**)CkHashtableGet(table, &scanner->from[i]);
00642 if (start == NULL) {
00643 BEFORE_MALLOC_CALL;
00644 cur = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00645 AFTER_MALLOC_CALL;
00646 numNodes ++;
00647 isnew = 1;
00648 cur->next = cur;
00649 *(AllocationPoint**)CkHashtablePut(table, &scanner->from[i]) = cur;
00650 } else {
00651 for (cur = (*start)->next; cur != *start && cur->parent != parent; cur = cur->next);
00652 if (cur->parent != parent) {
00653 BEFORE_MALLOC_CALL;
00654 cur = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00655 AFTER_MALLOC_CALL;
00656 numNodes ++;
00657 isnew = 1;
00658 cur->next = (*start)->next;
00659 (*start)->next = cur;
00660 }
00661 }
00662
00663 if (isnew) {
00664 cur->key = scanner->from[i];
00665 cur->parent = parent;
00666 cur->size = 0;
00667 cur->count = 0;
00668 cur->flags = 0;
00669 cur->firstChild = NULL;
00670
00671
00672
00673
00674
00675 cur->sibling = parent->firstChild;
00676 parent->firstChild = cur;
00677
00678 }
00679 cur->size += scanner->userSize;
00680 cur->count ++;
00681 cur->flags |= isLeakSlot(scanner);
00682 parent = cur;
00683 }
00684 SLOT_ITERATE_END
00685
00686 sprintf(filename, "allocationTree_%d", CmiMyPe());
00687 fd = fopen(filename, "w");
00688 fprintf(fd, "digraph %s {\n", filename);
00689 it = CkHashtableGetIterator(table);
00690 while ((startscan=(AllocationPoint**)CkHashtableIteratorNext(it,NULL))!=NULL) {
00691 fprintf(fd, "\t\"n%p\" [label=\"%p\\nsize=%d\\ncount=%d\"];\n",(void *)*startscan,(void *)(*startscan)->key,
00692 (*startscan)->size,(*startscan)->count);
00693 for (scan = (*startscan)->next; scan != *startscan; scan = scan->next) {
00694 fprintf(fd, "\t\"n%p\" [label=\"%p\\nsize=%d\\ncount=%d\"];\n",(void *)scan,(void *)scan->key,scan->size,scan->count);
00695 }
00696 }
00697 CkHashtableIteratorSeekStart(it);
00698 while ((startscan=(AllocationPoint**)CkHashtableIteratorNext(it,NULL))!=NULL) {
00699 fprintf(fd, "\t\"n%p\" -> \"n%p\";\n",(void *)(*startscan)->parent,(void *)(*startscan));
00700 for (scan = (*startscan)->next; scan != *startscan; scan = scan->next) {
00701 fprintf(fd, "\t\"n%p\" -> \"n%p\";\n",(void *)scan->parent,(void *)scan);
00702 }
00703 }
00704 fprintf(fd, "}\n");
00705 fclose(fd);
00706
00707 sprintf(filename, "allocationTree_%d.tree", CmiMyPe());
00708 fd = fopen(filename, "w");
00709 printAllocationTree(root, fd, 0);
00710 fclose(fd);
00711
00712 CkDeleteHashtable(table);
00713 if (nodesCount != NULL) *nodesCount = numNodes;
00714 return root;
00715 }
00716
00717 void MergeAllocationTreeSingle(AllocationPoint *node, AllocationPoint *remote, int numChildren, pup_er p) {
00718 AllocationPoint child;
00719 int numChildChildren;
00720 int i;
00721
00722
00723 node->size += remote->size;
00724 node->count += remote->count;
00725 node->flags |= remote->flags;
00726
00727 for (i=0; i<numChildren; ++i) {
00728 AllocationPoint *localChild;
00729 pupAllocationPointSingle(p, &child, &numChildChildren);
00730
00731 for (localChild = node->firstChild; localChild != NULL; localChild = localChild->sibling) {
00732 if (localChild->key == child.key) {
00733 break;
00734 }
00735 }
00736 if (localChild == NULL) {
00737
00738 BEFORE_MALLOC_CALL;
00739 localChild = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
00740 AFTER_MALLOC_CALL;
00741 localChild->key = child.key;
00742 localChild->flags = 0;
00743 localChild->count = 0;
00744 localChild->size = 0;
00745 localChild->firstChild = NULL;
00746 localChild->next = NULL;
00747 localChild->parent = node;
00748 localChild->sibling = node->firstChild;
00749 node->firstChild = localChild;
00750 }
00751 MergeAllocationTreeSingle(localChild, &child, numChildChildren, p);
00752 }
00753 }
00754
00755 void * MergeAllocationTree(int *size, void *data, void **remoteData, int numRemote) {
00756 int i;
00757 for (i=0; i<numRemote; ++i) {
00758 pup_er p = pup_new_fromMem(remoteData[i]);
00759 AllocationPoint root;
00760 int numChildren;
00761 pupAllocationPointSingle(p, &root, &numChildren);
00762 MergeAllocationTreeSingle((AllocationPoint*)data, &root, numChildren, p);
00763 pup_destroy(p);
00764 }
00765 return data;
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775 typedef struct MemStatSingle {
00776
00777 int pe;
00778 int sizes[2][5];
00779 int counts[2][5];
00780 } MemStatSingle;
00781
00782 typedef struct MemStat {
00783 int count;
00784 MemStatSingle array[1];
00785 } MemStat;
00786
00787 void pupMemStat(pup_er p, void *st) {
00788 int i;
00789 MemStat *comb = (MemStat*)st;
00790 pup_fmt_sync_begin_object(p);
00791 pup_comment(p, "count");
00792 pup_int(p, &comb->count);
00793 pup_comment(p, "list");
00794 pup_fmt_sync_begin_array(p);
00795 for (i=0; i<comb->count; ++i) {
00796 MemStatSingle *stat = &comb->array[i];
00797 pup_fmt_sync_item(p);
00798 pup_comment(p, "pe");
00799 pup_int(p, &stat->pe);
00800 pup_comment(p, "totalsize");
00801 pup_ints(p, stat->sizes[0], 5);
00802 pup_comment(p, "totalcount");
00803 pup_ints(p, stat->counts[0], 5);
00804 pup_comment(p, "leaksize");
00805 pup_ints(p, stat->sizes[1], 5);
00806 pup_comment(p, "leakcount");
00807 pup_ints(p, stat->counts[1], 5);
00808 }
00809 pup_fmt_sync_end_array(p);
00810 pup_fmt_sync_end_object(p);
00811 }
00812
00813 void deleteMemStat(void *ptr) {
00814 BEFORE_MALLOC_CALL;
00815 mm_free(ptr);
00816 AFTER_MALLOC_CALL;
00817 }
00818
00819 static int memStatReturnOnlyOne = 1;
00820 void * mergeMemStat(int *size, void *data, void **remoteData, int numRemote) {
00821 int i,j,k;
00822 if (memStatReturnOnlyOne) {
00823 MemStatSingle *l = &((MemStat*) data)->array[0];
00824 MemStat r;
00825 MemStatSingle *m = &r.array[0];
00826 l->pe = -1;
00827 for (i=0; i<numRemote; ++i) {
00828 pup_er p = pup_new_fromMem(remoteData[i]);
00829 pupMemStat(p, &r);
00830 for (j=0; j<2; ++j) {
00831 for (k=0; k<5; ++k) {
00832 l->sizes[j][k] += m->sizes[j][k];
00833 l->counts[j][k] += m->counts[j][k];
00834 }
00835 }
00836 pup_destroy(p);
00837 }
00838 return data;
00839 } else {
00840 MemStat *l = (MemStat*)data, *res;
00841 MemStat r;
00842 int count = l->count;
00843 for (i=0; i<numRemote; ++i) count += ((MemStat*)remoteData[i])->count;
00844 BEFORE_MALLOC_CALL;
00845 res = (MemStat*)mm_malloc(sizeof(MemStat) + (count-1)*sizeof(MemStatSingle));
00846 AFTER_MALLOC_CALL;
00847 memset(res, 0, sizeof(MemStat)+(count-1)*sizeof(MemStatSingle));
00848 res->count = count;
00849 memcpy(res->array, l->array, l->count*sizeof(MemStatSingle));
00850 count = l->count;
00851 for (i=0; i<numRemote; ++i) {
00852 pup_er p = pup_new_fromMem(remoteData[i]);
00853 pupMemStat(p, &r);
00854 memcpy(&res->array[count], r.array, r.count*sizeof(MemStatSingle));
00855 count += r.count;
00856 pup_destroy(p);
00857 }
00858 deleteMemStat(data);
00859 return res;
00860 }
00861 }
00862
00863 MemStat * CreateMemStat(void) {
00864 Slot *cur;
00865 MemStat *st;
00866 MemStatSingle *stat;
00867 BEFORE_MALLOC_CALL;
00868 st = (MemStat*)mm_calloc(1, sizeof(MemStat));
00869 AFTER_MALLOC_CALL;
00870 st->count = 1;
00871 stat = &st->array[0];
00872 SLOT_ITERATE_START(cur)
00873 stat->sizes[0][(cur->magic&0x7)] += cur->userSize;
00874 stat->counts[0][(cur->magic&0x7)] ++;
00875 if (cur->magic & 0x8) {
00876 stat->sizes[1][(cur->magic&0x7)] += cur->userSize;
00877 stat->counts[1][(cur->magic&0x7)] ++;
00878 }
00879 SLOT_ITERATE_END
00880 stat->pe=CmiMyPe();
00881 return st;
00882 }
00883
00884
00885
00886 static int reportMEM = 0;
00887
00888
00889
00890
00891
00892
00893
00894 static int CpdCRC32 = 0;
00895
00896 #define SLOT_CRC_LENGTH (sizeof(Slot) - 2*sizeof(CmiUInt8))
00897
00898 static int checkSlotCRC(void *userPtr) {
00899 Slot *sl = UserToSlot(userPtr);
00900 if (sl!=NULL) {
00901 unsigned int crc = crc32_initial((unsigned char*)sl, SLOT_CRC_LENGTH);
00902 crc = crc32_update((unsigned char*)sl->from, sl->stackLen*sizeof(void*), crc);
00903 return sl->slotCRC == crc;
00904 } else return 0;
00905 }
00906
00907 static int checkUserCRC(void *userPtr) {
00908 Slot *sl = UserToSlot(userPtr);
00909 if (sl!=NULL) return sl->userCRC == crc32_initial((unsigned char*)userPtr, sl->userSize);
00910 else return 0;
00911 }
00912
00913 static void resetUserCRC(void *userPtr) {
00914 Slot *sl = UserToSlot(userPtr);
00915 if (sl!=NULL) sl->userCRC = crc32_initial((unsigned char*)userPtr, sl->userSize);
00916 }
00917
00918 static void resetSlotCRC(void *userPtr) {
00919 Slot *sl = UserToSlot(userPtr);
00920 if (sl!=NULL) {
00921 unsigned int crc = crc32_initial((unsigned char*)sl, SLOT_CRC_LENGTH);
00922 crc = crc32_update((unsigned char*)sl->from, sl->stackLen*sizeof(void*), crc);
00923 sl->slotCRC = crc;
00924 }
00925 }
00926
00927 static void ResetAllCRC(void) {
00928 Slot *cur;
00929 unsigned int crc1, crc2;
00930
00931 SLOT_ITERATE_START(cur)
00932 crc1 = crc32_initial((unsigned char*)cur, SLOT_CRC_LENGTH);
00933 crc1 = crc32_update((unsigned char*)cur->from, cur->stackLen*sizeof(void*), crc1);
00934 crc2 = crc32_initial((unsigned char*)SlotToUser(cur), cur->userSize);
00935 cur->slotCRC = crc1;
00936 cur->userCRC = crc2;
00937 SLOT_ITERATE_END
00938 }
00939
00940 static void CheckAllCRC(void) {
00941 Slot *cur;
00942 unsigned int crc1, crc2;
00943
00944 SLOT_ITERATE_START(cur)
00945 crc1 = crc32_initial((unsigned char*)cur, SLOT_CRC_LENGTH);
00946 crc1 = crc32_update((unsigned char*)cur->from, cur->stackLen*sizeof(void*), crc1);
00947 crc2 = crc32_initial((unsigned char*)SlotToUser(cur), cur->userSize);
00948
00949 if (reportMEM && cur->slotCRC != crc1) CmiPrintf("CRC: Object %d modified slot for %p\n",memory_chare_id,(void *)SlotToUser(cur));
00950 cur->slotCRC = crc1;
00951 if (reportMEM && cur->userCRC != crc2 && memory_chare_id != cur->chareID)
00952 CmiPrintf("CRC: Object %d modified memory of object %d for %p\n",memory_chare_id,cur->chareID,(void *)SlotToUser(cur));
00953 cur->userCRC = crc2;
00954 SLOT_ITERATE_END
00955 }
00956
00957
00958
00959
00960
00961
00962 static int CpdMemBackup = 0;
00963
00964 static void backupMemory(void) {
00965 Slot *cur;
00966 char * ptr;
00967 int totalMemory = SLOTSPACE;
00968 if (*memoryBackup != NULL)
00969 CmiAbort("memoryBackup != NULL\n");
00970
00971 {
00972 SLOT_ITERATE_START(cur)
00973 totalMemory += sizeof(Slot) + cur->userSize + cur->stackLen*sizeof(void*);
00974 SLOT_ITERATE_END
00975 }
00976 if (reportMEM) CmiPrintf("CPD: total memory in use (%d): %d\n",CmiMyPe(),totalMemory);
00977 BEFORE_MALLOC_CALL;
00978 *memoryBackup = (char *)mm_malloc(totalMemory);
00979 AFTER_MALLOC_CALL;
00980
00981 ptr = *memoryBackup;
00982 #ifndef CMK_SEPARATE_SLOT
00983 memcpy(*memoryBackup, slot_first, sizeof(Slot));
00984 ptr += sizeof(Slot);
00985 #endif
00986 SLOT_ITERATE_START(cur)
00987 int tocopy = SLOTSPACE + cur->userSize + cur->stackLen*sizeof(void*);
00988 char *data = (char *)cur;
00989 #ifdef CMK_SEPARATE_SLOT
00990 memcpy(ptr, cur, sizeof(Slot));
00991 ptr += sizeof(Slot);
00992 data = SlotToUser(cur);
00993 #endif
00994 memcpy(ptr, data, tocopy);
00995 cur->magic &= ~ (NEW_BLOCK | MODIFIED);
00996 ptr += tocopy;
00997 SLOT_ITERATE_END
00998 allocatedSinceSize = 0;
00999 }
01000
01001 static void checkBackup(void) {
01002 #ifndef CMK_SEPARATE_SLOT
01003 Slot *cur = slot_first->next;
01004 char *ptr = *memoryBackup + sizeof(Slot);
01005
01006
01007
01008 int idx = allocatedSinceSize-1;
01009 while (idx >= 0) {
01010 while (idx >= 0 && allocatedSince[idx] != cur) idx--;
01011 if (idx >= 0) {
01012 cur = cur->next;
01013 idx --;
01014 }
01015 }
01016
01017 while (cur != slot_first) {
01018 char *last;
01019
01020 if (memory_chare_id != cur->chareID) {
01021 int res = memcmp(ptr+sizeof(Slot), ((char*)cur)+sizeof(Slot), cur->userSize + cur->stackLen*sizeof(void*));
01022 if (res != 0) {
01023 cur->magic |= MODIFIED;
01024 if (reportMEM) CmiPrintf("CPD: Object %d modified memory of object %d for %p on pe %d\n",memory_chare_id,cur->chareID,(void *)(cur+1),CmiMyPe());
01025 }
01026 }
01027
01028
01029 cur = cur->next;
01030 do {
01031 last = ptr;
01032 ptr += sizeof(Slot) + ((Slot*)ptr)->userSize + ((Slot*)ptr)->stackLen*sizeof(void*);
01033 } while (((Slot*)last)->next != cur);
01034 }
01035 #endif
01036
01037 BEFORE_MALLOC_CALL;
01038 mm_free(*memoryBackup);
01039 AFTER_MALLOC_CALL;
01040 *memoryBackup = NULL;
01041 }
01042
01043
01044
01045
01046
01047
01048
01049 #include <signal.h>
01050
01051 static int CpdMprotect = 0;
01052
01053 static void** unProtectedPages = NULL;
01054 static int unProtectedPagesSize = 0;
01055 static int unProtectedPagesMaxSize = 0;
01056
01057 static void* lastAddressSegv;
01058 static void CpdMMAPhandler(int sig, siginfo_t *si, void *unused){
01059 void *pageToUnprotect;
01060 if (lastAddressSegv == si->si_addr) {
01061 CmiPrintf("Second SIGSEGV at address 0x%lx\n", (long) si->si_addr);
01062 CpdFreeze();
01063 }
01064 lastAddressSegv = si->si_addr;
01065 pageToUnprotect = (void*)(uintptr_t)((CmiUInt8)(uintptr_t)si->si_addr & ~(CmiGetPageSize()-1));
01066 mprotect(pageToUnprotect, 4, PROT_READ|PROT_WRITE);
01067 if (unProtectedPagesSize >= unProtectedPagesMaxSize) {
01068 void **newUnProtectedPages;
01069 unProtectedPagesMaxSize += 10;
01070 BEFORE_MALLOC_CALL;
01071 newUnProtectedPages = (void**)mm_malloc((unProtectedPagesMaxSize)*sizeof(void*));
01072 memcpy(newUnProtectedPages, unProtectedPages, unProtectedPagesSize*sizeof(void*));
01073 mm_free(unProtectedPages);
01074 AFTER_MALLOC_CALL;
01075 unProtectedPages = newUnProtectedPages;
01076 }
01077 unProtectedPages[unProtectedPagesSize++] = pageToUnprotect;
01078 if (reportMEM) CpdNotify(CPD_CROSSCORRUPTION, si->si_addr, memory_chare_id);
01079
01080
01081 }
01082
01083 static void protectMemory(void) {
01084 #ifdef CPD_USE_MMAP
01085 Slot *cur;
01086
01087 SLOT_ITERATE_START(cur)
01088 if (cur->chareID != memory_chare_id && cur->chareID > 0) {
01089
01090 #ifdef CMK_SEPARATE_SLOT
01091 char * data = cur->userData;
01092 #else
01093 char * data = (char *)cur;
01094 #endif
01095 cur->magic |= BLOCK_PROTECTED;
01096 mprotect(data, cur->userSize+SLOTSPACE+cur->stackLen*sizeof(void*), PROT_READ);
01097 }
01098 SLOT_ITERATE_END
01099
01100 #endif
01101 }
01102
01103 static void unProtectMemory(void) {
01104 #ifdef CPD_USE_MMAP
01105 Slot *cur;
01106 SLOT_ITERATE_START(cur)
01107 #ifdef CMK_SEPARATE_SLOT
01108 char * data = cur->userData;
01109 #else
01110 char * data = (char *)cur;
01111 #endif
01112 mprotect(data, cur->userSize+SLOTSPACE+cur->stackLen*sizeof(void*), PROT_READ|PROT_WRITE);
01113 cur->magic &= ~BLOCK_PROTECTED;
01114 SLOT_ITERATE_END
01115
01116 #endif
01117 }
01118
01122 void CpdResetMemory(void) {
01123 if (CpdMemBackup) backupMemory();
01124 if (CpdCRC32) ResetAllCRC();
01125 if (CpdMprotect) protectMemory();
01126 }
01127
01131 void CpdCheckMemory(void) {
01132 Slot *cur;
01133 if (CpdMprotect) unProtectMemory();
01134 if (CpdCRC32) CheckAllCRC();
01135 if (CpdMemBackup) checkBackup();
01136 SLOT_ITERATE_START(cur)
01137 if (cur->magic == SLOTMAGIC_FREED) CmiAbort("SLOT deallocate in list");
01138 if (cur->from == NULL) printf("SLOT %p has no stack\n",(void *)cur);
01139 #ifndef CMK_SEPARATE_SLOT
01140 if (cur->next == NULL) printf("SLOT %p has null next!\n",(void *)cur);
01141 #endif
01142 SLOT_ITERATE_END
01143 }
01144
01145 void CpdSystemEnter(void) {
01146 #ifdef CPD_USE_MMAP
01147 Slot *cur;
01148 if (++cpdInSystem == 1) {
01149 if (CpdMprotect) {
01150 int count=0;
01151 SLOT_ITERATE_START(cur)
01152 if (cur->chareID == 0) {
01153 #ifdef CMK_SEPARATE_SLOT
01154 char * data = cur->userData;
01155 #else
01156 char * data = (char *)cur;
01157 #endif
01158 mprotect(data, cur->userSize+SLOTSPACE+cur->stackLen*sizeof(void*), PROT_READ|PROT_WRITE);
01159 cur->magic &= ~BLOCK_PROTECTED;
01160 count++;
01161 }
01162 SLOT_ITERATE_END
01163
01164 }
01165 }
01166 #endif
01167 }
01168
01169 void CpdSystemExit(void) {
01170 #ifdef CPD_USE_MMAP
01171 Slot *cur;
01172 int i;
01173 if (--cpdInSystem == 0) {
01174 if (CpdMprotect) {
01175 int count=0;
01176 SLOT_ITERATE_START(cur)
01177 if (cur->chareID == 0) {
01178 #ifdef CMK_SEPARATE_SLOT
01179 char * data = cur->userData;
01180 #else
01181 char * data = (char *)cur;
01182 #endif
01183 cur->magic |= BLOCK_PROTECTED;
01184 mprotect(data, cur->userSize+SLOTSPACE+cur->stackLen*sizeof(void*), PROT_READ);
01185 count++;
01186 }
01187 SLOT_ITERATE_END
01188
01189
01190 for (i=0; i<unProtectedPagesSize; ++i) {
01191 mprotect(unProtectedPages[i], 4, PROT_READ|PROT_WRITE);
01192 }
01193 }
01194 }
01195 #endif
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 static int stackTraceDisabled = 0;
01255 #define MAX_STACK_FRAMES 2048
01256 static int numStackFrames;
01257 static void *stackFrames[MAX_STACK_FRAMES];
01258
01259 static void dumpStackFrames(void) {
01260 numStackFrames=MAX_STACK_FRAMES;
01261 if (stackTraceDisabled==0) {
01262 stackTraceDisabled = 1;
01263 CmiBacktraceRecordHuge(stackFrames,&numStackFrames);
01264 stackTraceDisabled = 0;
01265 numStackFrames-=4;
01266 if (numStackFrames < 0) numStackFrames = 0;
01267 } else {
01268 numStackFrames=0;
01269 stackFrames[0] = (void*)0;
01270 }
01271 }
01272
01273
01274 static void *setSlot(Slot **sl,int userSize) {
01275 #ifdef CMK_SEPARATE_SLOT
01276 Slot *s;
01277 char *user;
01278
01279 static int mallocFirstTime = 1;
01280 if (mallocFirstTime) {
01281 mallocFirstTime = 0;
01282 memory_charmdebug_internal = 1;
01283 block_slots = CkCreateHashtable_pointer(sizeof(Slot), 10000);
01284 memory_charmdebug_internal = 0;
01285 }
01286
01287 user = (char *)*sl;
01288 memory_charmdebug_internal = 1;
01289 s = (Slot *)CkHashtablePut(block_slots, sl);
01290 memory_charmdebug_internal = 0;
01291 *sl = s;
01292
01293 s->userData = user;
01294 #else
01295 Slot *s = *sl;
01296 char *user=(char*)(s+1);
01297
01298
01299 s->next=slot_first->next;
01300 s->prev=slot_first;
01301
01302 if (CpdMprotect) {
01303 mprotect(s->next, 4, PROT_READ | PROT_WRITE);
01304 mprotect(s->prev, 4, PROT_READ | PROT_WRITE);
01305 }
01306
01307 s->next->prev=s;
01308 s->prev->next=s;
01309
01310 if (CpdCRC32) {
01311
01312 resetSlotCRC(s->next + 1);
01313 resetSlotCRC(s->prev + 1);
01314 }
01315 if (CpdMprotect) {
01316 if (isProtected(s->next)) mprotect(s->next, 4, PROT_READ);
01317 if (isProtected(s->prev)) mprotect(s->prev, 4, PROT_READ);
01318 }
01319 #endif
01320
01321
01322 s->magic=SLOTMAGIC + NEW_BLOCK + (memory_status_info>0? USER_TYPE : SYSTEM_TYPE);
01323
01324 s->chareID = memory_chare_id;
01325 s->userSize=userSize;
01326 s->extraStack=(SlotStack *)0;
01327
01328
01329 s->stackLen=numStackFrames;
01330 s->from=(void**)(user+userSize);
01331 memcpy(s->from, &stackFrames[4], numStackFrames*sizeof(void*));
01332
01333 if (CpdCRC32) {
01334 unsigned int crc = crc32_initial((unsigned char*)s, SLOT_CRC_LENGTH);
01335 s->slotCRC = crc32_update((unsigned char*)s->from, numStackFrames*sizeof(void*), crc);
01336 s->userCRC = crc32_initial((unsigned char*)user, userSize);
01337 }
01338 if (saveAllocationHistory) {
01339 if (allocatedSinceSize >= allocatedSinceMaxSize) {
01340 Slot **newAllocatedSince;
01341 allocatedSinceMaxSize += 10;
01342 BEFORE_MALLOC_CALL;
01343 newAllocatedSince = (Slot**)mm_malloc((allocatedSinceMaxSize)*sizeof(Slot*));
01344 memcpy(newAllocatedSince, allocatedSince, allocatedSinceSize*sizeof(Slot*));
01345 mm_free(allocatedSince);
01346 AFTER_MALLOC_CALL;
01347 allocatedSince = newAllocatedSince;
01348 }
01349 allocatedSince[allocatedSinceSize++] = s;
01350 }
01351 lastMemoryAllocated = user;
01352
01353 return (void *)user;
01354 }
01355
01356
01357 static void freeSlot(Slot *s) {
01358 #ifdef CMK_SEPARATE_SLOT
01359
01360 int removed = CkHashtableRemove(block_slots, &s->userData);
01361 CmiAssert(removed);
01362
01363
01364
01365 #else
01366
01367 if (CpdMprotect) {
01368 mprotect(s->next, 4, PROT_READ | PROT_WRITE);
01369 mprotect(s->prev, 4, PROT_READ | PROT_WRITE);
01370 }
01371
01372 s->next->prev=s->prev;
01373 s->prev->next=s->next;
01374 if (CpdCRC32) {
01375
01376 resetSlotCRC(s->next + 1);
01377 resetSlotCRC(s->prev + 1);
01378 }
01379 if (CpdMprotect) {
01380 if (isProtected(s->next)) mprotect(s->next, 4, PROT_READ);
01381 if (isProtected(s->prev)) mprotect(s->prev, 4, PROT_READ);
01382 }
01383 s->prev=s->next=(Slot *)0;
01384
01385 s->magic=SLOTMAGIC_FREED;
01386 s->userSize=-1;
01387 #endif
01388 }
01389
01390
01391
01392
01393 static void status(const char *msg) {
01394 if (CmiMyPe()==0 && !CmiArgGivingUsage()) {
01395 CmiPrintf("%s",msg);
01396 }
01397 }
01398
01399 extern int getCharmEnvelopeSize(void);
01400
01401 static int disableVerbosity = 1;
01402 int cpdInitializeMemory;
01403 void CpdSetInitializeMemory(int v) { cpdInitializeMemory = v; }
01404
01405 static void meta_init(char **argv) {
01406 if (CmiMyRank()==0) {
01407 char buf[100];
01408 status("Converse -memory mode: charmdebug\n");
01409 sprintf(buf, "slot size %d\n", (int)sizeof(Slot));
01410 status(buf);
01411 CmiMemoryIs_flag|=CMI_MEMORY_IS_CHARMDEBUG;
01412 cpdInitializeMemory = 0;
01413 charmEnvelopeSize = getCharmEnvelopeSize();
01414 CpdDebugGetAllocationTree = (void* (*)(int*))CreateAllocationTree;
01415 CpdDebug_pupAllocationPoint = pupAllocationPoint;
01416 CpdDebug_deleteAllocationPoint = deleteAllocationPoint;
01417 CpdDebug_MergeAllocationTree = MergeAllocationTree;
01418 CpdDebugGetMemStat = (void* (*)(void))CreateMemStat;
01419 CpdDebug_pupMemStat = pupMemStat;
01420 CpdDebug_deleteMemStat = deleteMemStat;
01421 CpdDebug_mergeMemStat = mergeMemStat;
01422 memory_allocated_user_total = 0;
01423 nextChareID = 1;
01424 #ifndef CMK_SEPARATE_SLOT
01425 slot_first->userSize = 0;
01426 slot_first->stackLen = 0;
01427 #endif
01428 }
01429 if (CmiGetArgFlagDesc(argv,"+memory_report", "Print all cross-object violations")) {
01430 if (CmiMyRank()==0) reportMEM = 1;
01431 }
01432 if (CmiGetArgFlagDesc(argv,"+memory_backup", "Backup all memory at every entry method")) {
01433 if (CmiMyRank()==0) {
01434 CpdMemBackup = 1;
01435 saveAllocationHistory = 1;
01436 }
01437 }
01438 if (CmiGetArgFlagDesc(argv,"+memory_crc", "Use CRC32 to detect memory changes")) {
01439 if (CmiMyRank()==0) CpdCRC32 = 1;
01440 }
01441 #ifdef CPD_USE_MMAP
01442 if (CmiGetArgFlagDesc(argv,"+memory_mprotect", "Use mprotect to protect memory of other chares")) {
01443 if (CmiMyRank()==0) {
01444 struct sigaction sa;
01445 CpdMprotect = 1;
01446 sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART;
01447 sigemptyset(&sa.sa_mask);
01448 sa.sa_sigaction = CpdMMAPhandler;
01449 if (sigaction(SIGSEGV, &sa, NULL) == -1) CmiPrintf("failed to install signal handler\n");
01450 }
01451 }
01452 #endif
01453 if (CmiGetArgFlagDesc(argv,"+memory_verbose", "Print all memory-related operations")) {
01454 if (CmiMyRank()==0) disableVerbosity = 0;
01455 }
01456 if (CmiGetArgFlagDesc(argv,"+memory_nostack", "Do not collect stack traces for memory allocations")) {
01457 if (CmiMyRank()==0) stackTraceDisabled = 1;
01458 }
01459 }
01460
01461 static void *meta_malloc(size_t size) {
01462 void *user = NULL;
01463 if (memory_charmdebug_internal==0) {
01464 Slot *s;
01465 dumpStackFrames();
01466 BEFORE_MALLOC_CALL;
01467 #if CPD_USE_MMAP
01468 s=(Slot *)mmap(NULL, SLOTSPACE+size+numStackFrames*sizeof(void*), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
01469 #else
01470 s=(Slot *)mm_malloc(SLOTSPACE+size+numStackFrames*sizeof(void*));
01471 #endif
01472 AFTER_MALLOC_CALL;
01473 if (s!=NULL) {
01474 user = (char*)setSlot(&s,size);
01475 memory_allocated_user_total += size;
01476 #if ! CMK_BIGSIM_CHARM
01477 traceMalloc_c(user, size, s->from, s->stackLen);
01478 #endif
01479 }
01480 if (disableVerbosity == 0) {
01481 disableVerbosity = 1;
01482 CmiPrintf("allocating %p: %d bytes\n",(void *)s,size);
01483 disableVerbosity = 0;
01484 }
01485 } else {
01486 BEFORE_MALLOC_CALL;
01487 user = mm_malloc(size);
01488 AFTER_MALLOC_CALL;
01489 }
01490 if (cpdInitializeMemory) {
01491 memset(user, 0, size);
01492 }
01493 return user;
01494 }
01495
01496 static void meta_free(void *mem) {
01497 if (memory_charmdebug_internal==0) {
01498 int memSize;
01499 Slot *s;
01500 if (mem==NULL) return;
01501 s=UserToSlot(mem);
01502 #if CMK_MEMORY_BUILD_OS
01503
01504
01505 if (s == NULL || ((s->magic&~FLAGS_MASK) != SLOTMAGIC_VALLOC &&
01506 (s->magic&~FLAGS_MASK) != SLOTMAGIC)) {
01507 BEFORE_MALLOC_CALL;
01508 mm_free(mem);
01509 AFTER_MALLOC_CALL;
01510 return;
01511 }
01512 #endif
01513
01514
01515
01516
01517 if (s == NULL ||
01518 ((s->magic&~FLAGS_MASK) != SLOTMAGIC &&
01519 (s->magic&~FLAGS_MASK) != SLOTMAGIC_FREED &&
01520 (s->magic&~FLAGS_MASK) != SLOTMAGIC_VALLOC)) {
01521 CmiAbort("Free'd non-malloc'd block");
01522 }
01523 #ifdef CMK_SEPARATE_SLOT
01524 CmiAssert(s->userData == mem);
01525 #endif
01526
01527 memSize = 0;
01528 if (mem!=NULL) memSize = s->userSize;
01529 memory_allocated_user_total -= memSize;
01530 #if ! CMK_BIGSIM_CHARM
01531 traceFree_c(mem, memSize);
01532 #endif
01533
01534 if (disableVerbosity == 0) {
01535 disableVerbosity = 1;
01536 CmiPrintf("freeing %p\n",(void *)mem);
01537 disableVerbosity = 0;
01538 }
01539
01540
01541 dumpStackFrames();
01542 if (s->stackLen > numStackFrames) s->stackLen=numStackFrames;
01543 memcpy(s->from, &stackFrames[4], s->stackLen*sizeof(void*));
01544
01545 if ((s->magic&~FLAGS_MASK)==SLOTMAGIC_VALLOC)
01546 {
01547 void *ptr = s->extraStack;
01548 freeSlot(s);
01549 BEFORE_MALLOC_CALL;
01550 mm_free(ptr);
01551
01552 AFTER_MALLOC_CALL;
01553 }
01554 else if ((s->magic&~FLAGS_MASK)==SLOTMAGIC)
01555 {
01556 int freeSize=SLOTSPACE+s->userSize+s->stackLen*sizeof(void*);
01557 void *ptr;
01558 freeSlot(s);
01559 #ifdef CMK_SEPARATE_SLOT
01560 ptr = mem;
01561 #else
01562 ptr = s;
01563 #endif
01564 BEFORE_MALLOC_CALL;
01565 #if CPD_USE_MMAP
01566 munmap(ptr, freeSize);
01567 #else
01568 mm_free(ptr);
01569 #endif
01570 AFTER_MALLOC_CALL;
01571 }
01572 else if (s->magic==SLOTMAGIC_FREED)
01573 CmiAbort("Free'd block twice");
01574 else
01575 CmiAbort("Free'd non-malloc'd block");
01576 } else {
01577 BEFORE_MALLOC_CALL;
01578 mm_free(mem);
01579 AFTER_MALLOC_CALL;
01580 }
01581 }
01582
01583 static void *meta_calloc(size_t nelem, size_t size) {
01584 void *area=meta_malloc(nelem*size);
01585 if (area != NULL) memset(area,0,nelem*size);
01586 return area;
01587 }
01588
01589 static void meta_cfree(void *mem) {
01590 meta_free(mem);
01591 }
01592
01593 static void *meta_realloc(void *oldBuffer, size_t newSize) {
01594 void *newBuffer = meta_malloc(newSize);
01595 if ( newBuffer && oldBuffer ) {
01596
01597 Slot *o=UserToSlot(oldBuffer);
01598 size_t size=o->userSize;
01599 if (size>newSize) size=newSize;
01600 if (size > 0)
01601 memcpy(newBuffer, oldBuffer, size);
01602
01603 meta_free(oldBuffer);
01604 }
01605 return newBuffer;
01606 }
01607
01608 static void *meta_memalign(size_t align, size_t size) {
01609 int overhead = align;
01610 char *alloc;
01611 Slot *s;
01612 void *user;
01613
01614 while (overhead < SLOTSPACE+sizeof(SlotStack)) overhead += align;
01615
01616 dumpStackFrames();
01617
01618 BEFORE_MALLOC_CALL;
01619 alloc=(char *)mm_memalign(align,overhead+size+numStackFrames*sizeof(void*));
01620 AFTER_MALLOC_CALL;
01621 s=(Slot*)(alloc+overhead-SLOTSPACE);
01622 user=setSlot(&s,size);
01623 s->magic = SLOTMAGIC_VALLOC + (s->magic&0xF);
01624 s->extraStack = (SlotStack *)alloc;
01625 s->extraStack->protectedMemory = NULL;
01626 s->extraStack->protectedMemoryLength = 0;
01627 memory_allocated_user_total += size;
01628 #if ! CMK_BIGSIM_CHARM
01629 traceMalloc_c(user, size, s->from, s->stackLen);
01630 #endif
01631 return user;
01632 }
01633
01634 static int meta_posix_memalign(void **outptr, size_t align, size_t size) {
01635 int overhead = align;
01636 int ret;
01637 char *alloc;
01638 Slot *s;
01639 void *user;
01640
01641 while (overhead < SLOTSPACE+sizeof(SlotStack)) overhead += align;
01642
01643 dumpStackFrames();
01644
01645 BEFORE_MALLOC_CALL;
01646 ret = mm_posix_memalign(outptr,align,overhead+size+numStackFrames*sizeof(void*));
01647 alloc=(char *)*outptr;
01648 AFTER_MALLOC_CALL;
01649 if (ret != 0)
01650 return ret;
01651 s=(Slot*)(alloc+overhead-SLOTSPACE);
01652 user=setSlot(&s,size);
01653 s->magic = SLOTMAGIC_VALLOC + (s->magic&0xF);
01654 s->extraStack = (SlotStack *)alloc;
01655 s->extraStack->protectedMemory = NULL;
01656 s->extraStack->protectedMemoryLength = 0;
01657 memory_allocated_user_total += size;
01658 #if ! CMK_BIGSIM_CHARM
01659 traceMalloc_c(user, size, s->from, s->stackLen);
01660 #endif
01661 *outptr = user;
01662 return 0;
01663 }
01664
01665 static void *meta_aligned_alloc(size_t align, size_t size) {
01666 int overhead = align;
01667 char *alloc;
01668 Slot *s;
01669 void *user;
01670
01671 while (overhead < SLOTSPACE+sizeof(SlotStack)) overhead += align;
01672
01673 dumpStackFrames();
01674
01675 BEFORE_MALLOC_CALL;
01676 alloc=(char *)mm_aligned_alloc(align,overhead+size+numStackFrames*sizeof(void*));
01677 AFTER_MALLOC_CALL;
01678 s=(Slot*)(alloc+overhead-SLOTSPACE);
01679 user=setSlot(&s,size);
01680 s->magic = SLOTMAGIC_VALLOC + (s->magic&0xF);
01681 s->extraStack = (SlotStack *)alloc;
01682 s->extraStack->protectedMemory = NULL;
01683 s->extraStack->protectedMemoryLength = 0;
01684 memory_allocated_user_total += size;
01685 #if ! CMK_BIGSIM_CHARM
01686 traceMalloc_c(user, size, s->from, s->stackLen);
01687 #endif
01688 return user;
01689 }
01690
01691 static void *meta_valloc(size_t size) {
01692 return meta_memalign(CmiGetPageSize(),size);
01693 }
01694
01695 static void *meta_pvalloc(size_t size) {
01696 const size_t pagesize = CmiGetPageSize();
01697 return meta_memalign(pagesize, (size + pagesize - 1) & ~(pagesize - 1));
01698 }
01699
01700 void setProtection(char* mem, char *ptr, int len, int flag) {
01701 Slot *sl = UserToSlot(mem);
01702 if (sl->extraStack == NULL) CmiAbort("Tried to protect memory not memaligned\n");
01703 if (flag != 0) {
01704 sl->extraStack->protectedMemory = ptr;
01705 sl->extraStack->protectedMemoryLength = len;
01706 } else {
01707 sl->extraStack->protectedMemory = NULL;
01708 sl->extraStack->protectedMemoryLength = 0;
01709 }
01710 }
01711
01712 void **chareObjectMemory = NULL;
01713 int chareObjectMemorySize = 0;
01714
01715 void setMemoryTypeChare(void *ptr) {
01716 Slot *sl = UserToSlot(ptr);
01717 sl->magic = (sl->magic & ~FLAGS_MASK) | CHARE_TYPE;
01718 sl->chareID = nextChareID;
01719 if (nextChareID >= chareObjectMemorySize) {
01720 void **newChare;
01721 BEFORE_MALLOC_CALL;
01722 newChare = (void**)mm_malloc((nextChareID+100) * sizeof(void*));
01723 AFTER_MALLOC_CALL;
01724 memcpy(newChare, chareObjectMemory, chareObjectMemorySize*sizeof(void*));
01725 chareObjectMemorySize = nextChareID+100;
01726 BEFORE_MALLOC_CALL;
01727 mm_free(chareObjectMemory);
01728 AFTER_MALLOC_CALL;
01729 chareObjectMemory = newChare;
01730 }
01731 chareObjectMemory[nextChareID] = ptr;
01732 nextChareID ++;
01733 }
01734
01735
01736 void setMemoryTypeMessage(void *ptr) {
01737 void *realptr = (char*)ptr - sizeof(CmiChunkHeader);
01738 Slot *sl = UserToSlot(realptr);
01739 if ((sl->magic&~FLAGS_MASK) == SLOTMAGIC || (sl->magic&~FLAGS_MASK) == SLOTMAGIC_VALLOC) {
01740 sl->magic = (sl->magic & ~FLAGS_MASK) | MESSAGE_TYPE;
01741 }
01742 }
01743
01744 int setMemoryChareIDFromPtr(void *ptr) {
01745 int tmp = memory_chare_id;
01746 if (ptr == NULL || ptr == 0) memory_chare_id = 0;
01747 else memory_chare_id = UserToSlot(ptr)->chareID;
01748 return tmp;
01749 }
01750
01751 void setMemoryChareID(int chareID) {
01752 memory_chare_id = chareID;
01753 }
01754
01755 void setMemoryOwnedBy(void *ptr, int chareID) {
01756 Slot *sl = UserToSlot(ptr);
01757 sl->chareID = chareID;
01758 }
01759
01760 void * MemoryToSlot(void *ptr) {
01761 Slot *sl;
01762 int i;
01763 #if defined(CPD_USE_MMAP) && defined(CMK_SEPARATE_SLOT)
01764 for (i=0; i<1000; ++i) {
01765 sl = UserToSlot((void*)(intptr_t)(((CmiUInt8)(intptr_t)ptr)-i*CmiGetPageSize() & ~(CmiGetPageSize()-1)));
01766 if (sl != NULL) return sl;
01767 }
01768 #endif
01769 return NULL;
01770 }
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784 #endif