adding a new variable that records the length of traceRoot
[charm.git] / src / ck-perf / trace-common.C
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**
9  * \addtogroup CkPerf
10 */
11 /*@{*/
12
13 #include <stdlib.h>
14 #if defined(_WIN32) && !defined(__CYGWIN__)
15 #include <direct.h>
16 #define CHDIR _chdir
17 #define GETCWD _getcwd
18 #define PATHSEP '\\'
19 #define PATHSEPSTR "\\"
20 #else
21 #include <unistd.h>
22 #define CHDIR chdir
23 #define GETCWD getcwd
24 #define PATHSEP '/'
25 #define PATHSEPSTR "/"
26 #endif
27
28 // cannot include charm++.h because trace-common.o is part of libconv-core.a
29 #include "charm.h"
30 #include "middle.h"
31 #include "cklists.h"
32 #include "ckliststring.h"
33
34 #include "trace.h"
35 #include "trace-common.h"
36 #include "allEvents.h"          //projector
37 #include "register.h" // for _entryTable
38
39 CpvCExtern(int, _traceCoreOn);   // projector
40
41 #ifdef CMK_OPTIMIZE
42 static int warned = 0;
43 #define OPTIMIZE_WARNING if (!warned) { warned=1;  CmiPrintf("\n\n!!!! Warning: tracing not available with CMK_OPTIMIZE!\n");  return;  }
44 #else
45 #define OPTIMIZE_WARNING /*empty*/
46 #endif
47
48 #define DEBUGF(x)          // CmiPrintf x
49
50 CkpvDeclare(TraceArray*, _traces);              // lists of all trace modules
51
52 /* trace for bluegene */
53 class TraceBluegene;
54 CkpvDeclare(TraceBluegene*, _tracebg);
55 int traceBluegeneLinked=0;                      // if trace-bluegene is linked
56
57 CkpvDeclare(double, traceInitTime);
58 CkpvDeclare(double, traceInitCpuTime);
59 CpvDeclare(int, traceOn);
60 CkpvDeclare(int, traceOnPe);
61 CkpvDeclare(char*, traceRoot);
62 CkpvDeclare(int, traceRootBaseLength);
63 CkpvDeclare(char*, selective);
64 CkpvDeclare(bool, verbose);
65
66 typedef void (*mTFP)();                   // function pointer for
67 CpvStaticDeclare(mTFP, machineTraceFuncPtr);    // machine user event
68                                           // registration
69
70 int _threadMsg, _threadChare, _threadEP;
71 int _packMsg, _packChare, _packEP;
72 int _unpackMsg, _unpackChare, _unpackEP;
73 int _dummyMsg, _dummyChare, _dummyEP;
74
75 /// decide parameters from command line
76 static void traceCommonInit(char **argv)
77 {
78   CmiArgGroup("Charm++","Tracing");
79   DEBUGF(("[%d] in traceCommonInit.\n", CkMyPe()));
80   CkpvInitialize(double, traceInitTime);
81   CkpvAccess(traceInitTime) = CmiStartTimer();
82   CkpvInitialize(double, traceInitCpuTime);
83   CkpvAccess(traceInitCpuTime) = TRACE_CPUTIMER();
84   CpvInitialize(int, traceOn);
85   CpvAccess(traceOn) = 0;
86   CpvInitialize(int, _traceCoreOn); //projector
87   CpvAccess(_traceCoreOn)=0; //projector
88   CpvInitialize(mTFP, machineTraceFuncPtr);
89   CpvAccess(machineTraceFuncPtr) = NULL;
90   CkpvInitialize(int, traceOnPe);
91   CkpvAccess(traceOnPe) = 1;
92
93   CkpvInitialize(bool, verbose);
94   if (CmiGetArgFlag(argv, "+traceWarn")) {
95     CkpvAccess(verbose) = true;
96   } else {
97     CkpvAccess(verbose) = false;
98   }
99
100   char *root;
101   char *temproot;
102   char *temproot2;
103   CkpvInitialize(char*, traceRoot);
104   CkpvInitialize(int, traceRootBaseLength);
105   if (CmiGetArgStringDesc(argv, "+traceroot", &temproot, "Directory to write trace files to")) {
106     int i;
107     // Trying to decide if the traceroot path is absolute or not. If it is not
108     // then create an absolute pathname for it.
109     if (temproot[0] != PATHSEP) {
110       temproot2 = GETCWD(NULL,0);
111       root = (char *)malloc(strlen(temproot2)+1+strlen(temproot)+1);
112       strcpy(root, temproot2);
113       strcat(root, PATHSEPSTR);
114       strcat(root, temproot);
115     } else {
116       root = (char *)malloc(strlen(temproot)+1);
117       strcpy(root,temproot);
118     }
119     for (i=strlen(argv[0])-1; i>=0; i--) if (argv[0][i] == PATHSEP) break;
120     i++;
121     CkpvAccess(traceRootBaseLength) = strlen(root)+1;
122     CkpvAccess(traceRoot) = (char *)malloc(strlen(argv[0]+i) + strlen(root) + 2);    _MEMCHECK(CkpvAccess(traceRoot));
123     strcpy(CkpvAccess(traceRoot), root);
124     strcat(CkpvAccess(traceRoot), PATHSEPSTR);
125     strcat(CkpvAccess(traceRoot), argv[0]+i);
126     if (CkMyPe() == 0) 
127       CmiPrintf("Trace: traceroot: %s\n", CkpvAccess(traceRoot));
128   }
129   else {
130     CkpvAccess(traceRoot) = (char *) malloc(strlen(argv[0])+1);
131     _MEMCHECK(CkpvAccess(traceRoot));
132     strcpy(CkpvAccess(traceRoot), argv[0]);
133   }
134         /* added for TAU trace module. */
135         char *cwd;
136   CkpvInitialize(char*, selective);
137   if (CmiGetArgStringDesc(argv, "+selective", &temproot, "TAU's selective instrumentation file")) {
138     // Trying to decide if the traceroot path is absolute or not. If it is not
139     // then create an absolute pathname for it.
140     if (temproot[0] != PATHSEP) {
141       cwd = GETCWD(NULL,0);
142       root = (char *)malloc(strlen(cwd)+strlen(temproot)+2);
143       strcpy(root, cwd);
144       strcat(root, PATHSEPSTR);
145       strcat(root, temproot);
146     } else {
147       root = (char *)malloc(strlen(temproot)+1);
148       strcpy(root,temproot);
149     }
150     CkpvAccess(selective) = (char *) malloc(strlen(root)+1);
151     _MEMCHECK(CkpvAccess(selective));
152     strcpy(CkpvAccess(selective), root);
153     if (CkMyPe() == 0) 
154       CmiPrintf("Trace: selective: %s\n", CkpvAccess(selective));
155   }
156   else {
157     CkpvAccess(selective) = (char *) malloc(3);
158     _MEMCHECK(CkpvAccess(selective));
159     strcpy(CkpvAccess(selective), "");
160   }
161   
162 #ifdef __BLUEGENE__
163   if(BgNodeRank()==0) {
164 #else
165   if(CkMyRank()==0) {
166 #endif
167     _threadMsg = CkRegisterMsg("dummy_thread_msg", 0, 0, 0, 0);
168     _threadChare = CkRegisterChare("dummy_thread_chare", 0);
169     CkRegisterChareInCharm(_threadChare);
170     _threadEP = CkRegisterEp("dummy_thread_ep", 0, _threadMsg,_threadChare, 0+CK_EP_INTRINSIC);
171
172     _packMsg = CkRegisterMsg("dummy_pack_msg", 0, 0, 0, 0);
173     _packChare = CkRegisterChare("dummy_pack_chare", 0);
174     CkRegisterChareInCharm(_packChare);
175     _packEP = CkRegisterEp("dummy_pack_ep", 0, _packMsg,_packChare, 0+CK_EP_INTRINSIC);
176
177     _unpackMsg = CkRegisterMsg("dummy_unpack_msg", 0, 0, 0, 0);
178     _unpackChare = CkRegisterChare("dummy_unpack_chare", 0);
179     CkRegisterChareInCharm(_unpackChare);
180     _unpackEP = CkRegisterEp("dummy_unpack_ep", 0, _unpackMsg,_unpackChare, 0+CK_EP_INTRINSIC);
181
182     _dummyMsg = CkRegisterMsg("dummy_msg", 0, 0, 0, 0);
183     _dummyChare = CkRegisterChare("dummy_chare", 0);
184     CkRegisterChareInCharm(_dummyChare);
185     _dummyEP = CkRegisterEp("dummy_ep", 0, _dummyMsg,_dummyChare, 0+CK_EP_INTRINSIC);
186   }
187 }
188
189 /** Write out the common parts of the .sts file. */
190 extern void traceWriteSTS(FILE *stsfp,int nUserEvents) {
191   fprintf(stsfp, "MACHINE %s\n",CMK_MACHINE_NAME);
192   fprintf(stsfp, "PROCESSORS %d\n", CkNumPes());
193   fprintf(stsfp, "TOTAL_CHARES %d\n", _chareTable.size());
194   fprintf(stsfp, "TOTAL_EPS %d\n", _entryTable.size());
195   fprintf(stsfp, "TOTAL_MSGS %d\n", _msgTable.size());
196   fprintf(stsfp, "TOTAL_PSEUDOS %d\n", 0);
197   fprintf(stsfp, "TOTAL_EVENTS %d\n", nUserEvents);
198   size_t i;
199   for(i=0;i<_chareTable.size();i++)
200     fprintf(stsfp, "CHARE %d %s\n", i, _chareTable[i]->name);
201   for(i=0;i<_entryTable.size();i++)
202     fprintf(stsfp, "ENTRY CHARE %d %s %d %d\n", i, _entryTable[i]->name,
203                  _entryTable[i]->chareIdx, _entryTable[i]->msgIdx);
204   for(i=0;i<_msgTable.size();i++)
205     fprintf(stsfp, "MESSAGE %d %u\n", i, _msgTable[i]->size);
206 }
207
208 extern "C"
209 void traceCommonBeginIdle(void *proj,double curWallTime)
210 {
211   ((TraceArray *)proj)->beginIdle(curWallTime);
212 }
213  
214 extern "C"
215 void traceCommonEndIdle(void *proj,double curWallTime)
216 {
217   ((TraceArray *)proj)->endIdle(curWallTime);
218 }
219
220 void TraceArray::traceBegin() {
221   if (n==0) return; // No tracing modules registered.
222 #if ! CMK_TRACE_IN_CHARM
223   cancel_beginIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)traceCommonBeginIdle,this);
224   cancel_endIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,(CcdVoidFn)traceCommonEndIdle,this);
225 #endif
226   ALLDO(traceBegin());
227 }
228
229 void TraceArray::traceEnd() {
230   if (n==0) return; // No tracing modules registered.
231   ALLDO(traceEnd());
232 #if ! CMK_TRACE_IN_CHARM
233   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE, cancel_beginIdle);
234   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY, cancel_endIdle);
235 #endif
236 }
237
238 /*Install the beginIdle/endIdle condition handlers.*/
239 extern "C" void traceBegin(void) {
240 #ifndef CMK_OPTIMIZE
241   DEBUGF(("[%d] traceBegin called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
242   if (CpvAccess(traceOn)==1) return;
243   CkpvAccess(_traces)->traceBegin();
244   CpvAccess(traceOn) = 1;
245 #endif
246 }
247
248 /*Cancel the beginIdle/endIdle condition handlers.*/
249 extern "C" void traceEnd(void) {
250 #ifndef CMK_OPTIMIZE
251   DEBUGF(("[%d] traceEnd called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
252   if (CpvAccess(traceOn)==0) return;
253   if (CkpvAccess(_traces) == NULL) {
254     CmiPrintf("Warning: did you mix compilation with and without -DCMK_OPTIMIZE? \n");
255   }
256   CkpvAccess(_traces)->traceEnd();
257   CpvAccess(traceOn) = 0;
258 #endif
259 }
260
261 static int checkTraceOnPe(char **argv)
262 {
263   int traceOnPE = 1;
264   char *procs = NULL;
265 #if CMK_BLUEGENE_CHARM
266   // check bgconfig file for settings
267   traceOnPE=0;
268   if (BgTraceProjectionOn(CkMyPe())) traceOnPE = 1;
269 #endif
270   if (CmiGetArgStringDesc(argv, "+traceprocessors", &procs, "A list of processors to trace, e.g. 0,10,20-30"))
271   {
272     CkListString procList(procs);
273     traceOnPE = procList.includes(CkMyPe());
274   }
275   // must include pe 0, otherwise sts file is not generated
276   if (CkMyPe()==0) traceOnPE = 1;
277 #if !CMK_TRACE_IN_CHARM
278   /* skip communication thread */
279   traceOnPE = traceOnPE && (CkMyRank() != CkMyNodeSize());
280 #endif
281   return traceOnPE;
282 }
283
284 /// defined in moduleInit.C
285 void _createTraces(char **argv);
286
287 /**
288     traceInit:          called at Converse level
289     traceCharmInit:     called at Charm++ level
290 */
291 /// initialize trace framework, also create the trace module(s).
292 static inline void _traceInit(char **argv) 
293 {
294   CkpvInitialize(TraceArray *, _traces);
295   CkpvAccess(_traces) = new TraceArray;
296
297   // common init
298   traceCommonInit(argv);
299
300   // check if trace is turned on/off for this pe
301   CkpvAccess(traceOnPe) = checkTraceOnPe(argv);
302
303   // defined in moduleInit.C
304   _createTraces(argv);
305
306   // set trace on/off
307   CkpvAccess(_traces)->setTraceOnPE(CkpvAccess(traceOnPe));
308
309   if (CkpvAccess(_traces)->length() && !CmiGetArgFlagDesc(argv,"+traceoff","Disable tracing"))
310     traceBegin();
311 }
312
313 /// Converse version
314 extern "C" void traceInit(char **argv) 
315 {
316 #if ! CMK_TRACE_IN_CHARM
317   _traceInit(argv);
318   initTraceCore(argv);
319 #endif
320 }
321
322 /// Charm++ version
323 extern "C" void traceCharmInit(char **argv) 
324 {
325 #if CMK_TRACE_IN_CHARM
326   _traceInit(argv);
327 #endif
328 }
329
330 // CMK_OPTIMIZE is already guarded in convcore.c
331 extern "C"
332 void traceMessageRecv(char *msg, int pe)
333 {
334 #if ! CMK_TRACE_IN_CHARM
335   CkpvAccessOther(_traces, CmiRankOf(pe))->messageRecv(msg, pe);
336 #endif
337 }
338
339 // CMK_OPTIMIZE is already guarded in convcore.c
340 // converse thread tracing is not supported in blue gene simulator
341 // in BigSim, threads need to be traced manually (because virtual processors
342 // themselves are implemented as threads and we don't want them to be traced
343 // In BigSim, so far, only AMPI threads are traced.
344 extern "C"
345 void traceResume(CmiObjId *tid)
346 {
347     _TRACE_ONLY(CkpvAccess(_traces)->beginExecute(tid));
348     if(CpvAccess(_traceCoreOn))
349             resumeTraceCore();
350 }
351
352 extern "C"
353 void traceSuspend(void)
354 {
355   _TRACE_ONLY(CkpvAccess(_traces)->endExecute());
356 }
357
358 extern "C"
359 void traceAwaken(CthThread t)
360 {
361   CkpvAccess(_traces)->creation(0, _threadEP);
362 }
363
364 extern "C"
365 void traceUserEvent(int e)
366 {
367 #ifndef CMK_OPTIMIZE
368   if (CpvAccess(traceOn))
369     CkpvAccess(_traces)->userEvent(e);
370 #endif
371 }
372
373 extern "C"
374 void traceUserBracketEvent(int e, double beginT, double endT)
375 {
376 #ifndef CMK_OPTIMIZE
377   if (CpvAccess(traceOn) && CkpvAccess(_traces))
378     CkpvAccess(_traces)->userBracketEvent(e, beginT, endT);
379 #endif
380 }
381
382 extern "C"
383 void traceUserSuppliedData(int d)
384 {
385 #ifndef CMK_OPTIMIZE
386   if (CpvAccess(traceOn) && CkpvAccess(_traces))
387     CkpvAccess(_traces)->userSuppliedData(d);
388 #endif
389 }
390
391 extern "C"
392 void traceUserSuppliedNote(char * note)
393 {
394 #ifndef CMK_OPTIMIZE
395   if (CpvAccess(traceOn) && CkpvAccess(_traces))
396     CkpvAccess(_traces)->userSuppliedNote(note);
397 #endif
398 }
399
400
401 extern "C"
402 void traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)
403 {
404   //CkPrintf("traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)\n");
405 #ifndef CMK_OPTIMIZE
406   if (CpvAccess(traceOn) && CkpvAccess(_traces))
407     CkpvAccess(_traces)->userSuppliedBracketedNote(note, eventID, bt, et);
408 #endif
409 }
410
411
412 extern "C"
413 void traceMemoryUsage()
414 {
415 #ifndef CMK_OPTIMIZE
416   double d = CmiMemoryUsage()*1.0;
417
418   if (CpvAccess(traceOn) && CkpvAccess(_traces))
419     CkpvAccess(_traces)->memoryUsage(d);
420 #endif
421 }
422
423
424 extern "C"
425 void registerMachineUserEventsFunction(void (*eventRegistrationFunc)()) {
426   CmiAssert(CpvInitialized(machineTraceFuncPtr));
427   CpvAccess(machineTraceFuncPtr) = eventRegistrationFunc;
428 }
429
430 extern "C"
431 void (*registerMachineUserEvents())() {
432   CmiAssert(CpvInitialized(machineTraceFuncPtr));
433   if (CpvAccess(machineTraceFuncPtr) != NULL) {
434     return CpvAccess(machineTraceFuncPtr);
435   } else {
436     return NULL;
437   }
438 }
439
440 extern "C"
441 int traceRegisterUserEvent(const char*x, int e)
442 {
443 #ifndef CMK_OPTIMIZE
444   return CkpvAccess(_traces)->traceRegisterUserEvent(x, e);
445 #else
446   return 0;
447 #endif
448 }
449
450 extern "C"
451 void traceClearEps(void)
452 {
453   OPTIMIZE_WARNING
454   CkpvAccess(_traces)->traceClearEps();
455 }
456
457 extern "C"
458 void traceWriteSts(void)
459 {
460   OPTIMIZE_WARNING
461   CkpvAccess(_traces)->traceWriteSts();
462 }
463
464 extern "C"
465 void traceFlushLog(void)
466 {
467   OPTIMIZE_WARNING
468   CkpvAccess(_traces)->traceFlushLog();
469 }
470
471 /**
472     traceClose:         this function is called at Converse
473     traceCharmClose:    called at Charm++ level
474 */
475 extern "C"
476 void traceClose(void)
477 {
478 #if ! CMK_BLUEGENE_CHARM
479   OPTIMIZE_WARNING
480   CkpvAccess(_traces)->traceClose();
481 #endif   
482 }
483
484 extern "C"
485 void traceCharmClose(void)
486 {
487 #if CMK_BLUEGENE_CHARM
488   OPTIMIZE_WARNING
489   CkpvAccess(_traces)->traceClose();
490 #endif
491 }
492
493 /* **CW** This is the API called from user code to support CCS operations 
494    if supported by the underlying trace module.
495  */
496 extern "C"
497 void traceEnableCCS(void)
498 {
499   OPTIMIZE_WARNING
500   CkpvAccess(_traces)->traceEnableCCS();  
501 }
502
503 /* **CW** Support for thread listeners. This makes a call to each
504    trace module which must support the call.
505 */
506 extern "C"
507 void traceAddThreadListeners(CthThread tid, envelope *e) {
508   _TRACE_ONLY(CkpvAccess(_traces)->traceAddThreadListeners(tid, e));
509 }
510
511 #if 0
512 // helper functions
513 int CkIsCharmMessage(char *msg)
514 {
515 //CmiPrintf("getMsgtype: %d %d %d %d %d\n", ((envelope *)msg)->getMsgtype(), CmiGetHandler(msg), CmiGetXHandler(msg), _charmHandlerIdx, index_skipCldHandler);
516   if ((CmiGetHandler(msg) == _charmHandlerIdx) &&
517          (CmiGetHandlerFunction(msg) == (CmiHandler)_processHandler))
518     return 1;
519   if (CmiGetXHandler(msg) == _charmHandlerIdx) return 1;
520   return 0;
521 }
522 #endif
523
524 // return 1 if any one of tracing modules is linked.
525 int  traceAvailable()
526 {
527 #ifdef CMK_OPTIMIZE
528   return 0;
529 #else
530   return CkpvAccess(_traces)->length()>0;
531 #endif
532 }
533
534 double CmiTraceTimer()
535 {
536   return TraceTimer();
537 }
538
539 void TraceArray::creation(envelope *env, int ep, int num)
540
541     if (_entryTable[ep]->traceEnabled)
542         ALLDO(creation(env, ep, num));
543 }
544
545 void TraceArray::creationMulticast(envelope *env, int ep, int num,
546                                    int *pelist)
547 {
548   if (_entryTable[ep]->traceEnabled)
549     ALLDO(creationMulticast(env, ep, num, pelist));
550 }
551
552 /*
553 extern "C" 
554 void registerFunction(char *name){
555         _TRACE_ONLY(CkpvAccess(_traces)->regFunc(name));
556 }
557 */
558
559 extern "C"
560 int traceRegisterFunction(const char* name, int idx) {
561 #ifndef CMK_OPTIMIZE
562   if(idx==-999){
563     CkpvAccess(_traces)->regFunc(name, idx);
564   } else {
565     CkpvAccess(_traces)->regFunc(name, idx, 1);
566   }
567   return idx;
568 #else
569   return 0;
570 #endif
571 }
572
573 extern "C" 
574 void traceBeginFuncProj(char *name,char *file,int line){
575          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(name,file,line));
576 }
577
578 extern "C"
579 void traceBeginFuncIndexProj(int idx,char *file,int line){
580          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(idx,file,line));
581 }
582
583 extern "C" 
584 void traceEndFuncProj(char *name){
585          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(name));
586 }
587
588 extern "C" 
589 void traceEndFuncIndexProj(int idx){
590          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(idx));
591 }
592
593 /*@}*/