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