1653b31dcde0af7190e2a1fa998cc0f7d3e3837f
[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 // CMK_TRACE_ENABLED is already guarded in convcore.c
410 // converse thread tracing is not supported in blue gene simulator
411 // in BigSim, threads need to be traced manually (because virtual processors
412 // themselves are implemented as threads and we don't want them to be traced
413 // In BigSim, so far, only AMPI threads are traced.
414 extern "C"
415 void traceResume(CmiObjId *tid)
416 {
417     _TRACE_ONLY(CkpvAccess(_traces)->beginExecute(tid));
418     if(CpvAccess(_traceCoreOn))
419             resumeTraceCore();
420 }
421
422 extern "C"
423 void traceSuspend(void)
424 {
425   _TRACE_ONLY(CkpvAccess(_traces)->endExecute());
426 }
427
428 extern "C"
429 void traceAwaken(CthThread t)
430 {
431   CkpvAccess(_traces)->creation(0, _threadEP);
432 }
433
434 extern "C"
435 void traceUserEvent(int e)
436 {
437 #if CMK_TRACE_ENABLED
438   if (CpvAccess(traceOn))
439     CkpvAccess(_traces)->userEvent(e);
440 #endif
441 }
442
443 extern "C"
444 void traceUserBracketEvent(int e, double beginT, double endT)
445 {
446 #if CMK_TRACE_ENABLED
447   if (CpvAccess(traceOn) && CkpvAccess(_traces))
448     CkpvAccess(_traces)->userBracketEvent(e, beginT, endT);
449 #endif
450 }
451
452 extern "C"
453 void traceUserSuppliedData(int d)
454 {
455 #if CMK_TRACE_ENABLED
456   if (CpvAccess(traceOn) && CkpvAccess(_traces))
457     CkpvAccess(_traces)->userSuppliedData(d);
458 #endif
459 }
460
461 extern "C"
462 void traceUserSuppliedNote(char * note)
463 {
464 #if CMK_TRACE_ENABLED
465   if (CpvAccess(traceOn) && CkpvAccess(_traces))
466     CkpvAccess(_traces)->userSuppliedNote(note);
467 #endif
468 }
469
470
471 extern "C"
472 void traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)
473 {
474   //CkPrintf("traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)\n");
475 #if CMK_TRACE_ENABLED
476   if (CpvAccess(traceOn) && CkpvAccess(_traces))
477     CkpvAccess(_traces)->userSuppliedBracketedNote(note, eventID, bt, et);
478 #endif
479 }
480
481
482 extern "C"
483 void traceMemoryUsage()
484 {
485 #if CMK_TRACE_ENABLED
486   double d = CmiMemoryUsage()*1.0;
487
488   if (CpvAccess(traceOn) && CkpvAccess(_traces))
489     CkpvAccess(_traces)->memoryUsage(d);
490 #endif
491 }
492
493 extern "C"
494 void tracePhaseEnd()
495 {
496   _TRACE_ONLY(CkpvAccess(_traces)->endPhase());
497 }
498
499 extern "C"
500 void registerMachineUserEventsFunction(void (*eventRegistrationFunc)()) {
501   CmiAssert(CpvInitialized(machineTraceFuncPtr));
502   CpvAccess(machineTraceFuncPtr) = eventRegistrationFunc;
503 }
504
505 extern "C"
506 void (*registerMachineUserEvents())() {
507   CmiAssert(CpvInitialized(machineTraceFuncPtr));
508   if (CpvAccess(machineTraceFuncPtr) != NULL) {
509     return CpvAccess(machineTraceFuncPtr);
510   } else {
511     return NULL;
512   }
513 }
514
515 extern "C"
516 int traceRegisterUserEvent(const char*x, int e)
517 {
518 #if CMK_TRACE_ENABLED
519   return CkpvAccess(_traces)->traceRegisterUserEvent(x, e);
520 #else
521   return 0;
522 #endif
523 }
524
525 extern "C"
526 void traceClearEps(void)
527 {
528   OPTIMIZE_WARNING
529   CkpvAccess(_traces)->traceClearEps();
530 }
531
532 extern "C"
533 void traceWriteSts(void)
534 {
535   OPTIMIZE_WARNING
536   CkpvAccess(_traces)->traceWriteSts();
537 }
538
539 extern "C"
540 void traceFlushLog(void)
541 {
542   OPTIMIZE_WARNING
543   CkpvAccess(_traces)->traceFlushLog();
544 }
545
546 /**
547     traceClose:         this function is called at Converse
548     traceCharmClose:    called at Charm++ level
549 */
550 extern "C"
551 void traceClose(void)
552 {
553 #if ! CMK_BIGSIM_CHARM
554   OPTIMIZE_WARNING
555   CkpvAccess(_traces)->traceClose();
556 #endif   
557 }
558
559 extern "C"
560 void traceCharmClose(void)
561 {
562 #if CMK_BIGSIM_CHARM
563   OPTIMIZE_WARNING
564   CkpvAccess(_traces)->traceClose();
565 #endif
566 }
567
568 /* **CW** This is the API called from user code to support CCS operations 
569    if supported by the underlying trace module.
570  */
571 extern "C"
572 void traceEnableCCS(void)
573 {
574   OPTIMIZE_WARNING
575   CkpvAccess(_traces)->traceEnableCCS();  
576 }
577
578 /* **CW** Support for thread listeners. This makes a call to each
579    trace module which must support the call.
580 */
581 extern "C"
582 void traceAddThreadListeners(CthThread tid, envelope *e) {
583   _TRACE_ONLY(CkpvAccess(_traces)->traceAddThreadListeners(tid, e));
584 }
585
586 #if 1
587 // helper functions
588 extern int _charmHandlerIdx;
589 class CkCoreState;
590 extern void _processHandler(void *, CkCoreState*);
591 int CkIsCharmMessage(char *msg)
592 {
593 //CmiPrintf("[%d] CkIsCharmMessage: %d %p %d %p\n", CkMyPe(),CmiGetHandler(msg), CmiGetHandlerFunction(msg), _charmHandlerIdx, _processHandler);
594   if ((CmiGetHandler(msg) == _charmHandlerIdx) &&
595          (CmiGetHandlerFunction(msg) == (CmiHandlerEx)_processHandler))
596     return 1;
597   if (CmiGetXHandler(msg) == _charmHandlerIdx) return 1;
598   return 0;
599 }
600 #endif
601
602 // return 1 if any one of tracing modules is linked.
603 int  traceAvailable()
604 {
605 #if ! CMK_TRACE_ENABLED
606   return 0;
607 #else
608   return CkpvAccess(_traces)->length()>0;
609 #endif
610 }
611
612 double CmiTraceTimer()
613 {
614   return TraceTimer();
615 }
616
617 void TraceArray::creation(envelope *env, int ep, int num)
618
619     if (_entryTable[ep]->traceEnabled)
620         ALLDO(creation(env, ep, num));
621 }
622
623 void TraceArray::creationMulticast(envelope *env, int ep, int num,
624                                    int *pelist)
625 {
626   if (_entryTable[ep]->traceEnabled)
627     ALLDO(creationMulticast(env, ep, num, pelist));
628 }
629
630 /*
631 extern "C" 
632 void registerFunction(char *name){
633         _TRACE_ONLY(CkpvAccess(_traces)->regFunc(name));
634 }
635 */
636
637 extern "C"
638 int traceRegisterFunction(const char* name, int idx) {
639 #if CMK_TRACE_ENABLED
640   if(idx==-999){
641     CkpvAccess(_traces)->regFunc(name, idx);
642   } else {
643     CkpvAccess(_traces)->regFunc(name, idx, 1);
644   }
645   return idx;
646 #else
647   return 0;
648 #endif
649 }
650
651 extern "C" 
652 void traceBeginFuncProj(char *name,char *file,int line){
653          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(name,file,line));
654 }
655
656 extern "C"
657 void traceBeginFuncIndexProj(int idx,char *file,int line){
658          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(idx,file,line));
659 }
660
661 extern "C" 
662 void traceEndFuncProj(char *name){
663          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(name));
664 }
665
666 extern "C" 
667 void traceEndFuncIndexProj(int idx){
668          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(idx));
669 }
670
671 #if CMK_SMP_TRACE_COMMTHREAD
672 extern "C"
673 int traceBeginCommOp(char *msg){
674 #if CMK_TRACE_ENABLED
675   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg)) {
676     CkpvAccess(_traces)->beginExecute(msg);
677     return 1;
678   }
679   return 0;
680 #endif
681 }
682
683 extern "C"
684 void traceEndCommOp(char *msg){
685 #if CMK_TRACE_ENABLED
686   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
687     CkpvAccess(_traces)->endExecute(msg);
688 #endif
689 }
690
691 extern "C"
692 void traceSendMsgComm(char *msg){
693 #if CMK_TRACE_ENABLED
694   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
695     CkpvAccess(_traces)->creation(msg);
696 #endif
697 }
698 #endif
699
700 extern "C"
701 void traceChangeLastTimestamp(double ts){
702 #if CMK_TRACE_ENABLED
703   if (CpvAccess(traceOn) && CkpvAccess(_traces))
704     CkpvAccess(_traces)->changeLastEntryTimestamp(ts);
705 #endif
706 }
707
708 /*@}*/