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