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