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