static void addMemTableEntry(void *memAlloc, size_t number, size_t size, chpl_mem_descInt_t description, int32_t lineno, int32_t filename) { unsigned hashValue; memTableEntry* memEntry; if ((totalEntries+1)*2 > hashSize && hashSizeIndex < NUM_HASH_SIZE_INDICES-1) resizeTable(1); memEntry = (memTableEntry*) sys_calloc(1, sizeof(memTableEntry)); if (!memEntry) { chpl_error("memtrack fault: out of memory allocating memtrack table", lineno, filename); } hashValue = hash(memAlloc, hashSize); memEntry->nextInBucket = memTable[hashValue]; memTable[hashValue] = memEntry; memEntry->description = description; memEntry->memAlloc = memAlloc; memEntry->lineno = lineno; memEntry->filename = filename; memEntry->number = number; memEntry->size = size; increaseMemStat(number*size, lineno, filename); totalEntries += 1; }
static void resizeTable(int direction) { memTableEntry** newMemTable = NULL; int newHashSizeIndex, newHashSize, newHashValue; int i; memTableEntry* me; memTableEntry* next; newHashSizeIndex = hashSizeIndex + direction; newHashSize = hashSizes[newHashSizeIndex]; newMemTable = sys_calloc(newHashSize, sizeof(memTableEntry*)); for (i = 0; i < hashSize; i++) { for (me = memTable[i]; me != NULL; me = next) { next = me->nextInBucket; newHashValue = hash(me->memAlloc, newHashSize); me->nextInBucket = newMemTable[newHashValue]; newMemTable[newHashValue] = me; } } sys_free(memTable); memTable = newMemTable; hashSize = newHashSize; hashSizeIndex = newHashSizeIndex; }
void chpl_setMemFlags(void) { chpl_bool local_memTrack = false; // // Get the values of the memTracking config consts from the module. // The runtime also has the execution-time settings for these same // config consts, but if their default values are changed at compile // time only the emitted code for the module reflects that; the // runtime doesn't know about it. So, we need to get the values // from the module. // // We use local_memTrack here so that the module code doesn't store // directly to our flag and effectively turn on memory tracking too // early. In the first version of this code I passed &chpl_memTrack // itself, and for comm=gasnet we ended up tracking an extra 2 bytes // of space the comm layer allocated as a result of our own call to // chpl_memTracking_returnConfigVals(). // chpl_memTracking_returnConfigVals(&local_memTrack, &memStats, &memLeaksByType, &memLeaksByDesc, &memLeaks, &memMax, &memThreshold, &memLog, &memLeaksLog); if (local_memTrack || memStats || memLeaksByType || (memLeaksByDesc && strcmp(memLeaksByDesc, "")) || memLeaks || memMax > 0 || memLeaksLog != NULL) { chpl_memTrack = true; } if (!memLog) { memLogFile = stdout; } else { if (chpl_numNodes == 1) { memLogFile = fopen(memLog, "w"); } else { char* filename = (char*)sys_malloc((strlen(memLog)+10)*sizeof(char)); sprintf(filename, "%s.%" PRI_c_nodeid_t, memLog, chpl_nodeID); memLogFile = fopen(filename, "w"); sys_free(filename); } } if (chpl_memTrack) { hashSizeIndex = 0; hashSize = hashSizes[hashSizeIndex]; memTable = sys_calloc(hashSize, sizeof(memTableEntry*)); } }
static void printMemAllocsByType(_Bool forLeaks, int32_t lineno, int32_t filename) { size_t* table; memTableEntry* me; int i; const int numberWidth = 9; const int numEntries = CHPL_RT_MD_NUM+chpl_mem_numDescs; if (!chpl_memTrack) { chpl_warning("invalid call to printMemAllocsByType(); rerun with " "--memTrack", lineno, filename); return; } table = (size_t*)sys_calloc(numEntries, 3*sizeof(size_t)); for (i = 0; i < hashSize; i++) { for (me = memTable[i]; me != NULL; me = me->nextInBucket) { table[3*me->description] += me->number*me->size; table[3*me->description+1] += 1; table[3*me->description+2] = me->description; } } qsort(table, numEntries, 3*sizeof(size_t), memTableEntryCmp); if (forLeaks) { fprintf(memLogFile, "====================\n"); fprintf(memLogFile, "Leaked Memory Report\n"); fprintf(memLogFile, "==============================================================\n"); fprintf(memLogFile, "Number of leaked allocations\n"); fprintf(memLogFile, " Total leaked memory (bytes)\n"); } else { fprintf(memLogFile, "================================\n"); fprintf(memLogFile, "Memory Allocation Report by Type\n"); fprintf(memLogFile, "==============================================================\n"); fprintf(memLogFile, "Number of allocations\n"); fprintf(memLogFile, " Total allocated bytes\n"); } fprintf(memLogFile, " Description of allocation\n"); fprintf(memLogFile, "==============================================================\n"); for (i = 0; i < 3*(CHPL_RT_MD_NUM+chpl_mem_numDescs); i += 3) { if (table[i] > 0) { fprintf(memLogFile, "%-*zu %-*zu %s\n", numberWidth, table[i+1], numberWidth, table[i], chpl_mem_descString(table[i+2])); } } fprintf(memLogFile, "==============================================================\n"); sys_free(table); }
__attribute__ ((visibility("default"))) void * calloc(size_t nmemb, size_t size) { if (sys_calloc == NULL) return NULL; num_alloc++; return sys_calloc(nmemb, size); }