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