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 #if CMK_SMP_TRACE_COMMTHREAD
221 void TraceArray::traceBeginOnCommThread() {
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 }
229 #endif
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 #if CMK_SMP_TRACE_COMMTHREAD
241 void TraceArray::traceEndOnCommThread() {
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 }
249 #endif
250
251
252 /*Install the beginIdle/endIdle condition handlers.*/
253 extern "C" void traceBegin(void) {
254 #if CMK_TRACE_ENABLED
255   DEBUGF(("[%d] traceBegin called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
256   
257 #if CMK_SMP_TRACE_COMMTHREAD
258   //the first core of this node controls the condition of comm thread
259   if(CmiMyRank()==0){
260         if(CpvAccessOther(traceOn, CmiMyNodeSize())!=1){
261                 CkpvAccessOther(_traces, CmiMyNodeSize())->traceBeginOnCommThread();            
262                 CpvAccessOther(traceOn, CmiMyNodeSize()) = 1;
263         }
264   }
265 #endif
266   if (CpvAccess(traceOn)==1) return;
267   CkpvAccess(_traces)->traceBegin();
268   CpvAccess(traceOn) = 1;
269 #endif
270 }
271
272 /*Cancel the beginIdle/endIdle condition handlers.*/
273 extern "C" void traceEnd(void) {
274 #if CMK_TRACE_ENABLED
275   DEBUGF(("[%d] traceEnd called with %d at %f\n", CkMyPe(), CpvAccess(traceOn), TraceTimer()));
276
277 #if CMK_SMP_TRACE_COMMTHREAD
278 //the first core of this node controls the condition of comm thread
279 if(CmiMyRank()==0){
280         if(CkpvAccessOther(traceOn, CmiMyNodeSize())!=0){
281                 CkpvAccessOther(_traces, CmiMyNodeSize())->traceEndOnCommThread();
282                 CkpvAccessOther(traceOn, CmiMyNodeSize()) = 0;
283         }
284 }
285 #endif
286         
287         
288   if (CpvAccess(traceOn)==0) return;
289   if (CkpvAccess(_traces) == NULL) {
290     CmiPrintf("Warning: did you mix compilation with and without -DCMK_TRACE_ENABLED? \n");
291   }
292   CkpvAccess(_traces)->traceEnd();
293   CpvAccess(traceOn) = 0;
294 #endif
295 }
296
297 static int checkTraceOnPe(char **argv)
298 {
299   int traceOnPE = 1;
300   char *procs = NULL;
301 #if CMK_BIGSIM_CHARM
302   // check bgconfig file for settings
303   traceOnPE=0;
304   if (BgTraceProjectionOn(CkMyPe())) traceOnPE = 1;
305 #endif
306   if (CmiGetArgStringDesc(argv, "+traceprocessors", &procs, "A list of processors to trace, e.g. 0,10,20-30"))
307   {
308     CkListString procList(procs);
309     traceOnPE = procList.includes(CkMyPe());
310   }
311   // must include pe 0, otherwise sts file is not generated
312   if (CkMyPe()==0) traceOnPE = 1;
313 #if !CMK_TRACE_IN_CHARM
314 #if !CMK_SMP_TRACE_COMMTHREAD
315   /* skip communication thread */
316   traceOnPE = traceOnPE && (CkMyRank() != CkMyNodeSize());
317 #endif
318 #endif
319   return traceOnPE;
320 }
321
322 /// defined in moduleInit.C
323 void _createTraces(char **argv);
324
325
326 bool enableCPTracing; // A global variable specifying whether or not the control point tracing module should be active in the run
327 extern void _registerTraceControlPoints();
328 extern void _createTracecontrolPoints(char **argv);
329
330
331 /**
332     traceInit:          called at Converse level
333     traceCharmInit:     called at Charm++ level
334 */
335 /// initialize trace framework, also create the trace module(s).
336 static inline void _traceInit(char **argv) 
337 {
338   CkpvInitialize(TraceArray *, _traces);
339   CkpvAccess(_traces) = new TraceArray;
340
341   // common init
342   traceCommonInit(argv);
343
344   // check if trace is turned on/off for this pe
345   CkpvAccess(traceOnPe) = checkTraceOnPe(argv);
346
347   // defined in moduleInit.C
348   _createTraces(argv);
349
350   // Now setup the control point tracing module if desired. It is always compiled/linked in, but is not always enabled
351   // FIXME: make sure it is safe to use argv in SMP version 
352   // because CmiGetArgFlagDesc is destructive and this is called on all PEs.
353   if( CmiGetArgFlagDesc(argv,"+CPEnableMeasurements","Enable recording of measurements for Control Points") ){
354     enableCPTracing = true;
355     _createTracecontrolPoints(argv);   
356   } else {
357     enableCPTracing = false;
358   }
359   
360
361   // set trace on/off
362   CkpvAccess(_traces)->setTraceOnPE(CkpvAccess(traceOnPe));
363
364 #if CMK_SMP_TRACE_COMMTHREAD
365 /**
366  * In traceBegin(), CkpvAccessOther will be used which means
367  * this core needs to access to some cpv variable on another 
368  * core in the same memory address space. It's possible the
369  * variable on the other core has not been initialized, which
370  * implies the CpvAcessOther will cause a bad memory access.
371  * Therefore, we need a barrier here for the traceCommonInit to
372  * finish here. -Chao Mei
373  */
374    CmiBarrier();
375 #endif
376
377   if (CkpvAccess(_traces)->length() && !CmiGetArgFlagDesc(argv,"+traceoff","Disable tracing"))
378     traceBegin();
379 }
380
381 /// Converse version
382 extern "C" void traceInit(char **argv) 
383 {
384 #if ! CMK_TRACE_IN_CHARM
385   _traceInit(argv);
386   initTraceCore(argv);
387 #endif
388 }
389
390 /// Charm++ version
391 extern "C" void traceCharmInit(char **argv) 
392 {
393 #if CMK_TRACE_IN_CHARM
394   _traceInit(argv);
395 #endif
396 }
397
398 // CMK_TRACE_ENABLED is already guarded in convcore.c
399 extern "C"
400 void traceMessageRecv(char *msg, int pe)
401 {
402 #if ! CMK_TRACE_IN_CHARM
403   CkpvAccessOther(_traces, CmiRankOf(pe))->messageRecv(msg, pe);
404 #endif
405 }
406
407 // CMK_TRACE_ENABLED is already guarded in convcore.c
408 // converse thread tracing is not supported in blue gene simulator
409 // in BigSim, threads need to be traced manually (because virtual processors
410 // themselves are implemented as threads and we don't want them to be traced
411 // In BigSim, so far, only AMPI threads are traced.
412 extern "C"
413 void traceResume(CmiObjId *tid)
414 {
415     _TRACE_ONLY(CkpvAccess(_traces)->beginExecute(tid));
416     if(CpvAccess(_traceCoreOn))
417             resumeTraceCore();
418 }
419
420 extern "C"
421 void traceSuspend(void)
422 {
423   _TRACE_ONLY(CkpvAccess(_traces)->endExecute());
424 }
425
426 extern "C"
427 void traceAwaken(CthThread t)
428 {
429   CkpvAccess(_traces)->creation(0, _threadEP);
430 }
431
432 extern "C"
433 void traceUserEvent(int e)
434 {
435 #if CMK_TRACE_ENABLED
436   if (CpvAccess(traceOn))
437     CkpvAccess(_traces)->userEvent(e);
438 #endif
439 }
440
441 extern "C"
442 void traceUserBracketEvent(int e, double beginT, double endT)
443 {
444 #if CMK_TRACE_ENABLED
445   if (CpvAccess(traceOn) && CkpvAccess(_traces))
446     CkpvAccess(_traces)->userBracketEvent(e, beginT, endT);
447 #endif
448 }
449
450 extern "C"
451 void traceUserSuppliedData(int d)
452 {
453 #if CMK_TRACE_ENABLED
454   if (CpvAccess(traceOn) && CkpvAccess(_traces))
455     CkpvAccess(_traces)->userSuppliedData(d);
456 #endif
457 }
458
459 extern "C"
460 void traceUserSuppliedNote(char * note)
461 {
462 #if CMK_TRACE_ENABLED
463   if (CpvAccess(traceOn) && CkpvAccess(_traces))
464     CkpvAccess(_traces)->userSuppliedNote(note);
465 #endif
466 }
467
468
469 extern "C"
470 void traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)
471 {
472   //CkPrintf("traceUserSuppliedBracketedNote(char *note, int eventID, double bt, double et)\n");
473 #if CMK_TRACE_ENABLED
474   if (CpvAccess(traceOn) && CkpvAccess(_traces))
475     CkpvAccess(_traces)->userSuppliedBracketedNote(note, eventID, bt, et);
476 #endif
477 }
478
479
480 extern "C"
481 void traceMemoryUsage()
482 {
483 #if CMK_TRACE_ENABLED
484   double d = CmiMemoryUsage()*1.0;
485
486   if (CpvAccess(traceOn) && CkpvAccess(_traces))
487     CkpvAccess(_traces)->memoryUsage(d);
488 #endif
489 }
490
491 extern "C"
492 void tracePhaseEnd()
493 {
494   _TRACE_ONLY(CkpvAccess(_traces)->endPhase());
495 }
496
497 extern "C"
498 void registerMachineUserEventsFunction(void (*eventRegistrationFunc)()) {
499   CmiAssert(CpvInitialized(machineTraceFuncPtr));
500   CpvAccess(machineTraceFuncPtr) = eventRegistrationFunc;
501 }
502
503 extern "C"
504 void (*registerMachineUserEvents())() {
505   CmiAssert(CpvInitialized(machineTraceFuncPtr));
506   if (CpvAccess(machineTraceFuncPtr) != NULL) {
507     return CpvAccess(machineTraceFuncPtr);
508   } else {
509     return NULL;
510   }
511 }
512
513 extern "C"
514 int traceRegisterUserEvent(const char*x, int e)
515 {
516 #if CMK_TRACE_ENABLED
517   return CkpvAccess(_traces)->traceRegisterUserEvent(x, e);
518 #else
519   return 0;
520 #endif
521 }
522
523 extern "C"
524 void traceClearEps(void)
525 {
526   OPTIMIZE_WARNING
527   CkpvAccess(_traces)->traceClearEps();
528 }
529
530 extern "C"
531 void traceWriteSts(void)
532 {
533   OPTIMIZE_WARNING
534   CkpvAccess(_traces)->traceWriteSts();
535 }
536
537 extern "C"
538 void traceFlushLog(void)
539 {
540   OPTIMIZE_WARNING
541   CkpvAccess(_traces)->traceFlushLog();
542 }
543
544 /**
545     traceClose:         this function is called at Converse
546     traceCharmClose:    called at Charm++ level
547 */
548 extern "C"
549 void traceClose(void)
550 {
551 #if ! CMK_BIGSIM_CHARM
552   OPTIMIZE_WARNING
553   CkpvAccess(_traces)->traceClose();
554 #endif   
555 }
556
557 extern "C"
558 void traceCharmClose(void)
559 {
560 #if CMK_BIGSIM_CHARM
561   OPTIMIZE_WARNING
562   CkpvAccess(_traces)->traceClose();
563 #endif
564 }
565
566 /* **CW** This is the API called from user code to support CCS operations 
567    if supported by the underlying trace module.
568  */
569 extern "C"
570 void traceEnableCCS(void)
571 {
572   OPTIMIZE_WARNING
573   CkpvAccess(_traces)->traceEnableCCS();  
574 }
575
576 /* **CW** Support for thread listeners. This makes a call to each
577    trace module which must support the call.
578 */
579 extern "C"
580 void traceAddThreadListeners(CthThread tid, envelope *e) {
581   _TRACE_ONLY(CkpvAccess(_traces)->traceAddThreadListeners(tid, e));
582 }
583
584 #if 1
585 // helper functions
586 extern int _charmHandlerIdx;
587 class CkCoreState;
588 extern void _processHandler(void *, CkCoreState*);
589 int CkIsCharmMessage(char *msg)
590 {
591 //CmiPrintf("[%d] CkIsCharmMessage: %d %p %d %p\n", CkMyPe(),CmiGetHandler(msg), CmiGetHandlerFunction(msg), _charmHandlerIdx, _processHandler);
592   if ((CmiGetHandler(msg) == _charmHandlerIdx) &&
593          (CmiGetHandlerFunction(msg) == (CmiHandlerEx)_processHandler))
594     return 1;
595   if (CmiGetXHandler(msg) == _charmHandlerIdx) return 1;
596   return 0;
597 }
598 #endif
599
600 // return 1 if any one of tracing modules is linked.
601 int  traceAvailable()
602 {
603 #if ! CMK_TRACE_ENABLED
604   return 0;
605 #else
606   return CkpvAccess(_traces)->length()>0;
607 #endif
608 }
609
610 double CmiTraceTimer()
611 {
612   return TraceTimer();
613 }
614
615 void TraceArray::creation(envelope *env, int ep, int num)
616
617     if (_entryTable[ep]->traceEnabled)
618         ALLDO(creation(env, ep, num));
619 }
620
621 void TraceArray::creationMulticast(envelope *env, int ep, int num,
622                                    int *pelist)
623 {
624   if (_entryTable[ep]->traceEnabled)
625     ALLDO(creationMulticast(env, ep, num, pelist));
626 }
627
628 /*
629 extern "C" 
630 void registerFunction(char *name){
631         _TRACE_ONLY(CkpvAccess(_traces)->regFunc(name));
632 }
633 */
634
635 extern "C"
636 int traceRegisterFunction(const char* name, int idx) {
637 #if CMK_TRACE_ENABLED
638   if(idx==-999){
639     CkpvAccess(_traces)->regFunc(name, idx);
640   } else {
641     CkpvAccess(_traces)->regFunc(name, idx, 1);
642   }
643   return idx;
644 #else
645   return 0;
646 #endif
647 }
648
649 extern "C" 
650 void traceBeginFuncProj(char *name,char *file,int line){
651          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(name,file,line));
652 }
653
654 extern "C"
655 void traceBeginFuncIndexProj(int idx,char *file,int line){
656          _TRACE_ONLY(CkpvAccess(_traces)->beginFunc(idx,file,line));
657 }
658
659 extern "C" 
660 void traceEndFuncProj(char *name){
661          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(name));
662 }
663
664 extern "C" 
665 void traceEndFuncIndexProj(int idx){
666          _TRACE_ONLY(CkpvAccess(_traces)->endFunc(idx));
667 }
668
669 #if CMK_SMP_TRACE_COMMTHREAD
670 extern "C"
671 int traceBeginCommOp(char *msg){
672 #if CMK_TRACE_ENABLED
673   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg)) {
674     CkpvAccess(_traces)->beginExecute(msg);
675     return 1;
676   }
677   return 0;
678 #endif
679 }
680
681 extern "C"
682 void traceEndCommOp(char *msg){
683 #if CMK_TRACE_ENABLED
684   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
685     CkpvAccess(_traces)->endExecute(msg);
686 #endif
687 }
688
689 extern "C"
690 void traceSendMsgComm(char *msg){
691 #if CMK_TRACE_ENABLED
692   if (CpvAccess(traceOn) && CkpvAccess(_traces) && CkIsCharmMessage(msg))
693     CkpvAccess(_traces)->creation(msg);
694 #endif
695 }
696 #endif
697
698 extern "C"
699 void traceChangeLastTimestamp(double ts){
700 #if CMK_TRACE_ENABLED
701   if (CpvAccess(traceOn) && CkpvAccess(_traces))
702     CkpvAccess(_traces)->changeLastEntryTimestamp(ts);
703 #endif
704 }
705
706 /*@}*/