00001 #include "trace-memory.h"
00002
00003 #define DefaultBufferSize 10000
00004
00005 #define DEBUGF(x) // CmiPrintf x
00006
00007 CkpvStaticDeclare(TraceMemory*, _trace);
00008 extern "C" void memory_trace_all_existing_mallocs();
00009 extern "C" int get_memory_allocated_user_total();
00010
00015 void _createTracememory(char **argv)
00016 {
00017 DEBUGF(("%d createTraceMemory\n", CkMyPe()));
00018 CkpvInitialize(TraceMemory*, _trace);
00019 CkpvAccess(_trace) = new TraceMemory(argv);
00020 CkpvAccess(_traces)->addTrace(CkpvAccess(_trace));
00021
00022
00023
00024
00025 }
00026
00027 MemEntry::MemEntry() : type(0), where(0), size(0), stackSize(0) { }
00028
00029 void MemEntry::write(FILE *fp) {
00030 if (type == BEGIN_TRACE) {
00031 fprintf(fp, "%d %d\n", type, size);
00032 return;
00033 }
00034 fprintf(fp, "%d %p %d", type, where, size);
00035 if (type == MEMORY_MALLOC) {
00036 fprintf(fp, " %d", stackSize);
00037 void **stack = (void**)(this+1);
00038 for (int i=stackSize-1; i>=0; --i) {
00039 fprintf(fp, " %p", stack[i]);
00040 }
00041 }
00042 fprintf(fp, "\n");
00043 }
00044
00045 TraceMemory::TraceMemory(char **argv) {
00046 usedBuffer = 0;
00047 firstTime = true;
00048 traceDisabled = false;
00049 logBufSize = DefaultBufferSize;
00050 if (CmiGetArgIntDesc(argv,"+memlogsize",&logBufSize,
00051 "Log buffer size (in kB)")) {
00052 if (CkMyPe() == 0) {
00053 CmiPrintf("Trace: logsize: %d kB\n", logBufSize);
00054 }
00055 }
00056 recordStack = false;
00057 if (CmiGetArgFlagDesc(argv,"+recordStack",
00058 "Record stack trace for malloc")) {
00059 recordStack = true;
00060 }
00061 logBufSize *= 1024;
00062 logBuffer = (char *) ::malloc(logBufSize);
00063 }
00064
00065 inline void TraceMemory::checkFlush(int increment) {
00066 if (usedBuffer+increment >= logBufSize) {
00067 flush();
00068 }
00069 }
00070
00071 inline void TraceMemory::flush() {
00072 traceDisabled = true;
00073
00074 const char *mode;
00075 if (firstTime) mode = "w";
00076 else mode = "a";
00077 firstTime = false;
00078
00079 char fname[1024];
00080 sprintf(fname, "memoryLog_%d", CkMyPe());
00081 FILE *fp;
00082 do {
00083 fp = fopen(fname, mode);
00084 } while (!fp && (errno == EINTR || errno == EMFILE));
00085 if (!fp) {
00086 CmiAbort("Cannot open file for Memory log writing\n");
00087 }
00088
00089 for (int i=0; i<usedBuffer; i += sizeof(MemEntry) + ((MemEntry*)&logBuffer[i])->stackSize*sizeof(void*)) {
00090 ((MemEntry*)&logBuffer[i])->write(fp);
00091 }
00092
00093 fclose(fp);
00094 usedBuffer = 0;
00095 traceDisabled = false;
00096 }
00097
00098 void TraceMemory::traceClose() {
00099 flush();
00100 }
00101
00102 void TraceMemory::traceBegin() {
00103 int increment = sizeof(MemEntry);
00104 checkFlush(increment);
00105 ((MemEntry*)&logBuffer[usedBuffer])->set(BEGIN_TRACE, 0, get_memory_allocated_user_total());
00106 usedBuffer += increment;
00107 }
00108
00109 void TraceMemory::malloc(void *where, int size, void **stack, int stackSize) {
00110 if (!traceDisabled) {
00111 int increment = sizeof(MemEntry) + (recordStack ? stackSize*sizeof(void*) : 0);
00112 checkFlush(increment);
00113 ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_MALLOC, where, size);
00114 if (recordStack) ((MemEntry*)&logBuffer[usedBuffer])->setStack(stackSize, stack);
00115 usedBuffer += increment;
00116
00117 }
00118 }
00119
00120 void TraceMemory::free(void *where, int size) {
00121 if (!traceDisabled) {
00122 int increment = sizeof(MemEntry);
00123 checkFlush(increment);
00124 ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_FREE, where, size);
00125 usedBuffer += increment;
00126
00127 }
00128 }