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