Fix absent return types in comm thread tracing
[charm.git] / src / ck-perf / trace-common.C
bloba59bc67b670570fe41cd6636c6994ae5a3d80569
1 /**
2  * \addtogroup CkPerf
3 */
4 /*@{*/
6 #include <sys/stat.h>
7 #include <sys/types.h>
9 #include "charm.h"
10 #include "middle.h"
11 #include "cklists.h"
12 #include "ckliststring.h"
14 #include "trace.h"
15 #include "trace-common.h"
16 #include "allEvents.h"          //projector
17 #include "register.h" // for _entryTable
19 CpvExtern(int, _traceCoreOn);   // projector
21 #if ! CMK_TRACE_ENABLED
22 static int warned = 0;
23 #define OPTIMIZE_WARNING if (!warned) { warned=1;  CmiPrintf("\n\n!!!! Warning: tracing not available without CMK_TRACE_ENABLED!\n");  return;  }
24 #else
25 #define OPTIMIZE_WARNING /*empty*/
26 #endif
28 #define DEBUGF(x)          // CmiPrintf x
30 CkpvDeclare(TraceArray*, _traces);              // lists of all trace modules
32 /* trace for bluegene */
33 class TraceBluegene;
34 CkpvDeclare(TraceBluegene*, _tracebg);
35 int traceBluegeneLinked=0;                      // if trace-bluegene is linked
37 CkpvDeclare(bool,   dumpData);
38 CkpvDeclare(double, traceInitTime);
39 CkpvDeclare(double, traceInitCpuTime);
40 CpvDeclare(int, traceOn);
41 CkpvDeclare(int, traceOnPe);
42 CkpvDeclare(char*, traceRoot);
43 CkpvDeclare(char*, partitionRoot);
44 CkpvDeclare(int, traceRootBaseLength);
45 CkpvDeclare(char*, selective);
46 CkpvDeclare(bool, verbose);
47 bool outlierAutomatic;
48 bool findOutliers;
49 int numKSeeds;
50 int peNumKeep;
51 bool outlierUsePhases;
52 double entryThreshold;
54 typedef void (*mTFP)();                   // function pointer for
55 CpvStaticDeclare(mTFP, machineTraceFuncPtr);    // machine user event
56                                           // registration
58 int _threadMsg, _threadChare, _threadEP;
59 int _packMsg, _packChare, _packEP;
60 int _unpackMsg, _unpackChare, _unpackEP;
61 int _sdagMsg, _sdagChare, _sdagEP;
63 CtvDeclare(int, curThreadEvent);
64 CpvDeclare(int, curPeEvent);
66 #if CMK_BIGSIM_CHARM
67 double TraceTimerCommon(){return TRACE_TIMER();}
68 #else
69 double TraceTimerCommon(){return TRACE_TIMER() - CkpvAccess(traceInitTime);}
70 #endif
71 #if CMK_TRACE_ENABLED
72 void CthSetEventInfo(CthThread t, int event, int srcPE);
73 #endif
74 /// decide parameters from command line
75 static void traceCommonInit(char **argv)
77   CmiArgGroup("Charm++","Tracing");
78   DEBUGF(("[%d] in traceCommonInit.\n", CkMyPe()));
79   CkpvInitialize(double, traceInitTime);
80   CkpvAccess(traceInitTime) = CmiStartTimer();
81   CkpvInitialize(bool, dumpData);
82   CkpvAccess(dumpData) = true;
83   CkpvInitialize(double, traceInitCpuTime);
84   CkpvAccess(traceInitCpuTime) = TRACE_CPUTIMER();
85   CpvInitialize(int, traceOn);
86   CpvAccess(traceOn) = 0;
87   CpvInitialize(int, _traceCoreOn); //projector
88   CpvAccess(_traceCoreOn)=0; //projector
89   CpvInitialize(mTFP, machineTraceFuncPtr);
90   CpvAccess(machineTraceFuncPtr) = NULL;
91   CkpvInitialize(int, traceOnPe);
92   CkpvAccess(traceOnPe) = 1;
93   CkpvInitialize(bool, verbose);
94   if (CmiGetArgFlag(argv, "+traceWarn")) {
95     CkpvAccess(verbose) = true;
96   } else {
97     CkpvAccess(verbose) = false;
98   }
100   char *root=NULL;
101   char *temproot;
102   char *temproot2;
103   CkpvInitialize(char*, traceRoot);
104   CkpvInitialize(char*, partitionRoot);
105   CkpvInitialize(int, traceRootBaseLength);
106   /* Ctv variable to store Cthread Local event ID for Cthread tracing */
107   CtvInitialize(int,curThreadEvent);
108   CtvAccess(curThreadEvent)=0;
109   /* Cpv variable to store current PE event ID for [local] and [inline] method tracing */
110   CpvInitialize(int, curPeEvent);
111   CpvAccess(curPeEvent)=0;
113   char subdir[20];
114   if(CmiNumPartitions() > 1) {
115     sprintf(subdir, "prj.part%d%s", CmiMyPartition(), PATHSEPSTR);
116   } else {
117     subdir[0]='\0';
118   }
120   if (CmiGetArgStringDesc(argv, "+traceroot", &temproot, "Directory to write trace files to")) {
121     int i;
122     // Trying to decide if the traceroot path is absolute or not. If it is not
123     // then create an absolute pathname for it.
124     if (temproot[0] != PATHSEP) {
125       temproot2 = GETCWD(NULL,0);
126       root = (char *)malloc(strlen(temproot2)+1+strlen(temproot)+1);
127       strcpy(root, temproot2);
128       strcat(root, PATHSEPSTR);
129       strcat(root, temproot);
130     } else {
131       root = (char *)malloc(strlen(temproot)+1);
132       strcpy(root,temproot);
133     }
134     for (i=strlen(argv[0])-1; i>=0; i--) if (argv[0][i] == PATHSEP) break;
135     i++;
136     CkpvAccess(traceRootBaseLength) = strlen(root)+1;
137     CkpvAccess(traceRoot) = (char *)malloc(strlen(argv[0]+i) + strlen(root) + 2 +strlen(subdir));    _MEMCHECK(CkpvAccess(traceRoot));
138     CkpvAccess(partitionRoot) = (char *)malloc(strlen(argv[0]+i) + strlen(root) + 2 +strlen(subdir));    _MEMCHECK(CkpvAccess(partitionRoot));
139     strcpy(CkpvAccess(traceRoot), root);
140     strcat(CkpvAccess(traceRoot), PATHSEPSTR);
141     strcat(CkpvAccess(traceRoot), subdir);
142     strcpy(CkpvAccess(partitionRoot),CkpvAccess(traceRoot));
143     strcat(CkpvAccess(traceRoot), argv[0]+i);
144   }
145   else {
146     CkpvAccess(traceRoot) = (char *) malloc(strlen(argv[0])+1 +strlen(subdir));
147     _MEMCHECK(CkpvAccess(traceRoot));
148     CkpvAccess(partitionRoot) = (char *) malloc(strlen(argv[0])+1 +strlen(subdir));
149     _MEMCHECK(CkpvAccess(partitionRoot));
150     strcpy(CkpvAccess(traceRoot), subdir);
151     strcpy(CkpvAccess(partitionRoot),CkpvAccess(traceRoot));
152     strcat(CkpvAccess(traceRoot), argv[0]);
153   }
154   CkpvAccess(traceRootBaseLength)  +=  strlen(subdir);
155         /* added for TAU trace module. */
156   char *cwd;
157   CkpvInitialize(char*, selective);
158   if (CmiGetArgStringDesc(argv, "+selective", &temproot, "TAU's selective instrumentation file")) {
159     // Trying to decide if the traceroot path is absolute or not. If it is not
160     // then create an absolute pathname for it.
161     if (temproot[0] != PATHSEP) {
162       cwd = GETCWD(NULL,0);
163       root = (char *)malloc(strlen(cwd)+strlen(temproot)+2);
164       strcpy(root, cwd);
165       strcat(root, PATHSEPSTR);
166       strcat(root, temproot);
167     } else {
168       root = (char *)malloc(strlen(temproot)+1);
169       strcpy(root,temproot);
170     }
171     CkpvAccess(selective) = (char *) malloc(strlen(root)+1);
172     _MEMCHECK(CkpvAccess(selective));
173     strcpy(CkpvAccess(selective), root);
174     if (CkMyPe() == 0) 
175       CmiPrintf("Trace: selective: %s\n", CkpvAccess(selective));
176   }
177   else {
178     CkpvAccess(selective) = (char *) malloc(3);
179     _MEMCHECK(CkpvAccess(selective));
180     strcpy(CkpvAccess(selective), "");
181   }
183   outlierAutomatic = true;
184   findOutliers = false;
185   numKSeeds = 10;
186   peNumKeep = CkNumPes();
187   outlierUsePhases = false;
188   entryThreshold = 0.0;
189   //For KMeans
190   if (outlierAutomatic) {
191     CmiGetArgIntDesc(argv, "+outlierNumSeeds", &numKSeeds,
192                      "Number of cluster seeds to apply at outlier analysis.");
193     CmiGetArgIntDesc(argv, "+outlierPeNumKeep", 
194                      &peNumKeep, "Number of Processors to retain data");
195     CmiGetArgDoubleDesc(argv, "+outlierEpThresh", &entryThreshold,
196                         "Minimum significance of entry points to be considered for clustering (%).");
197     findOutliers =
198       CmiGetArgFlagDesc(argv,"+outlier", "Find Outliers.");
199     outlierUsePhases = 
200       CmiGetArgFlagDesc(argv,"+outlierUsePhases",
201                         "Apply automatic outlier analysis to any available phases.");
202     if (outlierUsePhases) {
203       // if the user wants to use an outlier feature, it is assumed outlier
204       //    analysis is desired.
205       findOutliers = true;
206     }
207     if(root)
208         free(root);
209   }
211   
212   
213 #ifdef __BIGSIM__
214   if(BgNodeRank()==0) {
215 #else
216   if(CkMyRank()==0) {
217 #endif
218     _threadMsg = CkRegisterMsg("dummy_thread_msg", 0, 0, 0, 0);
219     _threadChare = CkRegisterChare("dummy_thread_chare", 0, TypeInvalid);
220     CkRegisterChareInCharm(_threadChare);
221     _threadEP = CkRegisterEp("dummy_thread_ep", 0, _threadMsg,_threadChare, 0+CK_EP_INTRINSIC);
223     _packMsg = CkRegisterMsg("dummy_pack_msg", 0, 0, 0, 0);
224     _packChare = CkRegisterChare("dummy_pack_chare", 0, TypeInvalid);
225     CkRegisterChareInCharm(_packChare);
226     _packEP = CkRegisterEp("dummy_pack_ep", 0, _packMsg,_packChare, 0+CK_EP_INTRINSIC);
228     _unpackMsg = CkRegisterMsg("dummy_unpack_msg", 0, 0, 0, 0);
229     _unpackChare = CkRegisterChare("dummy_unpack_chare", 0, TypeInvalid);
230     CkRegisterChareInCharm(_unpackChare);
231     _unpackEP = CkRegisterEp("dummy_unpack_ep", 0, _unpackMsg,_unpackChare, 0+CK_EP_INTRINSIC);
233     _sdagMsg = CkRegisterMsg("sdag_msg", 0, 0, 0, 0);
234     _sdagChare = CkRegisterChare("SDAG", 0, TypeInvalid);
235     CkRegisterChareInCharm(_sdagChare);
236     _sdagEP = CkRegisterEp("SDAG_RTS", 0, _sdagMsg, _sdagChare, 0+CK_EP_INTRINSIC);
237   }
240 /** Write out the common parts of the .sts file. */
241 void traceWriteSTS(FILE *stsfp,int nUserEvents) {
242   fprintf(stsfp, "MACHINE \"%s\"\n",CMK_MACHINE_NAME);
243 #if CMK_SMP_TRACE_COMMTHREAD
244   //Assuming there's only 1 comm thread now! --Chao Mei
245   //considering the extra comm thread per node
246   fprintf(stsfp, "PROCESSORS %d\n", CkNumPes()+CkNumNodes());  
247   fprintf(stsfp, "SMPMODE %d %d\n", CkMyNodeSize(), CkNumNodes());
248 #else   
249   fprintf(stsfp, "PROCESSORS %d\n", CkNumPes());
250 #endif  
251   fprintf(stsfp, "TOTAL_CHARES %d\n", (int)_chareTable.size());
252   fprintf(stsfp, "TOTAL_EPS %d\n", (int)_entryTable.size());
253   fprintf(stsfp, "TOTAL_MSGS %d\n", (int)_msgTable.size());
254   fprintf(stsfp, "TOTAL_PSEUDOS %d\n", (int)0);
255   fprintf(stsfp, "TOTAL_EVENTS %d\n", (int)nUserEvents);
256   size_t i;
257   for(i=0;i<_chareTable.size();i++)
258     fprintf(stsfp, "CHARE %d \"%s\" %d\n", (int)i, _chareTable[i]->name, _chareTable[i]->ndims);
259   for(i=0;i<_entryTable.size();i++)
260     fprintf(stsfp, "ENTRY CHARE %d \"%s\" %d %d\n", (int)i, _entryTable[i]->name,
261                  (int)_entryTable[i]->chareIdx, (int)_entryTable[i]->msgIdx);
262   for(i=0;i<_msgTable.size();i++)
263     fprintf(stsfp, "MESSAGE %d %u\n", (int)i, (int)_msgTable[i]->size);
266 void traceCommonBeginIdle(void *proj,double curWallTime)
268   ((TraceArray *)proj)->beginIdle(curWallTime);
271 void traceCommonEndIdle(void *proj,double curWallTime)
273   ((TraceArray *)proj)->endIdle(curWallTime);
276 void TraceArray::traceBegin() {
277   if (n==0) return; // No tracing modules registered.
278 #if ! CMK_TRACE_IN_CHARM
279   cancel_beginIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)traceCommonBeginIdle,this);
280   cancel_endIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,(CcdVoidFn)traceCommonEndIdle,this);
281 #endif
282   ALLDO(traceBegin());
285 void TraceArray::traceBeginOnCommThread() {
286 #if CMK_SMP_TRACE_COMMTHREAD
287   if (n==0) return; // No tracing modules registered.
288 /*#if ! CMK_TRACE_IN_CHARM      
289   cancel_beginIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)traceCommonBeginIdle,this);
290   cancel_endIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,(CcdVoidFn)traceCommonEndIdle,this);
291 #endif*/
292   ALLDO(traceBeginOnCommThread());
293 #endif
296 void TraceArray::traceEnd() {
297   if (n==0) return; // No tracing modules registered.
298   ALLDO(traceEnd());
299 #if ! CMK_TRACE_IN_CHARM
300   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE, cancel_beginIdle);
301   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY, cancel_endIdle);
302 #endif
305 void TraceArray::traceEndOnCommThread() {
306 #if CMK_SMP_TRACE_COMMTHREAD
307   if (n==0) return; // No tracing modules registered.
308   ALLDO(traceEndOnCommThread());
309 /*#if ! CMK_TRACE_IN_CHARM
310   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE, cancel_beginIdle);
311   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY, cancel_endIdle);
312 #endif*/
313 #endif
316 #if CMK_MULTICORE
317 extern int Cmi_commthread;
318 #endif
320 /*Install the beginIdle/endIdle condition handlers.*/
321 void traceBegin(void) {
322 #if CMK_TRACE_ENABLED
323   DEBUGF(("[%d] traceBegin called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
324   
325 #if CMK_SMP_TRACE_COMMTHREAD
326   //the first core of this node controls the condition of comm thread
327 #if CMK_MULTICORE
328   if (Cmi_commthread)
329 #endif
330   if(CmiMyRank()==0){
331         if(CpvAccessOther(traceOn, CmiMyNodeSize())!=1){
332                 CkpvAccessOther(_traces, CmiMyNodeSize())->traceBeginOnCommThread();            
333                 CpvAccessOther(traceOn, CmiMyNodeSize()) = 1;
334         }
335   }
336 #endif
337   if (CpvAccess(traceOn)==1) return;
338   CkpvAccess(_traces)->traceBegin();
339   CpvAccess(traceOn) = 1;
340 #endif
343 /*Cancel the beginIdle/endIdle condition handlers.*/
344 void traceEnd(void) {
345 #if CMK_TRACE_ENABLED
346   DEBUGF(("[%d] traceEnd called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
348 #if CMK_SMP_TRACE_COMMTHREAD
349 //the first core of this node controls the condition of comm thread
350 #if CMK_MULTICORE
351   if (Cmi_commthread)
352 #endif
353   if(CmiMyRank()==0){
354         if(CkpvAccessOther(traceOn, CmiMyNodeSize())!=0){
355                 CkpvAccessOther(_traces, CmiMyNodeSize())->traceEndOnCommThread();
356                 CkpvAccessOther(traceOn, CmiMyNodeSize()) = 0;
357         }
359 #endif
360         
361         
362   if (CpvAccess(traceOn)==0) return;
363   if (CkpvAccess(_traces) == NULL) {
364     CmiPrintf("Warning: did you mix compilation with and without -DCMK_TRACE_ENABLED? \n");
365   }
366   CkpvAccess(_traces)->traceEnd();
367   CpvAccess(traceOn) = 0;
368 #endif
371 void traceBeginComm(void) {
372 #if CMK_TRACE_ENABLED && CMK_SMP_TRACE_COMMTHREAD
373 #if CMK_MULTICORE
374   if (Cmi_commthread)
375 #endif
376     if (CmiMyRank() == 0) {
377       if (CkpvAccessOther(traceOn, CmiMyNodeSize()) != 1) {
378         CkpvAccessOther(_traces, CmiMyNodeSize())->traceBeginOnCommThread();
379         CkpvAccessOther(traceOn, CmiMyNodeSize()) = 1;
380       }
381     }
382 #endif
385 void traceEndComm(void) {
386 #if CMK_TRACE_ENABLED && CMK_SMP_TRACE_COMMTHREAD
387 #if CMK_MULTICORE
388   if (Cmi_commthread)
389 #endif
390     if (CmiMyRank() == 0) {
391       if (CkpvAccessOther(traceOn, CmiMyNodeSize()) != 0) {
392         CkpvAccessOther(_traces, CmiMyNodeSize())->traceEndOnCommThread();
393         CkpvAccessOther(traceOn, CmiMyNodeSize()) = 0;
394       }
395     }
396 #endif
399 static int checkTraceOnPe(char **argv)
401   int traceOnPE = 1;
402   char *procs = NULL;
403 #if CMK_BIGSIM_CHARM
404   // check bgconfig file for settings
405   traceOnPE=0;
406   if (BgTraceProjectionOn(CkMyPe())) traceOnPE = 1;
407 #endif
408   if (CmiGetArgStringDesc(argv, "+traceprocessors", &procs, "A list of processors to trace, e.g. 0,10,20-30"))
409   {
410     CkListString procList(procs);
411     traceOnPE = procList.includes(CkMyPe());
412   }
414   if (CmiGetArgFlagDesc(argv, "+traceselective", " Whether only dump data for PEs based on perfReport"))
415   {
416       if(CkMyPe() !=0)
417           CkpvAccess(dumpData) = false;
418   }
420   // must include pe 0, otherwise sts file is not generated
421   if (CkMyPe()==0) traceOnPE = 1;
422 #if !CMK_TRACE_IN_CHARM
423 #if !CMK_SMP_TRACE_COMMTHREAD
424   /* skip communication thread */
425   traceOnPE = traceOnPE && (CkMyRank() != CkMyNodeSize());
426 #endif
427 #endif
428   return traceOnPE;
431 /// defined in moduleInit.C
432 void _createTraces(char **argv);
435 bool enableCPTracing; // A global variable specifying whether or not the control point tracing module should be active in the run
436 extern void _registerTraceControlPoints();
437 extern void _createTracecontrolPoints(char **argv);
441     traceInit:          called at Converse level
442     traceCharmInit:     called at Charm++ level
444 /// initialize trace framework, also create the trace module(s).
445 static inline void _traceInit(char **argv) 
447   CkpvInitialize(TraceArray *, _traces);
448   CkpvAccess(_traces) = new TraceArray;
450   // common init
451   traceCommonInit(argv);
453   // check if trace is turned on/off for this pe
454   CkpvAccess(traceOnPe) = checkTraceOnPe(argv);
456 #if !CMK_CHARMPY
457   // defined in moduleInit.C
458   _createTraces(argv);
459 #endif
461   // Now setup the control point tracing module if desired. It is always compiled/linked in, but is not always enabled
462   // FIXME: make sure it is safe to use argv in SMP version 
463   // because CmiGetArgFlagDesc is destructive and this is called on all PEs.
464   if( CmiGetArgFlagDesc(argv,"+CPEnableMeasurements","Enable recording of measurements for Control Points") ){
465     enableCPTracing = true;
466     _createTracecontrolPoints(argv);   
467   } else {
468     enableCPTracing = false;
469   }
470   
472   // set trace on/off
473   CkpvAccess(_traces)->setTraceOnPE(CkpvAccess(traceOnPe));
475 #if CMK_SMP_TRACE_COMMTHREAD
477  * In traceBegin(), CkpvAccessOther will be used which means
478  * this core needs to access to some cpv variable on another 
479  * core in the same memory address space. It's possible the
480  * variable on the other core has not been initialized, which
481  * implies the CpvAcessOther will cause a bad memory access.
482  * Therefore, we need a barrier here for the traceCommonInit to
483  * finish here. -Chao Mei
484  */
485    CmiBarrier();
486 #endif
488   if (CkpvAccess(_traces)->length()) {
489     if (CkMyPe() == 0) 
490       CmiPrintf("Trace: traceroot: %s\n", CkpvAccess(traceRoot));
491     if (!CmiGetArgFlagDesc(argv,"+traceoff","Disable tracing"))
492       traceBegin();
493   }
496 /// Converse version
497 void traceInit(char **argv) 
499 #if ! CMK_TRACE_IN_CHARM
500   _traceInit(argv);
501   initTraceCore(argv);
502 #endif
505 /// Charm++ version
506 void traceCharmInit(char **argv) 
508 #if CMK_TRACE_IN_CHARM
509   _traceInit(argv);
510 #endif
513 // CMK_TRACE_ENABLED is already guarded in convcore.C
514 void traceMessageRecv(char *msg, int pe)
516 #if ! CMK_TRACE_IN_CHARM
517   CkpvAccessOther(_traces, CmiRankOf(pe))->messageRecv(msg, pe);
518 #endif
522 void traceBeginIdle()
524     _TRACE_ONLY(CkpvAccess(_traces)->beginIdle(CmiWallTimer()));
528 void traceEndIdle()
530     _TRACE_ONLY(CkpvAccess(_traces)->endIdle(CmiWallTimer()));
533 // CMK_TRACE_ENABLED is already guarded in convcore.C
534 // converse thread tracing is not supported in blue gene simulator
535 // in BigSim, threads need to be traced manually (because virtual processors
536 // themselves are implemented as threads and we don't want them to be traced
537 // In BigSim, so far, only AMPI threads are traced.
538 void traceResume(int eventID, int srcPE, CmiObjId *tid)
540     _TRACE_BEGIN_EXECUTE_DETAILED(eventID, ForChareMsg, _threadEP, srcPE, 0, NULL, tid);
541     if(CpvAccess(_traceCoreOn))
542             resumeTraceCore();
545 void traceSuspend(void)
547   _TRACE_ONLY(CkpvAccess(_traces)->endExecute());
550 void traceAwaken(CthThread t)
552   CkpvAccess(_traces)->creation(0, _threadEP);
553 #if CMK_TRACE_ENABLED
554   CthSetEventInfo(t, CtvAccess(curThreadEvent), CkMyPe());
555 #endif
558 void traceUserEvent(int e)
560 #if CMK_TRACE_ENABLED
561   if (CpvAccess(traceOn))
562     CkpvAccess(_traces)->userEvent(e);
563 #endif
567 void beginAppWork()
569 #if CMK_TRACE_ENABLED
570     if (CpvAccess(traceOn) && CkpvAccess(_traces))
571     {
572         CkpvAccess(_traces)->beginAppWork();
573     }
574 #endif
578 void endAppWork()
580 #if CMK_TRACE_ENABLED
581     if (CpvAccess(traceOn) && CkpvAccess(_traces))
582     {
583         CkpvAccess(_traces)->endAppWork();
584     }
585 #endif
588 void countNewChare()
590 #if CMK_TRACE_ENABLED
591     if (CpvAccess(traceOn) && CkpvAccess(_traces))
592     {
593         CkpvAccess(_traces)->countNewChare();
594     }
595 #endif
599 void beginTuneOverhead()
601 #if CMK_TRACE_ENABLED
602     if (CpvAccess(traceOn) && CkpvAccess(_traces))
603     {
604         CkpvAccess(_traces)->beginTuneOverhead();
605     }
606 #endif
609 void endTuneOverhead()
611 #if CMK_TRACE_ENABLED
612     if (CpvAccess(traceOn) && CkpvAccess(_traces))
613     {
614         CkpvAccess(_traces)->endTuneOverhead();
615     }
616 #endif
619 void traceUserBracketEvent(int e, double beginT, double endT)
621 #if CMK_TRACE_ENABLED
622   if (CpvAccess(traceOn) && CkpvAccess(_traces))
623     CkpvAccess(_traces)->userBracketEvent(e, beginT, endT);
624 #endif
627 // trace a UserBracketEvent that is coming from a "nested" thread, e.g. a virtual AMPI rank
628 void traceUserBracketEventNestedID(int e, double beginT, double endT, int nestedID)
630 #if CMK_TRACE_ENABLED
631   if (CpvAccess(traceOn) && CkpvAccess(_traces))
632     CkpvAccess(_traces)->userBracketEvent(e, beginT, endT, nestedID);
633 #endif
636 void traceBeginUserBracketEvent(int e)
638 #if CMK_TRACE_ENABLED
639   if (CpvAccess(traceOn) && CkpvAccess(_traces))
640     CkpvAccess(_traces)->beginUserBracketEvent(e);
641 #endif
644 void traceBeginUserBracketEventNestedID(int e, int nestedID)
646 #if CMK_TRACE_ENABLED
647   if (CpvAccess(traceOn) && CkpvAccess(_traces))
648     CkpvAccess(_traces)->beginUserBracketEvent(e, nestedID);
649 #endif
652 void traceEndUserBracketEvent(int e)
654 #if CMK_TRACE_ENABLED
655   if (CpvAccess(traceOn) && CkpvAccess(_traces))
656     CkpvAccess(_traces)->endUserBracketEvent(e);
657 #endif
660 void traceEndUserBracketEventNestedID(int e, int nestedID)
662 #if CMK_TRACE_ENABLED
663   if (CpvAccess(traceOn) && CkpvAccess(_traces))
664     CkpvAccess(_traces)->endUserBracketEvent(e, nestedID);
665 #endif
668 //common version of User Stat Functions
669 int traceRegisterUserStat(const char*x, int e)
671 #if CMK_TRACE_ENABLED
672   return CkpvAccess(_traces)->traceRegisterUserStat(x, e);
673 #else
674   return 0;
675 #endif
678 void updateStatPair(int e, double stat, double time)
680 #if CMK_TRACE_ENABLED
681   if (CpvAccess(traceOn) && CkpvAccess(_traces))
682     CkpvAccess(_traces)->updateStatPair(e, stat, time);
683 #endif
686 void updateStat(int e, double stat)
688 #if CMK_TRACE_ENABLED
689   if (CpvAccess(traceOn) && CkpvAccess(_traces))
690     CkpvAccess(_traces)->updateStat(e, stat);
691 #endif
694 void traceUserSuppliedData(int d)
696 #if CMK_TRACE_ENABLED
697   if (CpvAccess(traceOn) && CkpvAccess(_traces))
698     CkpvAccess(_traces)->userSuppliedData(d);
699 #endif
702 void traceUserSuppliedNote(const char * note)
704 #if CMK_TRACE_ENABLED
705   if (CpvAccess(traceOn) && CkpvAccess(_traces))
706     CkpvAccess(_traces)->userSuppliedNote(note);
707 #endif
711 void traceUserSuppliedBracketedNote(const char *note, int eventID, double bt, double et)
713   //CkPrintf("traceUserSuppliedBracketedNote(const char *note, int eventID, double bt, double et)\n");
714 #if CMK_TRACE_ENABLED
715   if (CpvAccess(traceOn) && CkpvAccess(_traces))
716     CkpvAccess(_traces)->userSuppliedBracketedNote(note, eventID, bt, et);
717 #endif
721 void traceMemoryUsage()
723 #if CMK_TRACE_ENABLED
724   double d = CmiMemoryUsage()*1.0;
726   if (CpvAccess(traceOn) && CkpvAccess(_traces))
727     CkpvAccess(_traces)->memoryUsage(d);
728 #endif
731 void tracePhaseEnd()
733   _TRACE_ONLY(CkpvAccess(_traces)->endPhase());
736 void registerMachineUserEventsFunction(void (*eventRegistrationFunc)()) {
737   CmiAssert(CpvInitialized(machineTraceFuncPtr));
738   CpvAccess(machineTraceFuncPtr) = eventRegistrationFunc;
741 void (*registerMachineUserEvents())() {
742   CmiAssert(CpvInitialized(machineTraceFuncPtr));
743   if (CpvAccess(machineTraceFuncPtr) != NULL) {
744     return CpvAccess(machineTraceFuncPtr);
745   } else {
746     return NULL;
747   }
750 int traceRegisterUserEvent(const char*x, int e)
752 #if CMK_TRACE_ENABLED
753   return CkpvAccess(_traces)->traceRegisterUserEvent(x, e);
754 #else
755   return 0;
756 #endif
759 void traceClearEps(void)
761   OPTIMIZE_WARNING
762   CkpvAccess(_traces)->traceClearEps();
765 void traceWriteSts(void)
767   OPTIMIZE_WARNING
768   CkpvAccess(_traces)->traceWriteSts();
771 void traceFlushLog(void)
773   OPTIMIZE_WARNING
774   CkpvAccess(_traces)->traceFlushLog();
778     traceClose:         this function is called at Converse
779     traceCharmClose:    called at Charm++ level
781 void traceClose(void)
783 #if ! CMK_BIGSIM_CHARM
784   OPTIMIZE_WARNING
785   CkpvAccess(_traces)->traceClose();
786 #endif   
789 void traceCharmClose(void)
791 #if CMK_BIGSIM_CHARM
792   OPTIMIZE_WARNING
793   CkpvAccess(_traces)->traceClose();
794 #endif
797 /* **CW** This is the API called from user code to support CCS operations 
798    if supported by the underlying trace module.
799  */
800 void traceEnableCCS(void)
802   OPTIMIZE_WARNING
803   CkpvAccess(_traces)->traceEnableCCS();  
806 /* **CW** Support for thread listeners. This makes a call to each
807    trace module which must support the call.
809 void traceAddThreadListeners(CthThread tid, envelope *e) {
810   _TRACE_ONLY(CkpvAccess(_traces)->traceAddThreadListeners(tid, e));
813 #if 1
814 // helper functions
815 extern int _charmHandlerIdx;
816 class CkCoreState;
817 extern void _processHandler(void *, CkCoreState*);
818 int isCharmEnvelope(void *msg);
819 int CkIsCharmMessage(char *msg)
821 //CmiPrintf("[%d] CkIsCharmMessage: %d %p %d %p\n", CkMyPe(),CmiGetHandler(msg), CmiGetHandlerFunction(msg), _charmHandlerIdx, _processHandler);
822   if ((CmiGetHandler(msg) == _charmHandlerIdx) &&
823          (CmiGetHandlerFunction(msg) == (CmiHandlerEx)_processHandler))
824     return 1;
825   if (CmiGetXHandler(msg) == _charmHandlerIdx) return isCharmEnvelope(msg);
826   return 0;
828 #endif
830 // return 1 if any one of tracing modules is linked.
831 int  traceAvailable()
833 #if ! CMK_TRACE_ENABLED
834   return 0;
835 #else
836   return CkpvAccess(_traces)->length()>0;
837 #endif
840 double CmiTraceTimer()
842   return TraceTimer();
845 void TraceArray::creation(envelope *env, int ep, int num)
847     if (_entryTable[ep]->traceEnabled)
848         ALLDO(creation(env, ep, num));
851 void TraceArray::creationMulticast(envelope *env, int ep, int num,
852                                    const int *pelist)
854   if (_entryTable[ep]->traceEnabled)
855     ALLDO(creationMulticast(env, ep, num, pelist));
858 #if CMK_SMP_TRACE_COMMTHREAD
859 int traceBeginCommOp(char *msg){
860 #if CMK_TRACE_ENABLED
861   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg)) {
862     CkpvAccess(_traces)->beginExecute(msg);
863     return 1;
864   }
865 #endif
866   return 0;
869 void traceEndCommOp(char *msg){
870 #if CMK_TRACE_ENABLED
871   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
872     CkpvAccess(_traces)->endExecute(msg);
873 #endif
876 void traceSendMsgComm(char *msg){
877 #if CMK_TRACE_ENABLED
878   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
879     CkpvAccess(_traces)->creation(msg);
880 #endif
883 void traceCommSetMsgID(char *msg){
884 #if CMK_TRACE_ENABLED
885   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
886     CkpvAccess(_traces)->traceCommSetMsgID(msg);
887 #endif
890 #endif
892 void traceGetMsgID(char *msg, int *pe, int *event)
894 #if CMK_TRACE_ENABLED
895   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
896     CkpvAccess(_traces)->traceGetMsgID(msg, pe, event);
897 #endif
900 void traceSetMsgID(char *msg, int pe, int event)
902 #if CMK_TRACE_ENABLED
903   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
904     CkpvAccess(_traces)->traceSetMsgID(msg, pe, event);
905 #endif
909 void traceChangeLastTimestamp(double ts){
910 #if CMK_TRACE_ENABLED
911   if (CpvAccess(traceOn) && CkpvAccess(_traces))
912     CkpvAccess(_traces)->changeLastEntryTimestamp(ts);
913 #endif
916 #if CMK_HAS_COUNTER_PAPI
917 CkpvDeclare(int, papiEventSet);
918 CkpvDeclare(LONG_LONG_PAPI*, papiValues);
919 CkpvDeclare(int, papiStarted);
920 CkpvDeclare(int, papiStopped);
921 #ifdef USE_SPP_PAPI
922 int papiEvents[NUMPAPIEVENTS];
923 #else
924 int papiEvents[NUMPAPIEVENTS] = { PAPI_L1_TCM, PAPI_L1_TCA, PAPI_L2_TCM, PAPI_L2_TCA};
925 #endif
926 #endif // CMK_HAS_COUNTER_PAPI
928 #if CMK_HAS_COUNTER_PAPI
929 void initPAPI() {
930 #if CMK_HAS_COUNTER_PAPI
931   // We initialize and create the event sets for use with PAPI here.
932   int papiRetValue;
933   if(CkMyRank()==0){
934       papiRetValue = PAPI_is_initialized();
935       if(papiRetValue != PAPI_NOT_INITED)
936           return;
937     papiRetValue = PAPI_library_init(PAPI_VER_CURRENT);
938     if (papiRetValue != PAPI_VER_CURRENT) {
939       CmiAbort("PAPI Library initialization failure!\n");
940     }
941 #if CMK_SMP
942     if(PAPI_thread_init(pthread_self) != PAPI_OK){
943       CmiAbort("PAPI could not be initialized in SMP mode!\n");
944     }
945 #endif
946   }
947   CkpvInitialize(int, papiStarted);
948   CkpvAccess(papiStarted) = 0;
949   CkpvInitialize(int, papiStopped);
950   CkpvAccess(papiStopped) = 0;
952 #if CMK_SMP
953   //PAPI_thread_init has to finish before calling PAPI_create_eventset
954   #if CMK_SMP_TRACE_COMMTHREAD
955       CmiNodeAllBarrier();
956   #else
957       CmiNodeBarrier();
958   #endif
959 #endif
960   // PAPI 3 mandates the initialization of the set to PAPI_NULL
961   CkpvInitialize(int, papiEventSet); 
962   CkpvAccess(papiEventSet) = PAPI_NULL; 
963   if (PAPI_create_eventset(&CkpvAccess(papiEventSet)) != PAPI_OK) {
964     CmiAbort("PAPI failed to create event set!\n");
965   }
966 #ifdef USE_SPP_PAPI
967   //  CmiPrintf("Using SPP counters for PAPI\n");
968   if(PAPI_query_event(PAPI_FP_OPS)==PAPI_OK) {
969     papiEvents[0] = PAPI_FP_OPS;
970   }else{
971     if(CmiMyPe()==0){
972       CmiAbort("WARNING: PAPI_FP_OPS doesn't exist on this platform!");
973     }
974   }
975   if(PAPI_query_event(PAPI_TOT_INS)==PAPI_OK) {
976     papiEvents[1] = PAPI_TOT_INS;
977   }else{
978     CmiAbort("WARNING: PAPI_TOT_INS doesn't exist on this platform!");
979   }
980   int EventCode;
981   int ret;
982   ret=PAPI_event_name_to_code("perf::PERF_COUNT_HW_CACHE_LL:MISS",&EventCode);
983   if(PAPI_query_event(EventCode)==PAPI_OK) {
984     papiEvents[2] = EventCode;
985   }else{
986     CmiAbort("WARNING: perf::PERF_COUNT_HW_CACHE_LL:MISS doesn't exist on this platform!");
987   }
988   ret=PAPI_event_name_to_code("DATA_PREFETCHER:ALL",&EventCode);
989   if(PAPI_query_event(EventCode)==PAPI_OK) {
990     papiEvents[3] = EventCode;
991   }else{
992     CmiAbort("WARNING: DATA_PREFETCHER:ALL doesn't exist on this platform!");
993   }
994   if(PAPI_query_event(PAPI_L1_DCA)==PAPI_OK) {
995     papiEvents[4] = PAPI_L1_DCA;
996   }else{
997     CmiAbort("WARNING: PAPI_L1_DCA doesn't exist on this platform!");
998   }
999   if(PAPI_query_event(PAPI_TOT_CYC)==PAPI_OK) {
1000     papiEvents[5] = PAPI_TOT_CYC;
1001   }else{
1002     CmiAbort("WARNING: PAPI_TOT_CYC doesn't exist on this platform!");
1003   }
1004 #else
1005   // just uses { PAPI_L2_DCM, PAPI_FP_OPS } the 2 initialized PAPI_EVENTS
1006 #endif
1007   papiRetValue = PAPI_add_events(CkpvAccess(papiEventSet), papiEvents, NUMPAPIEVENTS);
1008   if (papiRetValue < 0) {
1009     if (papiRetValue == PAPI_ECNFLCT) {
1010       CmiAbort("PAPI events conflict! Please re-assign event types!\n");
1011     } else {
1012       char error_str[PAPI_MAX_STR_LEN];
1013       //PAPI_perror(error_str);
1014       //PAPI_perror(papiRetValue,error_str,PAPI_MAX_STR_LEN);
1015       CmiAbort("PAPI failed to add designated events!\n");
1016     }
1017   }
1018   if(CkMyPe()==0)
1019     {
1020       CmiPrintf("Registered %d PAPI counters:",NUMPAPIEVENTS);
1021       char nameBuf[PAPI_MAX_STR_LEN];
1022       for(int i=0;i<NUMPAPIEVENTS;i++)
1023         {
1024           PAPI_event_code_to_name(papiEvents[i], nameBuf);
1025           CmiPrintf("%s ",nameBuf);
1026         }
1027       CmiPrintf("\n");
1028     }
1029   CkpvInitialize(LONG_LONG_PAPI*, papiValues);
1030   CkpvAccess(papiValues) = (LONG_LONG_PAPI*)malloc(NUMPAPIEVENTS*sizeof(LONG_LONG_PAPI));
1031   memset(CkpvAccess(papiValues), 0, NUMPAPIEVENTS*sizeof(LONG_LONG_PAPI));
1032 #endif
1034 #endif
1036 void traceSend(void *env, int pe, int size)
1038 #if CMK_TRACE_ENABLED
1039   if (CpvAccess(traceOn) && CkpvAccess(_traces))
1040       CkpvAccess(_traces)->messageSend(env, pe, size);
1041 #endif
1044 void traceRecv(void *env , int size)
1046 #if CMK_TRACE_ENABLED
1047   if (CpvAccess(traceOn) && CkpvAccess(_traces))
1048       CkpvAccess(_traces)->messageRecv(env, size);
1049 #endif
1052 /*@}*/