Enhanced tracemode memory with a new flag (+recordStack) to record the stack trace...
[charm.git] / src / ck-perf / trace-memory.C
1 #include "trace-memory.h"
2
3 #define DefaultBufferSize  10000
4
5 #define DEBUGF(x) // CmiPrintf x
6
7 CkpvStaticDeclare(TraceMemory*, _trace);
8
9 /**
10   For each TraceFoo module, _createTraceFoo() must be defined.
11   This function is called in _createTraces() generated in moduleInit.C
12 */
13 void _createTracememory(char **argv)
14 {
15   DEBUGF(("%d createTraceMemory\n", CkMyPe()));
16   CkpvInitialize(TraceMemory*, _trace);
17   CkpvAccess(_trace) = new TraceMemory(argv);
18   CkpvAccess(_traces)->addTrace(CkpvAccess(_trace));
19 }
20
21 MemEntry::MemEntry() : type(0), where(0), size(0), stackSize(0) { }
22
23 void MemEntry::write(FILE *fp) {
24   fprintf(fp, "%d %p", type, where);
25   if (type == MEMORY_MALLOC) {
26     fprintf(fp, " %d", size);
27     fprintf(fp, " %d", stackSize);
28     void **stack = (void**)(this+1);
29     for (int i=0; i<stackSize; ++i) {
30       fprintf(fp, " %p", stack[i]);
31     }
32   }
33   fprintf(fp, "\n");
34 }
35
36 TraceMemory::TraceMemory(char **argv) {
37   usedBuffer = 0;
38   firstTime = 1;
39   traceDisabled = false;
40   logBufSize = DefaultBufferSize;
41   if (CmiGetArgIntDesc(argv,"+memlogsize",&logBufSize, 
42                        "Log buffer size (in kB)")) {
43     if (CkMyPe() == 0) {
44       CmiPrintf("Trace: logsize: %d kB\n", logBufSize);
45     }
46   }
47   recordStack = false;
48   if (CmiGetArgFlagDesc(argv,"+recordStack",
49                "Record stack trace for malloc")) {
50     recordStack = true;
51   }
52   logBufSize *= 1024;
53   logBuffer = (char *) ::malloc(logBufSize);
54 }
55
56 inline void TraceMemory::checkFlush(int increment) {
57   if (usedBuffer+increment >= logBufSize) {
58     flush();
59   }
60 }
61
62 inline void TraceMemory::flush() {
63   traceDisabled = true;
64   //CmiPrintf("[%d] TraceMemory::flush %d\n",CmiMyPe(),usedBuffer);
65   char *mode;
66   if (firstTime) mode = "w";
67   else mode = "a";
68   firstTime = 0;
69   // flushing the logs
70   char fname[1024];
71   sprintf(fname, "memoryLog_%d", CkMyPe());
72   FILE *fp;
73   do {
74     fp = fopen(fname, mode);
75   } while (!fp && (errno == EINTR || errno == EMFILE));
76   if (!fp) {
77     CmiAbort("Cannot open file for Memory log writing\n");
78   }
79   //fprintf(fp, "begin flush\n");
80   for (int i=0; i<usedBuffer; i += sizeof(MemEntry) + ((MemEntry*)&logBuffer[i])->stackSize*sizeof(void*)) {
81     ((MemEntry*)&logBuffer[i])->write(fp);
82   }
83   //fprintf(fp, "end flush\n");
84   fclose(fp);
85   usedBuffer = 0;
86   traceDisabled = false;
87 }
88
89 void TraceMemory::traceClose() {
90   flush();
91 }
92
93 void TraceMemory::malloc(void *where, int size, void **stack, int stackSize) {
94   if (!traceDisabled) {
95     int increment = sizeof(MemEntry) + (recordStack ? stackSize*sizeof(void*) : 0);
96     checkFlush(increment);
97     ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_MALLOC, where, size);
98     if (recordStack) ((MemEntry*)&logBuffer[usedBuffer])->setStack(stackSize, stack);
99     usedBuffer += increment;
100     //CmiPrintf("[%d] TraceMemory::malloc  %d  (%p)\n",CmiMyPe(),usedBuffer,where);
101   }
102 }
103
104 void TraceMemory::free(void *where) {
105   if (!traceDisabled) {
106     int increment = sizeof(MemEntry);
107     checkFlush(increment);
108     ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_FREE, where);
109     usedBuffer += increment;
110     //CmiPrintf("[%d] TraceMemory::free    %d  (%p)\n",CmiMyPe(),usedBuffer,where);
111   }
112 }