always define ConverDeliver() function in case it is needed (for example, some part...
[charm.git] / src / ck-core / debug-charm.C
1 /*****************************************************************************
2  * A few useful built-in CPD and CCS handlers.
3  *****************************************************************************/
4
5 #include "converse.h"
6
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/stat.h>           // for chmod
10
11 #include "ckhashtable.h"
12 #include "conv-ccs.h"
13 #include "debug-charm.h"
14 #include "sockRoutines.h"
15 #include "charm.h"
16 #include "middle.h"
17 #include "cklists.h"
18 #include "register.h"
19 //#include "queueing.h"
20 #include <unistd.h>
21
22
23 /** Specify if we are replaying the processor from message logs, thus disable delivering of messages */
24 int _replaySystem = 0;
25
26 #undef ConverseDeliver
27 int ConverseDeliver() {
28   return !_replaySystem;
29 }
30
31 #if CMK_CCS_AVAILABLE && !defined(_WIN32)
32
33 #include "ck.h"
34
35 CkVec<DebugEntryInfo> _debugEntryTable;
36 CpdPersistentChecker persistentCheckerUselessClass;
37
38 void CpdFinishInitialization() {
39 #ifndef CMK_OPTIMIZE
40   _debugEntryTable.resize(_entryTable.size());
41 #endif
42 }
43
44 extern "C" void resetAllCRC();
45 extern "C" void checkAllCRC(int report);
46
47 typedef struct DebugRecursiveEntry {
48   int previousChareID;
49   int alreadyUserCode;
50   char *memoryBackup;
51   void *obj;
52   void *msg;
53 } DebugRecursiveEntry;
54
55 CkQ<DebugRecursiveEntry> _debugData;
56
57 void *CpdGetCurrentObject() { return _debugData.peek().obj; }
58 void *CpdGetCurrentMsg() { return _debugData.peek().msg; }
59
60 extern int cpdInSystem;
61 extern "C" int CpdInUserCode() {return cpdInSystem==0 && _debugData.length()>0 && _debugData.peek().alreadyUserCode==1;}
62
63 // Function called right before an entry method
64 void CpdBeforeEp(int ep, void *obj, void *msg) {
65 #ifndef CMK_OPTIMIZE
66   if (CpvAccess(cmiArgDebugFlag)) {
67     DebugRecursiveEntry entry;
68     entry.previousChareID = setMemoryChareIDFromPtr(obj);
69     entry.alreadyUserCode = _entryTable[ep]->inCharm ? 0 : 1;
70     entry.memoryBackup = NULL;
71     entry.obj = obj;
72     if (msg != NULL) {
73       entry.msg = msg;
74       CmiReference(UsrToEnv(msg));
75     }
76     else entry.msg = NULL;
77     _debugData.push(entry);
78     setMemoryStatus(entry.alreadyUserCode);
79     //if (_debugEntryTable[ep].isBreakpoint) printf("CpdBeforeEp breakpointed %d\n",ep);
80     memoryBackup = &_debugData.peek().memoryBackup;
81     if (!_entryTable[ep]->inCharm) {
82       CpdResetMemory();
83     }
84     CkVec<DebugPersistentCheck> &preExecutes = _debugEntryTable[ep].preProcess;
85     for (int i=0; i<preExecutes.size(); ++i) {
86       preExecutes[i].object->cpdCheck(preExecutes[i].msg);
87     }
88   }
89 #endif
90 }
91
92 // Function called right after an entry method
93 void CpdAfterEp(int ep) {
94 #ifndef CMK_OPTIMIZE
95   if (CpvAccess(cmiArgDebugFlag)) {
96     DebugRecursiveEntry entry = _debugData.peek();
97     CkVec<DebugPersistentCheck> &postExecutes = _debugEntryTable[ep].postProcess;
98     for (int i=0; i<postExecutes.size(); ++i) {
99       postExecutes[i].object->cpdCheck(postExecutes[i].msg);
100     }
101     memoryBackup = &entry.memoryBackup;
102     if (!_entryTable[ep]->inCharm) {
103       CpdCheckMemory();
104     }
105     if (entry.msg != NULL) CmiFree(UsrToEnv(entry.msg));
106     setMemoryChareID(entry.previousChareID);
107     setMemoryStatus(entry.alreadyUserCode);
108     _debugData.deq();
109   }
110 #endif
111 }
112
113 /************ Array Element CPD Lists ****************/
114
115 /**
116   Count array elements going by until they reach this
117   range (lo to hi), then start passing them to dest.
118 */
119 template <class T>
120 class CkArrayElementRangeIterator : public CkLocIterator {
121 private:
122    T *dest;
123    CkArray *mgr;
124    int cur,lo,hi;
125 public:
126    CkArrayElementRangeIterator(T *dest_,int l,int h)
127         :dest(dest_),mgr(0),cur(0),lo(l),hi(h) {}
128
129   /** Called to iterate only on a specific array manager.
130       Returs the number of objects it iterate on.
131   */
132   int iterate(int start, CkArray *m) {
133     cur = start;
134     mgr = m;
135     mgr->getLocMgr()->iterate(*this);
136     cur -= start;
137     return cur;
138   }
139
140    /** Call add for every in-range array element on this processor */
141    void iterate(void)
142    { /* Walk the groupTable for arrays (FIXME: get rid of _groupIDTable) */
143      int numGroups=CkpvAccess(_groupIDTable)->size();
144      for(int i=0;i<numGroups;i++) {
145         IrrGroup *obj = CkpvAccess(_groupTable)->find((*CkpvAccess(_groupIDTable))[i]).getObj();
146         if (obj->isArrMgr())
147         { /* This is an array manager: examine its array elements */
148           mgr=(CkArray *)obj;
149           mgr->getLocMgr()->iterate(*this);
150         }
151      }
152    }
153
154    // Called by location manager's iterate function
155    virtual void addLocation (CkLocation &loc)
156    {
157      if (cur>=lo && cur<hi)
158      { /* This element is in our range-- look it up */
159        dest->add(cur,mgr->lookup(loc.getIndex()),mgr->getGroupID().idx);
160      }
161      cur++;
162    }
163
164    // Return the number of total array elements seen so far.
165    int getCount(void) {return cur;}
166 };
167
168 /**
169   Count charm++ objects going by until they reach this
170   range (lo to hi), then start passing them to dest.
171 */
172 template <class T>
173 class CkObjectRangeIterator {
174 private:
175    T *dest;
176    int cur,lo,hi;
177 public:
178    CkObjectRangeIterator(T *dest_,int l,int h)
179         :dest(dest_),cur(0),lo(l),hi(h) {}
180
181    /** Call add for every in-range array element on this processor */
182    void iterate(void)
183    { /* Walk the groupTable for arrays (FIXME: get rid of _groupIDTable) */
184      int numGroups=CkpvAccess(_groupIDTable)->size();
185      for(int i=0;i<numGroups;i++) {
186        CkGroupID groupID = (*CkpvAccess(_groupIDTable))[i];
187         IrrGroup *obj = CkpvAccess(_groupTable)->find(groupID).getObj();
188         /*if (obj->isArrMgr())
189         { / * This is an array manager: examine its array elements * /
190           CkArray *mgr=(CkArray *)obj;
191           CkArrayElementRangeIterator<T> ait(dest,lo,hi);
192           ait.iterate(cur, mgr);
193           cur+=ait.getCount();
194         } else {*/
195           dest->add(cur,obj,groupID.idx);
196           cur++;
197         //}
198      }
199    }
200
201    // Return the number of total array elements seen so far.
202    int getCount(void) {return cur;}
203 };
204
205 class ignoreAdd {
206 public: void add(int cur,Chare *elt,int group) {}
207 };
208
209 /** Examine all the objects on the server returning the name */
210 class CpdList_objectNames : public CpdListAccessor {
211   PUP::er *pp; // Only used while inside pup routine.
212   int curGroup;
213 public:
214   virtual const char * getPath(void) const {return "charm/objectNames";}
215   virtual size_t getLength(void) const {
216     CkObjectRangeIterator<ignoreAdd> it(0,0,0);
217     it.iterate();
218     return it.getCount();
219   }
220   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
221     pp=&p;
222     CkObjectRangeIterator<CpdList_objectNames> it(this,req.lo,req.hi);
223     it.iterate(); // calls "add" for in-range elements
224   }
225   void add(int cur, Chare *obj, int group) {
226     PUP::er &p=*pp;
227     beginItem(p,cur);
228     p.comment("id");
229     char *n = (char*)malloc(30);
230     int s=obj->ckDebugChareID(n, 30);
231     CkAssert(s > 0);
232     p(n,s);
233     free(n);
234     PUPn(group);
235     p.comment("name");
236     n=obj->ckDebugChareName();
237     p(n,strlen(n));
238     free(n);
239   }
240 };
241
242 /** Examine a single object identified by the id passed in the request and
243     return its type and memory data */
244 class CpdList_object : public CpdListAccessor {
245   PUP::er *pp; //Only used while inside pup routine.
246   CpdListItemsRequest *reqq; // Only used while inside pup routine.
247 public:
248   virtual const char * getPath(void) const {return "charm/object";}
249   virtual size_t getLength(void) const {
250     CkObjectRangeIterator<ignoreAdd> it(0,0,0);
251     it.iterate();
252     return it.getCount();
253   }
254   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
255     pp=&p;
256     reqq=&req;
257     CkObjectRangeIterator<CpdList_object> it(this,req.lo,req.hi);
258     it.iterate(); // calls "add" for in-range elements;
259   }
260   void add(int cur, Chare *obj, int group) {
261     PUP::er &p=*pp;
262     CpdListItemsRequest &req=*reqq;
263     char *n = (char *)malloc(30);
264     int s=obj->ckDebugChareID(n, 30);
265     CkAssert(s > 0);
266     if (req.extraLen == s && memcmp(req.extra, n, s) == 0) {
267       // the object match, found!
268       beginItem(p,cur);
269       int type = obj->ckGetChareType();
270       p.comment("type");
271       const char *t = _chareTable[type]->name;
272       p((char*)t,strlen(t));
273       p.comment("value");
274       int size = _chareTable[type]->size;
275       p((char*)obj,size);
276     }
277   }
278 };
279
280 /** Coarse: examine array element names */
281 class CpdList_arrayElementNames : public CpdListAccessor {
282   PUP::er *pp; // Only used while inside pup routine.
283 public:
284   virtual const char * getPath(void) const {return "charm/arrayElementNames";}
285   virtual size_t getLength(void) const {
286     CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
287     it.iterate();
288     return it.getCount();
289   }
290   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
291     pp=&p;
292     CkArrayElementRangeIterator<CpdList_arrayElementNames> it(this,req.lo,req.hi);
293     it.iterate(); // calls "add" for in-range elements
294   }
295   void add(int cur,Chare *e,int group)
296   { // Just grab the name and nothing else:
297     ArrayElement *elt = (ArrayElement*)e;
298          PUP::er &p=*pp;
299          beginItem(p,cur);
300          p.comment("name");
301          char *n=elt->ckDebugChareName();
302          p(n,strlen(n));
303          free(n);
304   }
305 };
306
307 /** Detailed: examine array element data */
308 class CpdList_arrayElements : public CpdListAccessor {
309   PUP::er *pp; // Only used while inside pup routine.
310 public:
311   virtual const char * getPath(void) const {return "charm/arrayElements";}
312   virtual size_t getLength(void) const {
313     CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
314     it.iterate();
315     return it.getCount();
316   }
317   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
318     pp=&p;
319     CkArrayElementRangeIterator<CpdList_arrayElements> it(this,req.lo,req.hi);
320     it.iterate(); // calls "add" for in-range elements
321   }
322   void add(int cur, Chare *e, int group)
323   { // Pup the element data
324     ArrayElement *elt = (ArrayElement*)e;
325     PUP::er &p=*pp;
326     beginItem(p,cur);
327     //elt->ckDebugPup(p);
328     // Now ignore any pupper, just copy all the memory as raw data
329     p.comment("name");
330     char *n=elt->ckDebugChareName();
331     p(n,strlen(n));
332     free(n);
333     int type = elt->ckGetChareType();
334     p.comment("type");
335     const char *t = _chareTable[type]->name;
336     p((char*)t,strlen(t));
337     p.comment("value");
338     int size = _chareTable[type]->size;
339     p((char*)elt,size);
340   }
341 };
342
343 #ifndef __CYGWIN__
344 #include <rpc/rpc.h>
345 #endif
346
347 size_t hostInfoLength(void *) {return 1;}
348
349 void hostInfo(void *itemIter, pup_er pp, CpdListItemsRequest *req) {
350   PUP::er &p = *(PUP::er *)pp;
351   struct sockaddr_in addr;
352   CpdListBeginItem(pp, 0);
353 #if CMK_HAS_GET_MYADDRESS
354   get_myaddress(&addr);
355 #else
356   CmiAbort("hostInfo: get_myaddress does not work on this machine");
357 #endif
358   char *address = (char*)&addr.sin_addr.s_addr;
359   PUPv(address, 4);
360   int pid = getpid();
361   PUPn(pid);
362 }
363
364 /************ Message CPD Lists ****************/
365 CpvCExtern(void *,debugQueue);
366 CpvCExtern(int, skipBreakpoint);
367
368 // Interpret data in a message in a user-friendly way.
369 //  Ignores most of the envelope fields used by CkPupMessage,
370 //  and instead concentrates on user data
371 void CpdPupMessage(PUP::er &p, void *msg)
372 {
373   envelope *env=UsrToEnv(msg);
374   //int wasPacked=env->isPacked();
375   int size=env->getTotalsize();
376   int prioBits=env->getPriobits();
377   int from=env->getSrcPe();
378   PUPn(from);
379   //PUPn(wasPacked);
380   PUPn(prioBits);
381   int userSize=size-sizeof(envelope)-sizeof(int)*CkPriobitsToInts(prioBits);
382   PUPn(userSize);
383   int msgType = env->getMsgIdx();
384   PUPn(msgType);
385   int envType = env->getMsgtype();
386   PUPn(envType);
387
388   //p.synchronize(PUP::sync_last_system);
389
390   int ep=CkMessageToEpIdx(msg);
391   PUPn(ep);
392
393   // Pup the information specific to this envelope type
394   if (envType == ForArrayEltMsg || envType == ArrayEltInitMsg) {
395     int arrID = env->getsetArrayMgr().idx;
396     PUPn(arrID);
397     CkArrayIndexStruct &idx = *(CkArrayIndexStruct *)&env->getsetArrayIndex();
398     int nInts = idx.nInts;
399     int dimension = idx.dimension;
400     PUPn(nInts);
401     PUPn(dimension);
402     p.comment("index");
403     if (dimension >=4 && dimension <=6) {
404       p((short int *)idx.index, dimension);
405     } else {
406       p(idx.index, nInts);
407     }
408   } else if (envType == BocInitMsg || envType == NodeBocInitMsg ||
409              envType == ForNodeBocMsg || envType == ForBocMsg) {
410     int groupID = env->getGroupNum().idx;
411     PUPn(groupID);
412   } else if (envType == NewVChareMsg || envType == ForVidMsg || envType == FillVidMsg) {
413     p.comment("ptr");
414     void *ptr = env->getVidPtr();
415     pup_pointer(&p, &ptr);
416   } else if (envType == ForChareMsg) {
417     p.comment("ptr");
418     void *ptr = env->getObjPtr();
419     pup_pointer(&p, &ptr);
420   }
421   
422   /* user data */
423   p.comment("data");
424   p.synchronize(PUP::sync_begin_object);
425   if (_entryTable[ep]->messagePup!=NULL)
426     _entryTable[ep]->messagePup(p,msg);
427   else
428     CkMessage::ckDebugPup(p,msg);
429   p.synchronize(PUP::sync_end_object);
430 }
431
432 CpvStaticDeclare(void *, lastBreakPointMsg);
433
434 //Cpd Lists for local and scheduler queues
435 class CpdList_localQ : public CpdListAccessor {
436
437 public:
438   CpdList_localQ() {}
439   virtual const char * getPath(void) const {return "converse/localqueue";}
440   virtual size_t getLength(void) const {
441     int x = CdsFifo_Length((CdsFifo)(CpvAccess(debugQueue)));
442     //CmiPrintf("*******Returning fifo length %d*********\n", x);
443     //return CdsFifo_Length((CdsFifo)(CpvAccess(CmiLocalQueue)));
444     if (CpvAccess(lastBreakPointMsg) != NULL) x++;
445     return x;
446   }
447   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
448     int length = CdsFifo_Length((CdsFifo)(CpvAccess(debugQueue)));
449     void ** messages = CdsFifo_Enumerate(CpvAccess(debugQueue));
450     int curObj=0;
451
452     if (CpvAccess(lastBreakPointMsg) != NULL) {
453       beginItem(p, -1);
454       envelope *env=(envelope *)UsrToEnv(CpvAccess(lastBreakPointMsg));
455       p.comment("name");
456       char *type=(char*)"Breakpoint";
457       p(type,strlen(type));
458       p.comment("charmMsg");
459       p.synchronize(PUP::sync_begin_object);
460       CkUnpackMessage(&env);
461       CpdPupMessage(p, EnvToUsr(env));
462       p.synchronize(PUP::sync_end_object);
463     }
464
465     for(curObj=req.lo; curObj<req.hi; curObj++)
466       if ((curObj>=0) && (curObj<length))
467       {
468         beginItem(p,curObj);
469         void *msg=messages[curObj]; /* converse message */
470         int isCharm=0;
471         const char *type="Converse";
472         p.comment("name");
473         char name[128];
474         if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";}
475         if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";}
476         sprintf(name,"%s %d: %s (%d)","Message",curObj,type,CmiGetHandler(msg));
477         p(name, strlen(name));
478
479         if (isCharm)
480         { /* charm message */
481           p.comment("charmMsg");
482           p.synchronize(PUP::sync_begin_object);
483           envelope *env=(envelope *)msg;
484           CkUnpackMessage(&env);
485           messages[curObj]=env;
486           CpdPupMessage(p, EnvToUsr(env));
487           //CkPupMessage(p, &messages[curObj], 0);
488           p.synchronize(PUP::sync_end_object);
489         }
490       }
491     delete[] messages;
492
493   }
494 };
495
496 class CpdList_message : public CpdListAccessor {
497   virtual const char * getPath(void) const {return "converse/message";}
498   virtual size_t getLength(void) const {return 1;}
499   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
500     envelope *env = (envelope*)(((unsigned int)req.lo) + (((unsigned long)req.hi)<<32)+sizeof(CmiChunkHeader));
501     beginItem(p, 0);
502     const char *type="Converse";
503     p.comment("name");
504     char name[128];
505     if (CmiGetHandler(env)==_charmHandlerIdx) {type="Local Charm";}
506     if (CmiGetXHandler(env)==_charmHandlerIdx) {type="Network Charm";}
507     sprintf(name,"%s 0: %s (%d)","Message",type,CmiGetHandler(env));
508     p(name, strlen(name));
509     p.comment("charmMsg");
510     p.synchronize(PUP::sync_begin_object);
511     CpdPupMessage(p, EnvToUsr(env));
512     p.synchronize(PUP::sync_end_object);
513   }
514 };
515
516 class CpdList_msgStack : public CpdListAccessor {
517   virtual const char * getPath(void) const {return "charm/messageStack";}
518   virtual size_t getLength(void) const {
519     return _debugData.length();
520   }
521   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
522     for (int i=0; i<_debugData.length(); ++i) {
523       beginItem(p, i);
524       void *obj = _debugData[i].obj;
525       p.comment("obj");
526       pup_pointer(&p, &obj);
527       void *msg = _debugData[i].msg;
528       p.comment("msg");
529       pup_pointer(&p, &msg);
530     }
531   }
532 };
533
534 /****************** Breakpoints and other debug support **************/
535
536 typedef CkHashtableTslow<int,EntryInfo *> CpdBpFuncTable_t;
537
538
539 extern void CpdFreeze(void);
540 extern void CpdUnFreeze(void);
541 extern int  CpdIsFrozen(void);
542
543 CpvStaticDeclare(int, _debugMsg);
544 CpvStaticDeclare(int, _debugChare);
545
546 CpvStaticDeclare(CpdBpFuncTable_t *, breakPointEntryTable);
547
548 //CpvStaticDeclare(void *, lastBreakPointMsg);
549 CpvStaticDeclare(void *, lastBreakPointObject);
550 CpvStaticDeclare(int, lastBreakPointIndex);
551
552 void CpdBreakPointInit()
553 {
554   CpvInitialize(void *, lastBreakPointMsg);
555   CpvInitialize(void *, lastBreakPointObject);
556   CpvInitialize(int, lastBreakPointIndex);
557   CpvInitialize(int, _debugMsg);
558   CpvInitialize(int, _debugChare);
559   CpvInitialize(CpdBpFuncTable_t *, breakPointEntryTable);
560   CpvAccess(lastBreakPointMsg) = NULL;
561   CpvAccess(lastBreakPointObject) = NULL;
562   CpvAccess(lastBreakPointIndex) = 0;
563   CpvAccess(_debugMsg) = CkRegisterMsg("debug_msg",0,0,0,0);
564   CpvAccess(_debugChare) = CkRegisterChare("debug_Chare",0,TypeChare);
565   CkRegisterChareInCharm(CpvAccess(_debugChare));
566   CpvAccess(breakPointEntryTable) = new CpdBpFuncTable_t(10,0.5,CkHashFunction_int,CkHashCompare_int );
567 }
568
569
570
571 static void _call_freeze_on_break_point(void * msg, void * object)
572 {
573       //Save breakpoint entry point index. This is retrieved from msg.
574       //So that the appropriate EntryInfo can be later retrieved from the hash table
575       //of break point function entries, on continue.
576
577   // If the counter "skipBreakpoint" is not zero we actually do not freeze and deliver the regular message
578   if (CpvAccess(skipBreakpoint) > 0) {
579     EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkMessageToEpIdx(msg));
580     CkAssert(breakPointEntryInfo != NULL);
581     breakPointEntryInfo->call(msg, object);
582     CpvAccess(skipBreakpoint) --;
583   } else {
584       CpvAccess(lastBreakPointMsg) = msg;
585       CpvAccess(lastBreakPointObject) = object;
586       CpvAccess(lastBreakPointIndex) = CkMessageToEpIdx(msg);
587       EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
588       CpdNotify(CPD_BREAKPOINT,breakPointEntryInfo->name);
589       CpdFreeze();
590   }
591 }
592
593 //ccs handler when pressed the "next" command: deliver only a single message without unfreezing
594 extern "C"
595 void CpdDeliverSingleMessage () {
596   if (!CpdIsFrozen()) return; /* Do something only if we are in freeze mode */
597   if ( (CpvAccess(lastBreakPointMsg) != NULL) && (CpvAccess(lastBreakPointObject) != NULL) ) {
598     EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
599     if (breakPointEntryInfo != NULL) {
600       breakPointEntryInfo->call(CpvAccess(lastBreakPointMsg), CpvAccess(lastBreakPointObject));
601     }
602     CpvAccess(lastBreakPointMsg) = NULL;
603     CpvAccess(lastBreakPointObject) = NULL;
604   }
605   else {
606     // we were not stopped at a breakpoint, then deliver the first message in the debug queue
607     if (!CdsFifo_Empty(CpvAccess(debugQueue))) {
608       CpvAccess(skipBreakpoint) = 1;
609       char *queuedMsg = (char *)CdsFifo_Dequeue(CpvAccess(debugQueue));
610       CmiHandleMessage(queuedMsg);
611       CpvAccess(skipBreakpoint) = 0;
612     }
613   }
614 }
615
616 //ccs handler when continue from a break point
617 extern "C"
618 void CpdContinueFromBreakPoint ()
619 {
620     CpdUnFreeze();
621     if ( (CpvAccess(lastBreakPointMsg) != NULL) && (CpvAccess(lastBreakPointObject) != NULL) )
622     {
623         EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
624         if (breakPointEntryInfo != NULL) {
625            breakPointEntryInfo->call(CpvAccess(lastBreakPointMsg), CpvAccess(lastBreakPointObject));
626         } else {
627           // This means that the breakpoint got deleted in the meanwhile
628           
629         }
630     }
631     CpvAccess(lastBreakPointMsg) = NULL;
632     CpvAccess(lastBreakPointObject) = NULL;
633 }
634
635 //ccs handler to set a breakpoint with entry function name msg
636 void CpdSetBreakPoint (char *msg)
637 {
638   char functionName[128];
639   int tableSize, tableIdx = 0;
640   int reply = 0;
641   sscanf(msg+CmiMsgHeaderSizeBytes, "%s", functionName);
642   if (strlen(functionName) > 0)
643   {
644     tableSize = _entryTable.size();
645     // Replace entry in entry table with _call_freeze_on_break_point
646     // retrieve epIdx for entry method
647     //for (tableIdx=0; tableIdx < tableSize; tableIdx++)
648     //{
649        //if (strstr(_entryTable[tableIdx]->name, functionName) != NULL)
650        //{
651     tableIdx = atoi(functionName);
652     if (tableIdx >= 0 && tableIdx < tableSize) {
653            EntryInfo * breakPointEntryInfo = (EntryInfo *)CpvAccess(breakPointEntryTable)->get(tableIdx);
654            delete breakPointEntryInfo;
655            breakPointEntryInfo = new EntryInfo(_entryTable[tableIdx]->name, _entryTable[tableIdx]->call, _entryTable[tableIdx]->msgIdx, _entryTable[tableIdx]->chareIdx );
656            //CmiPrintf("Breakpoint is set for function %s with an epIdx = %ld\n", _entryTable[tableIdx]->name, tableIdx);
657            CpvAccess(breakPointEntryTable)->put(tableIdx) = breakPointEntryInfo;
658            _entryTable[tableIdx]->name = "debug_breakpoint_ep";
659            _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
660            //_entryTable[tableIdx]->msgIdx = CpvAccess(_debugMsg);
661            //_entryTable[tableIdx]->chareIdx = CpvAccess(_debugChare);
662            //_debugEntryTable[tableIdx].isBreakpoint = CmiTrue;
663            //break;
664            reply = ~0;
665            //}
666     }
667     //if (tableIdx == tableSize)
668     //{
669     //  CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName);
670     //  return;
671     //}
672
673   }
674   CcsSendReply(sizeof(int), (void*)&reply);
675
676 }
677
678 void CpdQuitDebug()
679 {
680   CpdContinueFromBreakPoint();
681   CkExit();
682 }
683
684 void CpdRemoveBreakPoint (char *msg)
685 {
686   char functionName[128];
687   int reply = 0;
688   sscanf(msg+CmiMsgHeaderSizeBytes, "%s", functionName);
689   if (strlen(functionName) > 0) {
690     int idx = atoi(functionName);
691     if (idx >= 0 && idx < _entryTable.size()) {
692       //CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName);
693       //void *objPointer;
694       //void *keyPointer;
695       //CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
696       //while(NULL!=(objPointer = it->next(&keyPointer)))
697       //{
698       //EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
699       EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(idx);
700       if (breakPointEntryInfo != NULL) {
701         _entryTable[idx]->name =  breakPointEntryInfo->name;
702         _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
703         _entryTable[idx]->msgIdx = breakPointEntryInfo->msgIdx;
704         _entryTable[idx]->chareIdx = breakPointEntryInfo->chareIdx;
705         reply = ~0 ;
706         //_debugEntryTable[idx].isBreakpoint = CmiFalse;
707         //CmiPrintf("Breakpoint is removed for function %s with epIdx %ld\n", _entryTable[idx]->name, idx);
708         //CpvAccess(breakPointEntryTable)->remove(idx);
709       }
710     }
711   }
712   CcsSendReply(sizeof(int), (void*)&reply);
713 }
714
715 void CpdRemoveAllBreakPoints ()
716 {
717   //all breakpoints removed
718   void *objPointer;
719   void *keyPointer;
720   int reply = 1;
721   CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
722   while(NULL!=(objPointer = it->next(&keyPointer)))
723   {
724     EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
725     int idx = *(int *)keyPointer;
726     _entryTable[idx]->name =  breakPointEntryInfo->name;
727     _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
728     _entryTable[idx]->msgIdx = breakPointEntryInfo->msgIdx;
729     _entryTable[idx]->chareIdx = breakPointEntryInfo->chareIdx;
730   }
731   CcsSendReply(sizeof(int), (void*)&reply);
732 }
733
734 extern "C" int CpdIsCharmDebugMessage(void *msg) {
735   envelope *env = (envelope*)msg;
736   // Later should use "isDebug" value, but for now just bypass all intrinsic EPs
737   return CmiGetHandler(msg) != _charmHandlerIdx || env->getMsgtype() == ForVidMsg ||
738          env->getMsgtype() == FillVidMsg || _entryTable[env->getEpIdx()]->inCharm;
739 }
740
741
742
743 CpvExtern(char *, displayArgument);
744
745 void CpdStartGdb(void)
746 {
747 #if !defined(_WIN32) || defined(__CYGWIN__)
748   FILE *f;
749   char gdbScript[200];
750   int pid;
751   if (CpvAccess(displayArgument) != NULL)
752   {
753      /*CmiPrintf("MY NODE IS %d  and process id is %d\n", CmiMyPe(), getpid());*/
754      sprintf(gdbScript, "/tmp/cpdstartgdb.%d.%d", getpid(), CmiMyPe());
755      f = fopen(gdbScript, "w");
756      fprintf(f,"#!/bin/sh\n");
757      fprintf(f,"cat > /tmp/start_gdb.$$ << END_OF_SCRIPT\n");
758      fprintf(f,"shell /bin/rm -f /tmp/start_gdb.$$\n");
759      //fprintf(f,"handle SIGPIPE nostop noprint\n");
760      fprintf(f,"handle SIGWINCH nostop noprint\n");
761      fprintf(f,"handle SIGWAITING nostop noprint\n");
762      fprintf(f, "attach %d\n", getpid());
763      fprintf(f,"END_OF_SCRIPT\n");
764      fprintf(f, "DISPLAY='%s';export DISPLAY\n",CpvAccess(displayArgument));
765      fprintf(f,"/usr/X11R6/bin/xterm ");
766      fprintf(f," -title 'Node %d ' ",CmiMyPe());
767      fprintf(f," -e /usr/bin/gdb -x /tmp/start_gdb.$$ \n");
768      fprintf(f, "exit 0\n");
769      fclose(f);
770      if( -1 == chmod(gdbScript, 0755))
771      {
772         CmiPrintf("ERROR> chmod on script failed!\n");
773         return;
774      }
775      pid = fork();
776      if (pid < 0)
777         { perror("ERROR> forking to run debugger script\n"); exit(1); }
778      if (pid == 0)
779      {
780          //CmiPrintf("In child process to start script %s\n", gdbScript);
781  if (-1 == execvp(gdbScript, NULL))
782             CmiPrintf ("Error> Could not Execute Debugger Script: %s\n",strerror
783 (errno));
784
785       }
786     }
787 #endif
788 }
789
790 extern "C" {
791   size_t cpd_memory_length(void*);
792   void cpd_memory_pup(void*,void*,CpdListItemsRequest*);
793   void cpd_memory_leak(void*,void*,CpdListItemsRequest*);
794   size_t cpd_memory_getLength(void*);
795   void cpd_memory_get(void*,void*,CpdListItemsRequest*);
796 }
797
798
799 void CpdCharmInit()
800 {
801   CpdListRegister(new CpdListAccessor_c("converse/memory",cpd_memory_length,0,cpd_memory_pup,0));
802   //CpdListRegister(new CpdListAccessor_c("converse/memory/leak",cpd_memory_length,0,cpd_memory_leak,0));
803   CpdListRegister(new CpdListAccessor_c("converse/memory/data",cpd_memory_getLength,0,cpd_memory_get,0,false));
804
805   CpdBreakPointInit();
806   CcsRegisterHandler("ccs_set_break_point",(CmiHandler)CpdSetBreakPoint);
807   CcsSetMergeFn("ccs_set_break_point",CcsMerge_logical_and);
808   CcsRegisterHandler("ccs_remove_break_point",(CmiHandler)CpdRemoveBreakPoint);
809   CcsSetMergeFn("ccs_remove_break_point",CcsMerge_logical_and);
810   CcsRegisterHandler("ccs_remove_all_break_points",(CmiHandler)CpdRemoveAllBreakPoints);
811   CcsSetMergeFn("ccs_remove_all_break_points",CmiReduceMergeFn_random);
812   CcsRegisterHandler("ccs_continue_break_point",(CmiHandler)CpdContinueFromBreakPoint);
813   CcsRegisterHandler("ccs_single_step",(CmiHandler)CpdDeliverSingleMessage);
814   CcsRegisterHandler("ccs_debug_quit",(CmiHandler)CpdQuitDebug);
815   CcsRegisterHandler("ccs_debug_startgdb",(CmiHandler)CpdStartGdb);
816   CpdListRegister(new CpdListAccessor_c("hostinfo",hostInfoLength,0,hostInfo,0));
817   CpdListRegister(new CpdList_localQ());
818   CpdListRegister(new CpdList_arrayElementNames());
819   CpdListRegister(new CpdList_arrayElements());
820   CpdListRegister(new CpdList_objectNames());
821   CpdListRegister(new CpdList_object());
822   CpdListRegister(new CpdList_message());
823   CpdListRegister(new CpdList_msgStack());
824   CpdIsDebugMessage = CpdIsCharmDebugMessage;
825 }
826
827 #else
828
829 void CpdCharmInit() {}
830
831 void CpdFinishInitialization() {}
832
833 void *CpdGetCurrentObject() {return NULL;}
834 void *CpdGetCurrentMsg() {return NULL;}
835
836 void CpdBeforeEp(int ep, void *obj, void *msg) {}
837 void CpdAfterEp(int ep) {}
838
839 #endif /*CMK_CCS_AVAILABLE*/