1 /*****************************************************************************
2 * A few useful built-in CPD and CCS handlers.
3 *****************************************************************************/
9 #include <sys/stat.h> // for chmod
11 #include "ckhashtable.h"
13 #include "debug-charm.h"
14 #include "sockRoutines.h"
19 //#include "queueing.h"
23 #include "blue_impl.h"
27 #if CMK_CHARMDEBUG && CMK_CCS_AVAILABLE && !defined(_WIN32)
31 CkpvDeclare(int, skipBreakpoint); /* This is a counter of how many breakpoints we should skip */
32 CkpvDeclare(DebugEntryTable, _debugEntryTable);
33 CpdPersistentChecker persistentCheckerUselessClass;
35 void CpdFinishInitialization() {
36 CkpvInitialize(int, skipBreakpoint);
37 CkpvAccess(skipBreakpoint) = 0;
38 CkpvInitialize(DebugEntryTable, _debugEntryTable);
39 CkpvAccess(_debugEntryTable).resize(_entryTable.size());
42 extern "C" void resetAllCRC();
43 extern "C" void checkAllCRC(int report);
45 typedef struct DebugRecursiveEntry {
51 } DebugRecursiveEntry;
53 CkQ<DebugRecursiveEntry> _debugData;
55 void *CpdGetCurrentObject() { return _debugData.peek().obj; }
56 void *CpdGetCurrentMsg() { return _debugData.peek().msg; }
58 extern int cpdInSystem;
59 extern "C" int CpdInUserCode() {return cpdInSystem==0 && _debugData.length()>0 && _debugData.peek().alreadyUserCode==1;}
61 // Function called right before an entry method
62 void CpdBeforeEp(int ep, void *obj, void *msg) {
64 if (CpvAccess(cmiArgDebugFlag)) {
65 DebugRecursiveEntry entry;
66 entry.previousChareID = setMemoryChareIDFromPtr(obj);
67 entry.alreadyUserCode = _entryTable[ep]->inCharm ? 0 : 1;
68 entry.memoryBackup = NULL;
72 CmiReference(UsrToEnv(msg));
74 else entry.msg = NULL;
75 _debugData.push(entry);
76 setMemoryStatus(entry.alreadyUserCode);
77 //if (CkpvAccess(_debugEntryTable)[ep].isBreakpoint) printf("CpdBeforeEp breakpointed %d\n",ep);
78 memoryBackup = &_debugData.peek().memoryBackup;
79 if (!_entryTable[ep]->inCharm) {
83 CkVec<DebugPersistentCheck> &preExecutes = CkpvAccess(_debugEntryTable)[ep].preProcess;
84 for (int i=0; i<preExecutes.size(); ++i) {
85 preExecutes[i].object->cpdCheck(preExecutes[i].msg);
91 // Function called right after an entry method
92 void CpdAfterEp(int ep) {
94 if (CpvAccess(cmiArgDebugFlag)) {
95 DebugRecursiveEntry entry = _debugData.peek();
96 CkVec<DebugPersistentCheck> &postExecutes = CkpvAccess(_debugEntryTable)[ep].postProcess;
97 for (int i=0; i<postExecutes.size(); ++i) {
98 postExecutes[i].object->cpdCheck(postExecutes[i].msg);
100 memoryBackup = &entry.memoryBackup;
101 if (!_entryTable[ep]->inCharm) {
105 if (entry.msg != NULL) CmiFree(UsrToEnv(entry.msg));
106 setMemoryChareID(entry.previousChareID);
107 setMemoryStatus(entry.alreadyUserCode);
113 /************ Array Element CPD Lists ****************/
116 Count array elements going by until they reach this
117 range (lo to hi), then start passing them to dest.
120 class CkArrayElementRangeIterator : public CkLocIterator {
126 CkArrayElementRangeIterator(T *dest_,int l,int h)
127 :dest(dest_),mgr(0),cur(0),lo(l),hi(h) {}
129 /** Called to iterate only on a specific array manager.
130 Returs the number of objects it iterate on.
132 int iterate(int start, CkArray *m) {
135 mgr->getLocMgr()->iterate(*this);
140 /** Call add for every in-range array element on this processor */
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();
147 { /* This is an array manager: examine its array elements */
149 mgr->getLocMgr()->iterate(*this);
154 // Called by location manager's iterate function
155 virtual void addLocation (CkLocation &loc)
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);
164 // Return the number of total array elements seen so far.
165 int getCount(void) {return cur;}
169 Count charm++ objects going by until they reach this
170 range (lo to hi), then start passing them to dest.
173 class CkObjectRangeIterator {
178 CkObjectRangeIterator(T *dest_,int l,int h)
179 :dest(dest_),cur(0),lo(l),hi(h) {}
181 /** Call add for every in-range array element on this processor */
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);
195 dest->add(cur,obj,groupID.idx);
201 // Return the number of total array elements seen so far.
202 int getCount(void) {return cur;}
206 public: void add(int cur,Chare *elt,int group) {}
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.
214 virtual const char * getPath(void) const {return "charm/objectNames";}
215 virtual size_t getLength(void) const {
216 CkObjectRangeIterator<ignoreAdd> it(0,0,0);
218 return it.getCount();
220 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
222 CkObjectRangeIterator<CpdList_objectNames> it(this,req.lo,req.hi);
223 it.iterate(); // calls "add" for in-range elements
225 void add(int cur, Chare *obj, int group) {
229 char *n = (char*)malloc(30);
230 int s=obj->ckDebugChareID(n, 30);
236 n=obj->ckDebugChareName();
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.
248 virtual const char * getPath(void) const {return "charm/object";}
249 virtual size_t getLength(void) const {
250 CkObjectRangeIterator<ignoreAdd> it(0,0,0);
252 return it.getCount();
254 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
257 CkObjectRangeIterator<CpdList_object> it(this,req.lo,req.hi);
258 it.iterate(); // calls "add" for in-range elements;
260 void add(int cur, Chare *obj, int group) {
262 CpdListItemsRequest &req=*reqq;
263 char *n = (char *)malloc(30);
264 int s=obj->ckDebugChareID(n, 30);
266 if (req.extraLen == s && memcmp(req.extra, n, s) == 0) {
267 // the object match, found!
269 int type = obj->ckGetChareType();
271 const char *t = _chareTable[type]->name;
272 p((char*)t,strlen(t));
274 int size = _chareTable[type]->size;
280 /** Coarse: examine array element names */
281 class CpdList_arrayElementNames : public CpdListAccessor {
282 PUP::er *pp; // Only used while inside pup routine.
284 virtual const char * getPath(void) const {return "charm/arrayElementNames";}
285 virtual size_t getLength(void) const {
286 CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
288 return it.getCount();
290 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
292 CkArrayElementRangeIterator<CpdList_arrayElementNames> it(this,req.lo,req.hi);
293 it.iterate(); // calls "add" for in-range elements
295 void add(int cur,Chare *e,int group)
296 { // Just grab the name and nothing else:
297 ArrayElement *elt = (ArrayElement*)e;
301 char *n=elt->ckDebugChareName();
307 /** Detailed: examine array element data */
308 class CpdList_arrayElements : public CpdListAccessor {
309 PUP::er *pp; // Only used while inside pup routine.
311 virtual const char * getPath(void) const {return "charm/arrayElements";}
312 virtual size_t getLength(void) const {
313 CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
315 return it.getCount();
317 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
319 CkArrayElementRangeIterator<CpdList_arrayElements> it(this,req.lo,req.hi);
320 it.iterate(); // calls "add" for in-range elements
322 void add(int cur, Chare *e, int group)
323 { // Pup the element data
324 ArrayElement *elt = (ArrayElement*)e;
327 //elt->ckDebugPup(p);
328 // Now ignore any pupper, just copy all the memory as raw data
330 char *n=elt->ckDebugChareName();
333 int type = elt->ckGetChareType();
335 const char *t = _chareTable[type]->name;
336 p((char*)t,strlen(t));
338 int size = _chareTable[type]->size;
347 size_t hostInfoLength(void *) {return 1;}
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);
356 CmiAbort("hostInfo: get_myaddress does not work on this machine");
358 char *address = (char*)&addr.sin_addr.s_addr;
364 /************ Message CPD Lists ****************/
365 CkpvExtern(void *,debugQueue);
367 // Interpret data in a message in a user-friendly way.
368 // Ignores most of the envelope fields used by CkPupMessage,
369 // and instead concentrates on user data
370 void CpdPupMessage(PUP::er &p, void *msg)
372 envelope *env=UsrToEnv(msg);
373 //int wasPacked=env->isPacked();
374 int size=env->getTotalsize();
375 int prioBits=env->getPriobits();
376 int from=env->getSrcPe();
380 int userSize=size-sizeof(envelope)-sizeof(int)*CkPriobitsToInts(prioBits);
382 int msgType = env->getMsgIdx();
384 int envType = env->getMsgtype();
387 //p.synchronize(PUP::sync_last_system);
389 int ep=CkMessageToEpIdx(msg);
392 // Pup the information specific to this envelope type
393 if (envType == ForArrayEltMsg || envType == ArrayEltInitMsg) {
394 int arrID = env->getArrayMgr().idx;
396 CkArrayIndex &idx = env->getsetArrayIndex();
397 int nInts = idx.nInts;
398 int dimension = idx.dimension;
402 if (dimension >=4 && dimension <=6) {
403 p((short int *)idx.index, dimension);
407 } else if (envType == ForNodeBocMsg || envType == ForBocMsg) {
408 int groupID = env->getGroupNum().idx;
410 } else if (envType == BocInitMsg || envType == NodeBocInitMsg) {
411 int groupID = env->getGroupNum().idx;
413 } else if (envType == NewVChareMsg || envType == ForVidMsg || envType == FillVidMsg) {
415 void *ptr = env->getVidPtr();
416 pup_pointer(&p, &ptr);
417 } else if (envType == ForChareMsg) {
419 void *ptr = env->getObjPtr();
420 pup_pointer(&p, &ptr);
425 p.synchronize(PUP::sync_begin_object);
426 if (_entryTable[ep]->messagePup!=NULL)
427 _entryTable[ep]->messagePup(p,msg);
429 CkMessage::ckDebugPup(p,msg);
430 p.synchronize(PUP::sync_end_object);
433 struct ConditionalList {
438 CkpvStaticDeclare(void *, lastBreakPointMsg);
439 CpvExtern(void*, conditionalQueue);
440 ConditionalList * conditionalShm = NULL;
442 //Cpd Lists for local and scheduler queues
443 class CpdList_localQ : public CpdListAccessor {
447 virtual const char * getPath(void) const {return "converse/localqueue";}
448 virtual size_t getLength(void) const {
449 int x = CdsFifo_Length((CdsFifo)(CkpvAccess(debugQueue)));
450 //CmiPrintf("*******Returning fifo length %d*********\n", x);
451 //return CdsFifo_Length((CdsFifo)(CpvAccess(CmiLocalQueue)));
452 if (CkpvAccess(lastBreakPointMsg) != NULL) x++;
455 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
461 length = CdsFifo_Length((CdsFifo)(CpvAccess(conditionalQueue)));
462 messages = CdsFifo_Enumerate(CpvAccess(conditionalQueue));
463 for (curObj=-length; curObj<0; curObj++) {
464 void *msg = messages[length+curObj];
465 pupSingleMessage(p, curObj-1, msg);
470 length = CdsFifo_Length((CdsFifo)(CkpvAccess(debugQueue)));
471 messages = CdsFifo_Enumerate(CkpvAccess(debugQueue));
473 if (CkpvAccess(lastBreakPointMsg) != NULL) {
475 envelope *env=(envelope *)UsrToEnv(CkpvAccess(lastBreakPointMsg));
477 char *type=(char*)"Breakpoint";
478 p(type,strlen(type));
479 p.comment("charmMsg");
480 p.synchronize(PUP::sync_begin_object);
481 CkUnpackMessage(&env);
482 CpdPupMessage(p, EnvToUsr(env));
483 p.synchronize(PUP::sync_end_object);
486 for(curObj=req.lo; curObj<req.hi; curObj++)
487 if ((curObj>=0) && (curObj<length))
489 void *msg=messages[curObj]; /* converse message */
490 pupSingleMessage(p, curObj, msg);
496 void pupSingleMessage(PUP::er &p, int curObj, void *msg) {
499 const char *type="Converse";
502 if (msg == (void*)-1) {
504 p((char*)type, strlen(type));
507 #if ! CMK_BIGSIM_CHARM
508 if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";}
509 if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";}
511 isCharm=1; type="BG";
513 if (curObj < 0) type="Conditional";
514 sprintf(name,"%s %d: %s (%d)","Message",curObj,type,CmiGetHandler(msg));
515 p(name, strlen(name));
518 { /* charm message */
519 p.comment("charmMsg");
520 p.synchronize(PUP::sync_begin_object);
521 envelope *env=(envelope *)msg;
522 CkUnpackMessage(&env);
523 //messages[curObj]=env;
524 CpdPupMessage(p, EnvToUsr(env));
525 //CkPupMessage(p, &messages[curObj], 0);
526 p.synchronize(PUP::sync_end_object);
531 class CpdList_message : public CpdListAccessor {
532 virtual const char * getPath(void) const {return "converse/message";}
533 virtual size_t getLength(void) const {return 1;}
534 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
535 envelope *env = (envelope*)(((unsigned int)req.lo) + (((unsigned long)req.hi)<<32)+sizeof(CmiChunkHeader));
537 const char *type="Converse";
540 if (CmiGetHandler(env)==_charmHandlerIdx) {type="Local Charm";}
541 if (CmiGetXHandler(env)==_charmHandlerIdx) {type="Network Charm";}
542 sprintf(name,"%s 0: %s (%d)","Message",type,CmiGetHandler(env));
543 p(name, strlen(name));
544 p.comment("charmMsg");
545 p.synchronize(PUP::sync_begin_object);
546 CpdPupMessage(p, EnvToUsr(env));
547 p.synchronize(PUP::sync_end_object);
551 static void CpdDeliverMessageInt(int msgNum) {
553 void *debugQ=CkpvAccess(debugQueue);
554 CdsFifo_Enqueue(debugQ, (void*)(-1)); // Enqueue a guard
555 for (int i=0; i<msgNum; ++i) CdsFifo_Enqueue(debugQ, CdsFifo_Dequeue(debugQ));
556 CkpvAccess(skipBreakpoint) = 1;
557 char *queuedMsg = (char *)CdsFifo_Dequeue(debugQ);
558 if (_conditionalDelivery==1) conditionalShm->msgs[conditionalShm->count++] = msgNum;
559 if (_conditionalDelivery) {
560 CmiReference(queuedMsg);
561 CdsFifo_Enqueue(CpvAccess(conditionalQueue), queuedMsg);
565 BgProcessMessageDefault(cta(threadinfo), queuedMsg);
568 CmiHandleMessage(queuedMsg);
570 CkpvAccess(skipBreakpoint) = 0;
571 while ((m=CdsFifo_Dequeue(debugQ)) != (void*)(-1)) CdsFifo_Enqueue(debugQ, m);
574 void CpdDeliverMessage(char * msg) {
576 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);
577 //CmiPrintf("received deliver request %d\n",msgNum);
578 CpdDeliverMessageInt(msgNum);
581 void *CpdGetNextMessageConditional(CsdSchedulerState_t *s) {
584 if ((msg=CdsFifo_Dequeue(s->localQ)) != NULL) return msg;
585 CqsDequeue((Queue_struct*)s->schedQ,(void **)&msg);
586 if (msg!=NULL) return msg;
587 read(conditionalPipe[0], &len, 4);
589 read(conditionalPipe[0], msg, len);
593 #include <sys/wait.h>
597 extern "C" void CpdDeliverSingleMessage ();
599 static pid_t CpdConditional_SetupComm() {
601 pipe(pipefd[0]); // parent to child
602 pipe(pipefd[1]); // child to parent
604 if (conditionalShm == NULL) {
605 struct shmid_ds dummy;
606 int shmemid = shmget(IPC_PRIVATE, 1024*1024, IPC_CREAT | 0666);
607 conditionalShm = (ConditionalList*)shmat(shmemid, NULL, 0);
608 conditionalShm->count = 0;
609 conditionalShm->deliver = 0;
610 shmctl(shmemid, IPC_RMID, &dummy);
616 CmiPrintf("parent %d\n",pid);
619 conditionalPipe[0] = pipefd[1][0];
620 conditionalPipe[1] = pipefd[0][1];
621 //CpdConditionalDeliveryScheduler(pipefd[1][0], pipefd[0][1]);
622 read(conditionalPipe[0], &bytes, 4);
623 char *buf = (char*)malloc(bytes);
624 read(conditionalPipe[0], buf, bytes);
625 CcsSendReply(bytes,buf);
630 //int volatile tmp=1;
633 _conditionalDelivery = 1;
636 conditionalPipe[0] = pipefd[0][0];
637 conditionalPipe[1] = pipefd[1][1];
638 CpdGetNextMessage = CpdGetNextMessageConditional;
642 void CpdEndConditionalDelivery(char *msg) {
645 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);
646 printf("%d messages:\n",conditionalShm->count);
647 for (int i=0; i<conditionalShm->count; ++i)
648 printf("message delivered %d\n",conditionalShm->msgs[i]);
649 conditionalShm->count = msgNum;
650 shmdt((char*)conditionalShm);
654 extern "C" void CpdEndConditionalDeliver_master() {
655 close(conditionalPipe[0]);
656 conditionalPipe[0] = 0;
657 close(conditionalPipe[1]);
658 conditionalPipe[1] = 0;
661 // Check if we have to deliver unconditionally some messages
662 if (conditionalShm->deliver > 0) {
663 // Deliver the requested number of messages
664 for (i=0; i < conditionalShm->deliver; ++i) {
665 int msgNum = conditionalShm->msgs[i];
666 if (msgNum == -1) CpdDeliverSingleMessage();
667 else CpdDeliverMessageInt(msgNum);
669 // Move back the remaining messages accordingly
670 for (i=conditionalShm->deliver; i < conditionalShm->count; ++i) {
671 conditionalShm->msgs[i-conditionalShm->deliver] = conditionalShm->msgs[i];
673 conditionalShm->count -= conditionalShm->deliver;
674 conditionalShm->deliver = 0;
675 CmiMachineProgressImpl();
677 CkAssert(conditionalShm->count >= 0);
678 if (conditionalShm->count == 0) {
679 CcsSendReply(0,NULL);
680 shmdt((char*)conditionalShm);
681 conditionalShm = NULL;
682 CkPrintf("Conditional delivery on %d concluded; normal mode resumed\n",CkMyPe());
684 if (CpdConditional_SetupComm()==0) {
685 // We are in the child, deliver again the messages
686 _conditionalDelivery = 2;
687 printf("new child: redelivering %d messages\n",conditionalShm->count);
688 for (int i=0; i<conditionalShm->count; ++i) {
689 int msgNum = conditionalShm->msgs[i];
690 if (msgNum == -1) CpdDeliverSingleMessage();
691 else CpdDeliverMessageInt(msgNum);
693 _conditionalDelivery = 1;
694 CcsSendReply(0, NULL);
699 void CpdDeliverMessageConditionally(char * msg) {
702 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);
703 //CmiPrintf("received deliver request %d\n",msgNum);
705 if (CpdConditional_SetupComm()==0) {
706 if (msgNum == -1) CpdDeliverSingleMessage();
707 else CpdDeliverMessageInt(msgNum);
711 void CpdCommitConditionalDelivery(char * msg) {
713 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);\
714 conditionalShm->deliver = msgNum;
715 shmdt((char*)conditionalShm);
719 class CpdList_msgStack : public CpdListAccessor {
720 virtual const char * getPath(void) const {return "charm/messageStack";}
721 virtual size_t getLength(void) const {
722 return _debugData.length();
724 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
725 for (int i=0; i<_debugData.length(); ++i) {
727 void *obj = _debugData[i].obj;
729 pup_pointer(&p, &obj);
730 void *msg = _debugData[i].msg;
732 pup_pointer(&p, &msg);
737 /****************** Breakpoints and other debug support **************/
739 typedef CkHashtableTslow<int,EntryInfo *> CpdBpFuncTable_t;
741 extern void CpdFreeze(void);
742 extern void CpdUnFreeze(void);
743 extern int CpdIsFrozen(void);
745 CpvStaticDeclare(int, _debugMsg);
746 CpvStaticDeclare(int, _debugChare);
748 CpvStaticDeclare(CpdBpFuncTable_t *, breakPointEntryTable);
750 //CpvStaticDeclare(void *, lastBreakPointMsg);
751 CkpvStaticDeclare(void *, lastBreakPointObject);
752 CkpvStaticDeclare(int, lastBreakPointIndex);
754 void CpdBreakPointInit()
756 CkpvInitialize(void *, lastBreakPointMsg);
757 CkpvInitialize(void *, lastBreakPointObject);
758 CkpvInitialize(int, lastBreakPointIndex);
759 CpvInitialize(int, _debugMsg);
760 CpvInitialize(int, _debugChare);
761 CpvInitialize(CpdBpFuncTable_t *, breakPointEntryTable);
762 CkpvAccess(lastBreakPointMsg) = NULL;
763 CkpvAccess(lastBreakPointObject) = NULL;
764 CkpvAccess(lastBreakPointIndex) = 0;
765 CpvAccess(_debugMsg) = CkRegisterMsg("debug_msg",0,0,0,0);
766 CpvAccess(_debugChare) = CkRegisterChare("debug_Chare",0,TypeChare);
767 CkRegisterChareInCharm(CpvAccess(_debugChare));
768 CpvAccess(breakPointEntryTable) = new CpdBpFuncTable_t(10,0.5,CkHashFunction_int,CkHashCompare_int );
771 static void _call_freeze_on_break_point(void * msg, void * object)
773 //Save breakpoint entry point index. This is retrieved from msg.
774 //So that the appropriate EntryInfo can be later retrieved from the hash table
775 //of break point function entries, on continue.
777 // If the counter "skipBreakpoint" is not zero we actually do not freeze and deliver the regular message
778 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkMessageToEpIdx(msg));
779 if (CkpvAccess(skipBreakpoint) > 0 || CkpvAccess(_debugEntryTable)[CkMessageToEpIdx(msg)].isBreakpoint==false) {
780 CkAssert(breakPointEntryInfo != NULL);
781 breakPointEntryInfo->call(msg, object);
782 if (CkpvAccess(skipBreakpoint) > 0) CkpvAccess(skipBreakpoint) --;
784 CkpvAccess(lastBreakPointMsg) = msg;
785 CkpvAccess(lastBreakPointObject) = object;
786 CkpvAccess(lastBreakPointIndex) = CkMessageToEpIdx(msg);
787 CpdNotify(CPD_BREAKPOINT,breakPointEntryInfo->name);
791 ((workThreadInfo*)cta(threadinfo))->scheduler(-1);
796 //ccs handler when pressed the "next" command: deliver only a single message without unfreezing
798 void CpdDeliverSingleMessage () {
799 if (!CpdIsFrozen()) return; /* Do something only if we are in freeze mode */
800 if ( (CkpvAccess(lastBreakPointMsg) != NULL) && (CkpvAccess(lastBreakPointObject) != NULL) ) {
801 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkpvAccess(lastBreakPointIndex));
802 if (breakPointEntryInfo != NULL) {
803 if (_conditionalDelivery) {
804 if (_conditionalDelivery==1) conditionalShm->msgs[conditionalShm->count++] = -1;
805 void *env = UsrToEnv(CkpvAccess(lastBreakPointMsg));
807 CdsFifo_Enqueue(CpvAccess(conditionalQueue),env);
809 breakPointEntryInfo->call(CkpvAccess(lastBreakPointMsg), CkpvAccess(lastBreakPointObject));
811 CkpvAccess(lastBreakPointMsg) = NULL;
812 CkpvAccess(lastBreakPointObject) = NULL;
814 ((workThreadInfo*)cta(threadinfo))->stopScheduler();
818 // we were not stopped at a breakpoint, then deliver the first message in the debug queue
819 if (!CdsFifo_Empty(CkpvAccess(debugQueue))) {
820 CkpvAccess(skipBreakpoint) = 1;
821 char *queuedMsg = (char *)CdsFifo_Dequeue(CkpvAccess(debugQueue));
822 if (_conditionalDelivery) {
823 if (_conditionalDelivery==1) conditionalShm->msgs[conditionalShm->count++] = 0;
824 CmiReference(queuedMsg);
825 CdsFifo_Enqueue(CpvAccess(conditionalQueue),queuedMsg);
829 BgProcessMessageDefault(cta(threadinfo), queuedMsg);
832 CmiHandleMessage(queuedMsg);
834 CkpvAccess(skipBreakpoint) = 0;
839 //ccs handler when continue from a break point
841 void CpdContinueFromBreakPoint ()
844 if ( (CkpvAccess(lastBreakPointMsg) != NULL) && (CkpvAccess(lastBreakPointObject) != NULL) )
846 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkpvAccess(lastBreakPointIndex));
847 if (breakPointEntryInfo != NULL) {
848 breakPointEntryInfo->call(CkpvAccess(lastBreakPointMsg), CkpvAccess(lastBreakPointObject));
850 ((workThreadInfo*)cta(threadinfo))->stopScheduler();
853 // This means that the breakpoint got deleted in the meanwhile
857 CkpvAccess(lastBreakPointMsg) = NULL;
858 CkpvAccess(lastBreakPointObject) = NULL;
861 //ccs handler to set a breakpoint with entry function name msg
862 void CpdSetBreakPoint (char *msg)
864 char functionName[128];
865 int tableSize, tableIdx = 0;
867 sscanf(msg+CmiReservedHeaderSize, "%s", functionName);
868 if (strlen(functionName) > 0)
870 tableSize = _entryTable.size();
871 // Replace entry in entry table with _call_freeze_on_break_point
872 tableIdx = atoi(functionName);
873 if (tableIdx >= 0 && tableIdx < tableSize) {
874 if (! CkpvAccess(_debugEntryTable)[tableIdx].isBreakpoint) {
875 EntryInfo * breakPointEntryInfo = (EntryInfo *)CpvAccess(breakPointEntryTable)->get(tableIdx);
876 if (breakPointEntryInfo == 0) {
877 breakPointEntryInfo = new EntryInfo(_entryTable[tableIdx]->name, _entryTable[tableIdx]->call, 1, 0 );
878 //CmiPrintf("Breakpoint is set for function %s with an epIdx = %ld\n", _entryTable[tableIdx]->name, tableIdx);
879 CpvAccess(breakPointEntryTable)->put(tableIdx) = breakPointEntryInfo;
880 _entryTable[tableIdx]->name = "debug_breakpoint_ep";
881 _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
883 if (breakPointEntryInfo->msgIdx == 0) {
884 // Reset the breakpoint info
885 _entryTable[tableIdx]->name = "debug_breakpoint_ep";
886 _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
888 breakPointEntryInfo->msgIdx ++;
889 //CkAssert(breakPointEntryInfo->name == _entryTable[tableIdx]->name);
890 //CkAssert(breakPointEntryInfo->call == _entryTable[tableIdx]->call);
891 //CkAssert(breakPointEntryInfo->msgIdx == _entryTable[tableIdx]->msgIdx);
892 //CkAssert(breakPointEntryInfo->chareIdx == _entryTable[tableIdx]->chareIdx);
894 CkpvAccess(_debugEntryTable)[tableIdx].isBreakpoint = true;
900 CcsSendReply(sizeof(int), (void*)&reply);
906 CpdContinueFromBreakPoint();
910 void CpdRemoveBreakPoint (char *msg)
912 char functionName[128];
914 sscanf(msg+CmiReservedHeaderSize, "%s", functionName);
915 if (strlen(functionName) > 0) {
916 int idx = atoi(functionName);
917 if (idx >= 0 && idx < _entryTable.size()) {
918 if (CkpvAccess(_debugEntryTable)[idx].isBreakpoint) {
919 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(idx);
920 if (breakPointEntryInfo != NULL) {
921 if (--breakPointEntryInfo->msgIdx == 0) {
922 // If we are the last to delete the breakpoint, then restore the original name and call function pointer
923 _entryTable[idx]->name = breakPointEntryInfo->name;
924 _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
927 CkpvAccess(_debugEntryTable)[idx].isBreakpoint = false;
928 //CmiPrintf("Breakpoint is removed for function %s with epIdx %ld\n", _entryTable[idx]->name, idx);
929 //CkpvAccess(breakPointEntryTable)->remove(idx);
934 CcsSendReply(sizeof(int), (void*)&reply);
937 void CpdRemoveAllBreakPoints ()
939 //all breakpoints removed
943 CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
944 while(NULL!=(objPointer = it->next(&keyPointer)))
946 EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
947 int idx = *(int *)keyPointer;
948 if (--breakPointEntryInfo->msgIdx == 0) {
949 // If we are the last to delete the breakpoint, then restore the original name and call function pointer
950 _entryTable[idx]->name = breakPointEntryInfo->name;
951 _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
953 CkpvAccess(_debugEntryTable)[idx].isBreakpoint = false;
955 CcsSendReply(sizeof(int), (void*)&reply);
958 extern "C" int CpdIsCharmDebugMessage(void *msg) {
959 envelope *env = (envelope*)msg;
960 // Later should use "isDebug" value, but for now just bypass all intrinsic EPs
961 return CmiGetHandler(msg) != _charmHandlerIdx || env->getMsgtype() == ForVidMsg ||
962 env->getMsgtype() == FillVidMsg || _entryTable[env->getEpIdx()]->inCharm;
966 CpvExtern(int, _bgCcsHandlerIdx);
967 extern "C" int CpdIsBgCharmDebugMessage(void *msg) {
968 envelope *env = (envelope*)msg;
969 if (CmiBgMsgFlag(msg) == BG_CLONE) {
970 env=*(envelope**)(((char*)msg)+CmiBlueGeneMsgHeaderSizeBytes);
972 if ((((CmiBlueGeneMsgHeader*)env)->hID) == CpvAccess(_bgCcsHandlerIdx)) return 1;
973 // make sure it indeed is a charm message
974 if (CmiBgMsgHandle(env) == _charmHandlerIdx) {
975 return env->getMsgtype() == ForVidMsg || env->getMsgtype() == FillVidMsg ||
976 _entryTable[env->getEpIdx()]->inCharm;
982 CpvExtern(char *, displayArgument);
984 void CpdStartGdb(void)
986 #if !defined(_WIN32) || defined(__CYGWIN__)
990 if (CpvAccess(displayArgument) != NULL)
992 /*CmiPrintf("MY NODE IS %d and process id is %d\n", CmiMyPe(), getpid());*/
993 sprintf(gdbScript, "/tmp/cpdstartgdb.%d.%d", getpid(), CmiMyPe());
994 f = fopen(gdbScript, "w");
995 fprintf(f,"#!/bin/sh\n");
996 fprintf(f,"cat > /tmp/start_gdb.$$ << END_OF_SCRIPT\n");
997 fprintf(f,"shell /bin/rm -f /tmp/start_gdb.$$\n");
998 //fprintf(f,"handle SIGPIPE nostop noprint\n");
999 fprintf(f,"handle SIGWINCH nostop noprint\n");
1000 fprintf(f,"handle SIGWAITING nostop noprint\n");
1001 fprintf(f, "attach %d\n", getpid());
1002 fprintf(f,"END_OF_SCRIPT\n");
1003 fprintf(f, "DISPLAY='%s';export DISPLAY\n",CpvAccess(displayArgument));
1004 fprintf(f,"/usr/X11R6/bin/xterm ");
1005 fprintf(f," -title 'Node %d ' ",CmiMyPe());
1006 fprintf(f," -e /usr/bin/gdb -x /tmp/start_gdb.$$ \n");
1007 fprintf(f, "exit 0\n");
1009 if( -1 == chmod(gdbScript, 0755))
1011 CmiPrintf("ERROR> chmod on script failed!\n");
1016 { perror("ERROR> forking to run debugger script\n"); exit(1); }
1019 //CmiPrintf("In child process to start script %s\n", gdbScript);
1020 if (-1 == execvp(gdbScript, NULL))
1021 CmiPrintf ("Error> Could not Execute Debugger Script: %s\n",strerror
1030 size_t cpd_memory_length(void*);
1031 void cpd_memory_pup(void*,void*,CpdListItemsRequest*);
1032 void cpd_memory_leak(void*,void*,CpdListItemsRequest*);
1033 size_t cpd_memory_getLength(void*);
1034 void cpd_memory_get(void*,void*,CpdListItemsRequest*);
1040 CpdListRegister(new CpdListAccessor_c("memory/list",cpd_memory_length,0,cpd_memory_pup,0));
1041 CpdListRegister(new CpdListAccessor_c("memory/data",cpd_memory_getLength,0,cpd_memory_get,0,false));
1043 //CpdBreakPointInit();
1044 CcsRegisterHandler("debug/charm/bp/set",(CmiHandler)CpdSetBreakPoint);
1045 CcsSetMergeFn("debug/charm/bp/set",CcsMerge_logical_and);
1046 CcsRegisterHandler("debug/charm/bp/remove",(CmiHandler)CpdRemoveBreakPoint);
1047 CcsSetMergeFn("debug/charm/bp/remove",CcsMerge_logical_and);
1048 CcsRegisterHandler("debug/charm/bp/removeall",(CmiHandler)CpdRemoveAllBreakPoints);
1049 CcsSetMergeFn("debug/charm/bp/removeall",CmiReduceMergeFn_random);
1050 CcsRegisterHandler("debug/charm/continue",(CmiHandler)CpdContinueFromBreakPoint);
1051 CcsSetMergeFn("debug/charm/continue",CmiReduceMergeFn_random);
1052 CcsRegisterHandler("debug/charm/next",(CmiHandler)CpdDeliverSingleMessage);
1053 CcsSetMergeFn("debug/charm/next",CmiReduceMergeFn_random);
1054 CcsRegisterHandler("debug/converse/quit",(CmiHandler)CpdQuitDebug);
1055 CcsSetMergeFn("debug/converse/quit",CmiReduceMergeFn_random);
1056 CcsRegisterHandler("debug/converse/startgdb",(CmiHandler)CpdStartGdb);
1057 CpdListRegister(new CpdListAccessor_c("hostinfo",hostInfoLength,0,hostInfo,0));
1058 CpdListRegister(new CpdList_localQ());
1059 CcsRegisterHandler("debug/charm/deliver",(CmiHandler)CpdDeliverMessage);
1060 CcsRegisterHandler("debug/provisional/deliver",(CmiHandler)CpdDeliverMessageConditionally);
1061 CcsRegisterHandler("debug/provisional/rollback",(CmiHandler)CpdEndConditionalDelivery);
1062 CcsRegisterHandler("debug/provisional/commit",(CmiHandler)CpdCommitConditionalDelivery);
1063 CpdListRegister(new CpdList_arrayElementNames());
1064 CpdListRegister(new CpdList_arrayElements());
1065 CpdListRegister(new CpdList_objectNames());
1066 CpdListRegister(new CpdList_object());
1067 CpdListRegister(new CpdList_message());
1068 CpdListRegister(new CpdList_msgStack());
1069 CpdGetNextMessage = CsdNextMessage;
1070 CpdIsDebugMessage = CpdIsCharmDebugMessage;
1071 #if CMK_BIGSIM_CHARM
1072 CpdIsDebugMessage = CpdIsBgCharmDebugMessage;
1076 #if CMK_BIGSIM_CHARM
1077 CpvExtern(int, _bgCcsHandlerIdx);
1078 CpvExtern(int, _bgCcsAck);
1079 extern "C" void req_fw_handler(char*);
1080 CkpvExtern(void *, debugQueue);
1081 CkpvExtern(int, freezeModeFlag);
1082 #include "blue_impl.h"
1083 extern void BgProcessMessageFreezeMode(threadInfo *, char *);
1087 // Register the BG handler for CCS. Notice that this is put into a variable shared by
1088 // the whole real processor. This because converse needs to find it. We check that all
1089 // virtual processors register the same index for this handler.
1090 int bgCcsHandlerIdx = CkRegisterHandler((CmiHandler)req_fw_handler);
1091 if (CpvAccess(_bgCcsHandlerIdx) == 0) CpvAccess(_bgCcsHandlerIdx) = bgCcsHandlerIdx;
1092 CkAssert(CpvAccess(_bgCcsHandlerIdx)==bgCcsHandlerIdx);
1093 CpvAccess(_bgCcsAck) ++;
1094 CcsReleaseMessages();
1096 CkpvInitialize(int, freezeModeFlag);
1097 CkpvAccess(freezeModeFlag) = 0;
1099 CkpvInitialize(void *, debugQueue);
1100 CkpvAccess(debugQueue) = CdsFifo_Create();
1102 BgProcessMessage = BgProcessMessageFreezeMode;
1108 void CpdBreakPointInit() {}
1109 void CpdCharmInit() {}
1110 #if CMK_BIGSIM_CHARM
1114 void CpdFinishInitialization() {}
1116 void *CpdGetCurrentObject() {return NULL;}
1117 void *CpdGetCurrentMsg() {return NULL;}
1118 extern "C" void CpdEndConditionalDeliver_master() {}
1120 void CpdBeforeEp(int ep, void *obj, void *msg) {}
1121 void CpdAfterEp(int ep) {}
1123 #endif /*CMK_CCS_AVAILABLE*/