revise app interation API for better interface
[charm.git] / src / ck-perf / trace-common.C
1 /**
2  * \addtogroup CkPerf
3 */
4 /*@{*/
5
6 #include <sys/stat.h>
7 #include <sys/types.h>
8
9 #include "charm.h"
10 #include "middle.h"
11 #include "cklists.h"
12 #include "ckliststring.h"
13
14 #include "trace.h"
15 #include "trace-common.h"
16 #include "allEvents.h"          //projector
17 #include "register.h" // for _entryTable
18
19 CpvCExtern(int, _traceCoreOn);   // projector
20
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
27
28 #define DEBUGF(x)          // CmiPrintf x
29
30 CkpvDeclare(TraceArray*, _traces);              // lists of all trace modules
31
32 /* trace for bluegene */
33 class TraceBluegene;
34 CkpvDeclare(TraceBluegene*, _tracebg);
35 int traceBluegeneLinked=0;                      // if trace-bluegene is linked
36
37 CkpvDeclare(double, traceInitTime);
38 CkpvDeclare(double, traceInitCpuTime);
39 CpvDeclare(int, traceOn);
40 CkpvDeclare(int, traceOnPe);
41 CkpvDeclare(char*, traceRoot);
42 CkpvDeclare(char*, partitionRoot);
43 CkpvDeclare(int, traceRootBaseLength);
44 CkpvDeclare(char*, selective);
45 CkpvDeclare(bool, verbose);
46
47 typedef void (*mTFP)();                   // function pointer for
48 CpvStaticDeclare(mTFP, machineTraceFuncPtr);    // machine user event
49                                           // registration
50
51 int _threadMsg, _threadChare, _threadEP;
52 int _packMsg, _packChare, _packEP;
53 int _unpackMsg, _unpackChare, _unpackEP;
54 int _sdagMsg, _sdagChare, _sdagEP;
55
56 /// decide parameters from command line
57 static void traceCommonInit(char **argv)
58 {
59   CmiArgGroup("Charm++","Tracing");
60   DEBUGF(("[%d] in traceCommonInit.\n", CkMyPe()));
61   CkpvInitialize(double, traceInitTime);
62   CkpvAccess(traceInitTime) = CmiStartTimer();
63   CkpvInitialize(double, traceInitCpuTime);
64   CkpvAccess(traceInitCpuTime) = TRACE_CPUTIMER();
65   CpvInitialize(int, traceOn);
66   CpvAccess(traceOn) = 0;
67   CpvInitialize(int, _traceCoreOn); //projector
68   CpvAccess(_traceCoreOn)=0; //projector
69   CpvInitialize(mTFP, machineTraceFuncPtr);
70   CpvAccess(machineTraceFuncPtr) = NULL;
71   CkpvInitialize(int, traceOnPe);
72   CkpvAccess(traceOnPe) = 1;
73   CkpvInitialize(bool, verbose);
74   if (CmiGetArgFlag(argv, "+traceWarn")) {
75     CkpvAccess(verbose) = true;
76   } else {
77     CkpvAccess(verbose) = false;
78   }
79
80   char *root;
81   char *temproot;
82   char *temproot2;
83   CkpvInitialize(char*, traceRoot);
84   CkpvInitialize(char*, partitionRoot);
85   CkpvInitialize(int, traceRootBaseLength);
86
87   char subdir[20];
88   if(CmiNumPartitions() > 1) {
89     sprintf(subdir, "prj.part%d%s", CmiMyPartition(), PATHSEPSTR);
90   } else {
91     subdir[0]='\0';
92   }
93
94   if (CmiGetArgStringDesc(argv, "+traceroot", &temproot, "Directory to write trace files to")) {
95     int i;
96     // Trying to decide if the traceroot path is absolute or not. If it is not
97     // then create an absolute pathname for it.
98     if (temproot[0] != PATHSEP) {
99       temproot2 = GETCWD(NULL,0);
100       root = (char *)malloc(strlen(temproot2)+1+strlen(temproot)+1);
101       strcpy(root, temproot2);
102       strcat(root, PATHSEPSTR);
103       strcat(root, temproot);
104     } else {
105       root = (char *)malloc(strlen(temproot)+1);
106       strcpy(root,temproot);
107     }
108     for (i=strlen(argv[0])-1; i>=0; i--) if (argv[0][i] == PATHSEP) break;
109     i++;
110     CkpvAccess(traceRootBaseLength) = strlen(root)+1;
111     CkpvAccess(traceRoot) = (char *)malloc(strlen(argv[0]+i) + strlen(root) + 2 +strlen(subdir));    _MEMCHECK(CkpvAccess(traceRoot));
112     CkpvAccess(partitionRoot) = (char *)malloc(strlen(argv[0]+i) + strlen(root) + 2 +strlen(subdir));    _MEMCHECK(CkpvAccess(partitionRoot));
113     strcpy(CkpvAccess(traceRoot), root);
114     strcat(CkpvAccess(traceRoot), PATHSEPSTR);
115     strcat(CkpvAccess(traceRoot), subdir);
116     strcpy(CkpvAccess(partitionRoot),CkpvAccess(traceRoot));
117     strcat(CkpvAccess(traceRoot), argv[0]+i);
118   }
119   else {
120     CkpvAccess(traceRoot) = (char *) malloc(strlen(argv[0])+1 +strlen(subdir));
121     _MEMCHECK(CkpvAccess(traceRoot));
122     CkpvAccess(partitionRoot) = (char *) malloc(strlen(argv[0])+1 +strlen(subdir));
123     _MEMCHECK(CkpvAccess(partitionRoot));
124     strcpy(CkpvAccess(traceRoot), subdir);
125     strcpy(CkpvAccess(partitionRoot),CkpvAccess(traceRoot));
126     strcat(CkpvAccess(traceRoot), argv[0]);
127   }
128   CkpvAccess(traceRootBaseLength)  +=  strlen(subdir);
129         /* added for TAU trace module. */
130   char *cwd;
131   CkpvInitialize(char*, selective);
132   if (CmiGetArgStringDesc(argv, "+selective", &temproot, "TAU's selective instrumentation file")) {
133     // Trying to decide if the traceroot path is absolute or not. If it is not
134     // then create an absolute pathname for it.
135     if (temproot[0] != PATHSEP) {
136       cwd = GETCWD(NULL,0);
137       root = (char *)malloc(strlen(cwd)+strlen(temproot)+2);
138       strcpy(root, cwd);
139       strcat(root, PATHSEPSTR);
140       strcat(root, temproot);
141     } else {
142       root = (char *)malloc(strlen(temproot)+1);
143       strcpy(root,temproot);
144     }
145     CkpvAccess(selective) = (char *) malloc(strlen(root)+1);
146     _MEMCHECK(CkpvAccess(selective));
147     strcpy(CkpvAccess(selective), root);
148     if (CkMyPe() == 0) 
149       CmiPrintf("Trace: selective: %s\n", CkpvAccess(selective));
150   }
151   else {
152     CkpvAccess(selective) = (char *) malloc(3);
153     _MEMCHECK(CkpvAccess(selective));
154     strcpy(CkpvAccess(selective), "");
155   }
156   
157 #ifdef __BIGSIM__
158   if(BgNodeRank()==0) {
159 #else
160   if(CkMyRank()==0) {
161 #endif
162     _threadMsg = CkRegisterMsg("dummy_thread_msg", 0, 0, 0, 0);
163     _threadChare = CkRegisterChare("dummy_thread_chare", 0, TypeInvalid);
164     CkRegisterChareInCharm(_threadChare);
165     _threadEP = CkRegisterEp("dummy_thread_ep", 0, _threadMsg,_threadChare, 0+CK_EP_INTRINSIC);
166
167     _packMsg = CkRegisterMsg("dummy_pack_msg", 0, 0, 0, 0);
168     _packChare = CkRegisterChare("dummy_pack_chare", 0, TypeInvalid);
169     CkRegisterChareInCharm(_packChare);
170     _packEP = CkRegisterEp("dummy_pack_ep", 0, _packMsg,_packChare, 0+CK_EP_INTRINSIC);
171
172     _unpackMsg = CkRegisterMsg("dummy_unpack_msg", 0, 0, 0, 0);
173     _unpackChare = CkRegisterChare("dummy_unpack_chare", 0, TypeInvalid);
174     CkRegisterChareInCharm(_unpackChare);
175     _unpackEP = CkRegisterEp("dummy_unpack_ep", 0, _unpackMsg,_unpackChare, 0+CK_EP_INTRINSIC);
176
177     _sdagMsg = CkRegisterMsg("sdag_msg", 0, 0, 0, 0);
178     _sdagChare = CkRegisterChare("SDAG", 0, TypeInvalid);
179     CkRegisterChareInCharm(_sdagChare);
180     _sdagEP = CkRegisterEp("SDAG_RTS", 0, _sdagMsg, _sdagChare, 0+CK_EP_INTRINSIC);
181   }
182 }
183
184 /** Write out the common parts of the .sts file. */
185 void traceWriteSTS(FILE *stsfp,int nUserEvents) {
186   fprintf(stsfp, "MACHINE %s\n",CMK_MACHINE_NAME);
187 #if CMK_SMP_TRACE_COMMTHREAD
188   //Assuming there's only 1 comm thread now! --Chao Mei
189   //considering the extra comm thread per node
190   fprintf(stsfp, "PROCESSORS %d\n", CkNumPes()+CkNumNodes());  
191   fprintf(stsfp, "SMPMODE %d %d\n", CkMyNodeSize(), CkNumNodes());
192 #else   
193   fprintf(stsfp, "PROCESSORS %d\n", CkNumPes());
194 #endif  
195   fprintf(stsfp, "TOTAL_CHARES %d\n", (int)_chareTable.size());
196   fprintf(stsfp, "TOTAL_EPS %d\n", (int)_entryTable.size());
197   fprintf(stsfp, "TOTAL_MSGS %d\n", (int)_msgTable.size());
198   fprintf(stsfp, "TOTAL_PSEUDOS %d\n", (int)0);
199   fprintf(stsfp, "TOTAL_EVENTS %d\n", (int)nUserEvents);
200   size_t i;
201   for(i=0;i<_chareTable.size();i++)
202     fprintf(stsfp, "CHARE %d %s\n", (int)i, _chareTable[i]->name);
203   for(i=0;i<_entryTable.size();i++)
204     fprintf(stsfp, "ENTRY CHARE %d %s %d %d\n", (int)i, _entryTable[i]->name,
205                  (int)_entryTable[i]->chareIdx, (int)_entryTable[i]->msgIdx);
206   for(i=0;i<_msgTable.size();i++)
207     fprintf(stsfp, "MESSAGE %d %u\n", (int)i, (int)_msgTable[i]->size);
208 }
209
210 extern "C"
211 void traceCommonBeginIdle(void *proj,double curWallTime)
212 {
213   ((TraceArray *)proj)->beginIdle(curWallTime);
214 }
215  
216 extern "C"
217 void traceCommonEndIdle(void *proj,double curWallTime)
218 {
219   ((TraceArray *)proj)->endIdle(curWallTime);
220 }
221
222 void TraceArray::traceBegin() {
223   if (n==0) return; // No tracing modules registered.
224 #if ! CMK_TRACE_IN_CHARM
225   cancel_beginIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)traceCommonBeginIdle,this);
226   cancel_endIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,(CcdVoidFn)traceCommonEndIdle,this);
227 #endif
228   ALLDO(traceBegin());
229 }
230
231 void TraceArray::traceBeginOnCommThread() {
232 #if CMK_SMP_TRACE_COMMTHREAD
233   if (n==0) return; // No tracing modules registered.
234 /*#if ! CMK_TRACE_IN_CHARM      
235   cancel_beginIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)traceCommonBeginIdle,this);
236   cancel_endIdle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,(CcdVoidFn)traceCommonEndIdle,this);
237 #endif*/
238   ALLDO(traceBeginOnCommThread());
239 #endif
240 }
241
242 void TraceArray::traceEnd() {
243   if (n==0) return; // No tracing modules registered.
244   ALLDO(traceEnd());
245 #if ! CMK_TRACE_IN_CHARM
246   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE, cancel_beginIdle);
247   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY, cancel_endIdle);
248 #endif
249 }
250
251 void TraceArray::traceEndOnCommThread() {
252 #if CMK_SMP_TRACE_COMMTHREAD
253   if (n==0) return; // No tracing modules registered.
254   ALLDO(traceEndOnCommThread());
255 /*#if ! CMK_TRACE_IN_CHARM
256   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE, cancel_beginIdle);
257   CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY, cancel_endIdle);
258 #endif*/
259 #endif
260 }
261
262 #if CMK_MULTICORE
263 extern int Cmi_commthread;
264 #endif
265
266 /*Install the beginIdle/endIdle condition handlers.*/
267 extern "C" void traceBegin(void) {
268 #if CMK_TRACE_ENABLED
269   DEBUGF(("[%d] traceBegin called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
270   
271 #if CMK_SMP_TRACE_COMMTHREAD
272   //the first core of this node controls the condition of comm thread
273 #if CMK_MULTICORE
274   if (Cmi_commthread)
275 #endif
276   if(CmiMyRank()==0){
277         if(CpvAccessOther(traceOn, CmiMyNodeSize())!=1){
278                 CkpvAccessOther(_traces, CmiMyNodeSize())->traceBeginOnCommThread();            
279                 CpvAccessOther(traceOn, CmiMyNodeSize()) = 1;
280         }
281   }
282 #endif
283   if (CpvAccess(traceOn)==1) return;
284   CkpvAccess(_traces)->traceBegin();
285   CpvAccess(traceOn) = 1;
286 #endif
287 }
288
289 /*Cancel the beginIdle/endIdle condition handlers.*/
290 extern "C" void traceEnd(void) {
291 #if CMK_TRACE_ENABLED
292   DEBUGF(("[%d] traceEnd called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
293
294 #if CMK_SMP_TRACE_COMMTHREAD
295 //the first core of this node controls the condition of comm thread
296 #if CMK_MULTICORE
297   if (Cmi_commthread)
298 #endif
299   if(CmiMyRank()==0){
300         if(CkpvAccessOther(traceOn, CmiMyNodeSize())!=0){
301                 CkpvAccessOther(_traces, CmiMyNodeSize())->traceEndOnCommThread();
302                 CkpvAccessOther(traceOn, CmiMyNodeSize()) = 0;
303         }
304 }
305 #endif
306         
307         
308   if (CpvAccess(traceOn)==0) return;
309   if (CkpvAccess(_traces) == NULL) {
310     CmiPrintf("Warning: did you mix compilation with and without -DCMK_TRACE_ENABLED? \n");
311   }
312   CkpvAccess(_traces)->traceEnd();
313   CpvAccess(traceOn) = 0;
314 #endif
315 }
316
317 static int checkTraceOnPe(char **argv)
318 {
319   int traceOnPE = 1;
320   char *procs = NULL;
321 #if CMK_BIGSIM_CHARM
322   // check bgconfig file for settings
323   traceOnPE=0;
324   if (BgTraceProjectionOn(CkMyPe())) traceOnPE = 1;
325 #endif
326   if (CmiGetArgStringDesc(argv, "+traceprocessors", &procs, "A list of processors to trace, e.g. 0,10,20-30"))
327   {
328     CkListString procList(procs);
329     traceOnPE = procList.includes(CkMyPe());
330   }
331   // must include pe 0, otherwise sts file is not generated
332   if (CkMyPe()==0) traceOnPE = 1;
333 #if !CMK_TRACE_IN_CHARM
334 #if !CMK_SMP_TRACE_COMMTHREAD
335   /* skip communication thread */
336   traceOnPE = traceOnPE && (CkMyRank() != CkMyNodeSize());
337 #endif
338 #endif
339   return traceOnPE;
340 }
341
342 /// defined in moduleInit.C
343 void _createTraces(char **argv);
344
345
346 bool enableCPTracing; // A global variable specifying whether or not the control point tracing module should be active in the run
347 extern void _registerTraceControlPoints();
348 extern void _createTracecontrolPoints(char **argv);
349
350
351 /**
352     traceInit:          called at Converse level
353     traceCharmInit:     called at Charm++ level
354 */
355 /// initialize trace framework, also create the trace module(s).
356 static inline void _traceInit(char **argv) 
357 {
358   CkpvInitialize(TraceArray *, _traces);
359   CkpvAccess(_traces) = new TraceArray;
360
361   // common init
362   traceCommonInit(argv);
363
364   // check if trace is turned on/off for this pe
365   CkpvAccess(traceOnPe) = checkTraceOnPe(argv);
366
367   // defined in moduleInit.C
368   _createTraces(argv);
369
370   // Now setup the control point tracing module if desired. It is always compiled/linked in, but is not always enabled
371   // FIXME: make sure it is safe to use argv in SMP version 
372   // because CmiGetArgFlagDesc is destructive and this is called on all PEs.
373   if( CmiGetArgFlagDesc(argv,"+CPEnableMeasurements","Enable recording of measurements for Control Points") ){
374     enableCPTracing = true;
375     _createTracecontrolPoints(argv);   
376   } else {
377     enableCPTracing = false;
378   }
379   
380
381   // set trace on/off
382   CkpvAccess(_traces)->setTraceOnPE(CkpvAccess(traceOnPe));
383
384 #if CMK_SMP_TRACE_COMMTHREAD
385 /**
386  * In traceBegin(), CkpvAccessOther will be used which means
387  * this core needs to access to some cpv variable on another 
388  * core in the same memory address space. It's possible the
389  * variable on the other core has not been initialized, which
390  * implies the CpvAcessOther will cause a bad memory access.
391  * Therefore, we need a barrier here for the traceCommonInit to
392  * finish here. -Chao Mei
393  */
394    CmiBarrier();
395 #endif
396
397   if (CkpvAccess(_traces)->length()) {
398     if (CkMyPe() == 0) 
399       CmiPrintf("Trace: traceroot: %s\n", CkpvAccess(traceRoot));
400     if (!CmiGetArgFlagDesc(argv,"+traceoff","Disable tracing"))
401       traceBegin();
402   }
403 }
404
405 /// Converse version
406 extern "C" void traceInit(char **argv) 
407 {
408 #if ! CMK_TRACE_IN_CHARM
409   _traceInit(argv);
410   initTraceCore(argv);
411 #endif
412 }
413
414 /// Charm++ version
415 extern "C" void traceCharmInit(char **argv) 
416 {
417 #if CMK_TRACE_IN_CHARM
418   _traceInit(argv);
419 #endif
420 }
421
422 // CMK_TRACE_ENABLED is already guarded in convcore.c
423 extern "C"
424 void traceMessageRecv(char *msg, int pe)
425 {
426 #if ! CMK_TRACE_IN_CHARM
427   CkpvAccessOther(_traces, CmiRankOf(pe))->messageRecv(msg, pe);
428 #endif
429 }
430
431 extern "C" 
432 void traceBeginIdle()
433 {
434     _TRACE_ONLY(CkpvAccess(_traces)->beginIdle(CmiWallTimer()));
435 }
436
437 extern "C" 
438 void traceEndIdle()
439 {
440     _TRACE_ONLY(CkpvAccess(_traces)->endIdle(CmiWallTimer()));
441 }
442
443 // CMK_TRACE_ENABLED is already guarded in convcore.c
444 // converse thread tracing is not supported in blue gene simulator
445 // in BigSim, threads need to be traced manually (because virtual processors
446 // themselves are implemented as threads and we don't want them to be traced
447 // In BigSim, so far, only AMPI threads are traced.
448 extern "C"
449 void traceResume(CmiObjId *tid)
450 {
451     _TRACE_ONLY(CkpvAccess(_traces)->beginExecute(tid));
452     if(CpvAccess(_traceCoreOn))
453             resumeTraceCore();
454 }
455
456 extern "C"
457 void traceSuspend(void)
458 {
459   _TRACE_ONLY(CkpvAccess(_traces)->endExecute());
460 }
461
462 extern "C"
463 void traceAwaken(CthThread t)
464 {
465   CkpvAccess(_traces)->creation(0, _threadEP);
466 }
467
468 extern "C"
469 void traceUserEvent(int e)
470 {
471 #if CMK_TRACE_ENABLED
472   if (CpvAccess(traceOn))
473     CkpvAccess(_traces)->userEvent(e);
474 #endif
475 }
476
477 extern "C" 
478 void beginAppWork()
479 {
480 #if CMK_TRACE_ENABLED
481     if (CpvAccess(traceOn) && CkpvAccess(_traces))
482     {
483         CkpvAccess(_traces)->beginAppWork();
484     }
485 #endif
486 }
487
488 extern "C" 
489 void endAppWork()
490 {
491 #if CMK_TRACE_ENABLED
492     if (CpvAccess(traceOn) && CkpvAccess(_traces))
493     {
494         CkpvAccess(_traces)->endAppWork();
495     }
496 #endif
497 }
498
499 extern "C"
500 void traceUserBracketEvent(int e, double beginT, double endT)
501 {
502 #if CMK_TRACE_ENABLED
503   if (CpvAccess(traceOn) && CkpvAccess(_traces))
504     CkpvAccess(_traces)->userBracketEvent(e, beginT, endT);
505 #endif
506 }
507
508 extern "C"
509 void traceUserSuppliedData(int d)
510 {
511 #if CMK_TRACE_ENABLED
512   if (CpvAccess(traceOn) && CkpvAccess(_traces))
513     CkpvAccess(_traces)->userSuppliedData(d);
514 #endif
515 }
516
517 extern "C"
518 void traceUserSuppliedNote(char * note)
519 {
520 #if CMK_TRACE_ENABLED
521   if (CpvAccess(traceOn) && CkpvAccess(_traces))
522     CkpvAccess(_traces)->userSuppliedNote(note);
523 #endif
524 }
525
526
527 extern "C"
528 void traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)
529 {
530   //CkPrintf("traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)\n");
531 #if CMK_TRACE_ENABLED
532   if (CpvAccess(traceOn) && CkpvAccess(_traces))
533     CkpvAccess(_traces)->userSuppliedBracketedNote(note, eventID, bt, et);
534 #endif
535 }
536
537
538 extern "C"
539 void traceMemoryUsage()
540 {
541 #if CMK_TRACE_ENABLED
542   double d = CmiMemoryUsage()*1.0;
543
544   if (CpvAccess(traceOn) && CkpvAccess(_traces))
545     CkpvAccess(_traces)->memoryUsage(d);
546 #endif
547 }
548
549 extern "C"
550 void tracePhaseEnd()
551 {
552   _TRACE_ONLY(CkpvAccess(_traces)->endPhase());
553 }
554
555 extern "C"
556 void registerMachineUserEventsFunction(void (*eventRegistrationFunc)()) {
557   CmiAssert(CpvInitialized(machineTraceFuncPtr));
558   CpvAccess(machineTraceFuncPtr) = eventRegistrationFunc;
559 }
560
561 extern "C"
562 void (*registerMachineUserEvents())() {
563   CmiAssert(CpvInitialized(machineTraceFuncPtr));
564   if (CpvAccess(machineTraceFuncPtr) != NULL) {
565     return CpvAccess(machineTraceFuncPtr);
566   } else {
567     return NULL;
568   }
569 }
570
571 extern "C"
572 int traceRegisterUserEvent(const char*x, int e)
573 {
574 #if CMK_TRACE_ENABLED
575   return CkpvAccess(_traces)->traceRegisterUserEvent(x, e);
576 #else
577   return 0;
578 #endif
579 }
580
581 extern "C"
582 void traceClearEps(void)
583 {
584   OPTIMIZE_WARNING
585   CkpvAccess(_traces)->traceClearEps();
586 }
587
588 extern "C"
589 void traceWriteSts(void)
590 {
591   OPTIMIZE_WARNING
592   CkpvAccess(_traces)->traceWriteSts();
593 }
594
595 extern "C"
596 void traceFlushLog(void)
597 {
598   OPTIMIZE_WARNING
599   CkpvAccess(_traces)->traceFlushLog();
600 }
601
602 /**
603     traceClose:         this function is called at Converse
604     traceCharmClose:    called at Charm++ level
605 */
606 extern "C"
607 void traceClose(void)
608 {
609 #if ! CMK_BIGSIM_CHARM
610   OPTIMIZE_WARNING
611   CkpvAccess(_traces)->traceClose();
612 #endif   
613 }
614
615 extern "C"
616 void traceCharmClose(void)
617 {
618 #if CMK_BIGSIM_CHARM
619   OPTIMIZE_WARNING
620   CkpvAccess(_traces)->traceClose();
621 #endif
622 }
623
624 /* **CW** This is the API called from user code to support CCS operations 
625    if supported by the underlying trace module.
626  */
627 extern "C"
628 void traceEnableCCS(void)
629 {
630   OPTIMIZE_WARNING
631   CkpvAccess(_traces)->traceEnableCCS();  
632 }
633
634 /* **CW** Support for thread listeners. This makes a call to each
635    trace module which must support the call.
636 */
637 extern "C"
638 void traceAddThreadListeners(CthThread tid, envelope *e) {
639   _TRACE_ONLY(CkpvAccess(_traces)->traceAddThreadListeners(tid, e));
640 }
641
642 #if 1
643 // helper functions
644 extern int _charmHandlerIdx;
645 class CkCoreState;
646 extern void _processHandler(void *, CkCoreState*);
647 extern "C" int isCharmEnvelope(void *msg);
648 int CkIsCharmMessage(char *msg)
649 {
650 //CmiPrintf("[%d] CkIsCharmMessage: %d %p %d %p\n", CkMyPe(),CmiGetHandler(msg), CmiGetHandlerFunction(msg), _charmHandlerIdx, _processHandler);
651   if ((CmiGetHandler(msg) == _charmHandlerIdx) &&
652          (CmiGetHandlerFunction(msg) == (CmiHandlerEx)_processHandler))
653     return 1;
654   if (CmiGetXHandler(msg) == _charmHandlerIdx) return isCharmEnvelope(msg);
655   return 0;
656 }
657 #endif
658
659 // return 1 if any one of tracing modules is linked.
660 int  traceAvailable()
661 {
662 #if ! CMK_TRACE_ENABLED
663   return 0;
664 #else
665   return CkpvAccess(_traces)->length()>0;
666 #endif
667 }
668
669 double CmiTraceTimer()
670 {
671   return TraceTimer();
672 }
673
674 void TraceArray::creation(envelope *env, int ep, int num)
675
676     if (_entryTable[ep]->traceEnabled)
677         ALLDO(creation(env, ep, num));
678 }
679
680 void TraceArray::creationMulticast(envelope *env, int ep, int num,
681                                    int *pelist)
682 {
683   if (_entryTable[ep]->traceEnabled)
684     ALLDO(creationMulticast(env, ep, num, pelist));
685 }
686
687 /*
688 extern "C" 
689 void registerFunction(char *name){
690         _TRACE_ONLY(CkpvAccess(_traces)->regFunc(name));
691 }
692 */
693
694 extern "C"
695 int traceRegisterFunction(const char* name, int idx) {
696 #if CMK_TRACE_ENABLED
697   if(idx==-999){
698     CkpvAccess(_traces)->regFunc(name, idx);
699   } else {
700     CkpvAccess(_traces)->regFunc(name, idx, 1);
701   }
702   return idx;
703 #else
704   return 0;
705 #endif
706 }
707
708 extern "C" 
709 void traceBeginFuncProj(char *name,char *file,int line){
710          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(name,file,line));
711 }
712
713 extern "C"
714 void traceBeginFuncIndexProj(int idx,char *file,int line){
715          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(idx,file,line));
716 }
717
718 extern "C" 
719 void traceEndFuncProj(char *name){
720          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(name));
721 }
722
723 extern "C" 
724 void traceEndFuncIndexProj(int idx){
725          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(idx));
726 }
727
728 #if CMK_SMP_TRACE_COMMTHREAD
729 extern "C"
730 int traceBeginCommOp(char *msg){
731 #if CMK_TRACE_ENABLED
732   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg)) {
733     CkpvAccess(_traces)->beginExecute(msg);
734     return 1;
735   }
736   return 0;
737 #endif
738 }
739
740 extern "C"
741 void traceEndCommOp(char *msg){
742 #if CMK_TRACE_ENABLED
743   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
744     CkpvAccess(_traces)->endExecute(msg);
745 #endif
746 }
747
748 extern "C"
749 void traceSendMsgComm(char *msg){
750 #if CMK_TRACE_ENABLED
751   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
752     CkpvAccess(_traces)->creation(msg);
753 #endif
754 }
755
756 extern "C"
757 void traceCommSetMsgID(char *msg){
758 #if CMK_TRACE_ENABLED
759   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
760     CkpvAccess(_traces)->traceCommSetMsgID(msg);
761 #endif
762 }
763
764 #endif
765
766 extern "C"
767 void traceGetMsgID(char *msg, int *pe, int *event)
768 {
769 #if CMK_TRACE_ENABLED
770   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
771     CkpvAccess(_traces)->traceGetMsgID(msg, pe, event);
772 #endif
773 }
774
775 extern "C"
776 void traceSetMsgID(char *msg, int pe, int event)
777 {
778 #if CMK_TRACE_ENABLED
779   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
780     CkpvAccess(_traces)->traceSetMsgID(msg, pe, event);
781 #endif
782 }
783
784
785 extern "C"
786 void traceChangeLastTimestamp(double ts){
787 #if CMK_TRACE_ENABLED
788   if (CpvAccess(traceOn) && CkpvAccess(_traces))
789     CkpvAccess(_traces)->changeLastEntryTimestamp(ts);
790 #endif
791 }
792
793 #if CMK_HAS_COUNTER_PAPI
794 CkpvDeclare(int, papiEventSet);
795 CkpvDeclare(LONG_LONG_PAPI*, papiValues);
796 CkpvDeclare(int, papiStarted);
797 CkpvDeclare(int, papiStopped);
798 #ifdef USE_SPP_PAPI
799 int papiEvents[NUMPAPIEVENTS];
800 #else
801 int papiEvents[NUMPAPIEVENTS] = { PAPI_L2_DCM, PAPI_FP_OPS };
802 #endif
803 #endif // CMK_HAS_COUNTER_PAPI
804
805 #if CMK_HAS_COUNTER_PAPI
806 void initPAPI() {
807 #if CMK_HAS_COUNTER_PAPI
808   // We initialize and create the event sets for use with PAPI here.
809   int papiRetValue;
810   if(CkMyRank()==0){
811       papiRetValue = PAPI_is_initialized();
812       if(papiRetValue != PAPI_NOT_INITED)
813           return;
814       CkpvInitialize(int, papiStarted);
815       CkpvAccess(papiStarted) = 0;
816       CkpvInitialize(int, papiStopped);
817       CkpvAccess(papiStopped) = 0;
818     papiRetValue = PAPI_library_init(PAPI_VER_CURRENT);
819     if (papiRetValue != PAPI_VER_CURRENT) {
820       CmiAbort("PAPI Library initialization failure!\n");
821     }
822 #if CMK_SMP
823     if(PAPI_thread_init(pthread_self) != PAPI_OK){
824       CmiAbort("PAPI could not be initialized in SMP mode!\n");
825     }
826 #endif
827   }
828
829 #if CMK_SMP
830   //PAPI_thread_init has to finish before calling PAPI_create_eventset
831   #if CMK_SMP_TRACE_COMMTHREAD
832       CmiNodeAllBarrier();
833   #else
834       CmiNodeBarrier();
835   #endif
836 #endif
837   // PAPI 3 mandates the initialization of the set to PAPI_NULL
838   CkpvInitialize(int, papiEventSet); 
839   CkpvAccess(papiEventSet) = PAPI_NULL; 
840   if (PAPI_create_eventset(&CkpvAccess(papiEventSet)) != PAPI_OK) {
841     CmiAbort("PAPI failed to create event set!\n");
842   }
843 #ifdef USE_SPP_PAPI
844   //  CmiPrintf("Using SPP counters for PAPI\n");
845   if(PAPI_query_event(PAPI_FP_OPS)==PAPI_OK) {
846     papiEvents[0] = PAPI_FP_OPS;
847   }else{
848     if(CmiMyPe()==0){
849       CmiAbort("WARNING: PAPI_FP_OPS doesn't exist on this platform!");
850     }
851   }
852   if(PAPI_query_event(PAPI_TOT_INS)==PAPI_OK) {
853     papiEvents[1] = PAPI_TOT_INS;
854   }else{
855     CmiAbort("WARNING: PAPI_TOT_INS doesn't exist on this platform!");
856   }
857   int EventCode;
858   int ret;
859   ret=PAPI_event_name_to_code("perf::PERF_COUNT_HW_CACHE_LL:MISS",&EventCode);
860   if(PAPI_query_event(EventCode)==PAPI_OK) {
861     papiEvents[2] = EventCode;
862   }else{
863     CmiAbort("WARNING: perf::PERF_COUNT_HW_CACHE_LL:MISS doesn't exist on this platform!");
864   }
865   ret=PAPI_event_name_to_code("DATA_PREFETCHER:ALL",&EventCode);
866   if(PAPI_query_event(EventCode)==PAPI_OK) {
867     papiEvents[3] = EventCode;
868   }else{
869     CmiAbort("WARNING: DATA_PREFETCHER:ALL doesn't exist on this platform!");
870   }
871   if(PAPI_query_event(PAPI_L1_DCA)==PAPI_OK) {
872     papiEvents[4] = PAPI_L1_DCA;
873   }else{
874     CmiAbort("WARNING: PAPI_L1_DCA doesn't exist on this platform!");
875   }
876   if(PAPI_query_event(PAPI_TOT_CYC)==PAPI_OK) {
877     papiEvents[5] = PAPI_TOT_CYC;
878   }else{
879     CmiAbort("WARNING: PAPI_TOT_CYC doesn't exist on this platform!");
880   }
881 #else
882   // just uses { PAPI_L2_DCM, PAPI_FP_OPS } the 2 initialized PAPI_EVENTS
883 #endif
884   papiRetValue = PAPI_add_events(CkpvAccess(papiEventSet), papiEvents, NUMPAPIEVENTS);
885   if (papiRetValue < 0) {
886     if (papiRetValue == PAPI_ECNFLCT) {
887       CmiAbort("PAPI events conflict! Please re-assign event types!\n");
888     } else {
889       char error_str[PAPI_MAX_STR_LEN];
890       PAPI_perror(error_str);
891       //PAPI_perror(papiRetValue,error_str,PAPI_MAX_STR_LEN);
892       CmiPrintf("PAPI failed with error %s val %d\n",error_str,papiRetValue);
893       CmiAbort("PAPI failed to add designated events!\n");
894     }
895   }
896   if(CkMyPe()==0)
897     {
898       CmiPrintf("Registered %d PAPI counters:",NUMPAPIEVENTS);
899       char nameBuf[PAPI_MAX_STR_LEN];
900       for(int i=0;i<NUMPAPIEVENTS;i++)
901         {
902           PAPI_event_code_to_name(papiEvents[i], nameBuf);
903           CmiPrintf("%s ",nameBuf);
904         }
905       CmiPrintf("\n");
906     }
907   CkpvInitialize(LONG_LONG_PAPI*, papiValues);
908   CkpvAccess(papiValues) = (LONG_LONG_PAPI*)malloc(NUMPAPIEVENTS*sizeof(LONG_LONG_PAPI));
909   memset(CkpvAccess(papiValues), 0, NUMPAPIEVENTS*sizeof(LONG_LONG_PAPI));
910 #endif
911 }
912 #endif
913
914 /*@}*/