00001
00002
00003
00004
00005 #include "converse.h"
00006
00007 #include <errno.h>
00008 #include <string.h>
00009 #include <sys/stat.h>
00010
00011 #include "ckhashtable.h"
00012 #include "conv-ccs.h"
00013 #include "debug-charm.h"
00014 #include "sockRoutines.h"
00015 #include "charm.h"
00016 #include "middle.h"
00017 #include "cklists.h"
00018 #include "register.h"
00019
00020 #include <unistd.h>
00021
00022 #if CMK_BIGSIM_CHARM
00023 #include "blue_impl.h"
00024 #endif
00025
00026
00027 #if CMK_CHARMDEBUG && CMK_CCS_AVAILABLE && !defined(_WIN32)
00028
00029 #include "ck.h"
00030
00031 CkpvDeclare(int, skipBreakpoint);
00032 CkpvDeclare(DebugEntryTable, _debugEntryTable);
00033 CpdPersistentChecker persistentCheckerUselessClass;
00034
00035 void CpdFinishInitialization() {
00036 CkpvInitialize(int, skipBreakpoint);
00037 CkpvAccess(skipBreakpoint) = 0;
00038 CkpvInitialize(DebugEntryTable, _debugEntryTable);
00039 CkpvAccess(_debugEntryTable).resize(_entryTable.size());
00040 }
00041
00042 extern "C" void resetAllCRC();
00043 extern "C" void checkAllCRC(int report);
00044
00045 typedef struct DebugRecursiveEntry {
00046 int previousChareID;
00047 int alreadyUserCode;
00048 char *memoryBackup;
00049 void *obj;
00050 void *msg;
00051 } DebugRecursiveEntry;
00052
00053 CkQ<DebugRecursiveEntry> _debugData;
00054
00055 void *CpdGetCurrentObject() { return _debugData.peek().obj; }
00056 void *CpdGetCurrentMsg() { return _debugData.peek().msg; }
00057
00058 extern int cpdInSystem;
00059 extern "C" int CpdInUserCode() {return cpdInSystem==0 && _debugData.length()>0 && _debugData.peek().alreadyUserCode==1;}
00060
00061
00062 void CpdBeforeEp(int ep, void *obj, void *msg) {
00063 #ifndef CMK_OPTIMIZE
00064 if (CpvAccess(cmiArgDebugFlag)) {
00065 DebugRecursiveEntry entry;
00066 entry.previousChareID = setMemoryChareIDFromPtr(obj);
00067 entry.alreadyUserCode = _entryTable[ep]->inCharm ? 0 : 1;
00068 entry.memoryBackup = NULL;
00069 entry.obj = obj;
00070 if (msg != NULL) {
00071 entry.msg = msg;
00072 CmiReference(UsrToEnv(msg));
00073 }
00074 else entry.msg = NULL;
00075 _debugData.push(entry);
00076 setMemoryStatus(entry.alreadyUserCode);
00077
00078 memoryBackup = &_debugData.peek().memoryBackup;
00079 if (!_entryTable[ep]->inCharm) {
00080 CpdResetMemory();
00081 CpdSystemExit();
00082 }
00083 CkVec<DebugPersistentCheck> &preExecutes = CkpvAccess(_debugEntryTable)[ep].preProcess;
00084 for (int i=0; i<preExecutes.size(); ++i) {
00085 preExecutes[i].object->cpdCheck(preExecutes[i].msg);
00086 }
00087 }
00088 #endif
00089 }
00090
00091
00092 void CpdAfterEp(int ep) {
00093 #ifndef CMK_OPTIMIZE
00094 if (CpvAccess(cmiArgDebugFlag)) {
00095 DebugRecursiveEntry entry = _debugData.peek();
00096 CkVec<DebugPersistentCheck> &postExecutes = CkpvAccess(_debugEntryTable)[ep].postProcess;
00097 for (int i=0; i<postExecutes.size(); ++i) {
00098 postExecutes[i].object->cpdCheck(postExecutes[i].msg);
00099 }
00100 memoryBackup = &entry.memoryBackup;
00101 if (!_entryTable[ep]->inCharm) {
00102 CpdSystemEnter();
00103 CpdCheckMemory();
00104 }
00105 if (entry.msg != NULL) CmiFree(UsrToEnv(entry.msg));
00106 setMemoryChareID(entry.previousChareID);
00107 setMemoryStatus(entry.alreadyUserCode);
00108 _debugData.deq();
00109 }
00110 #endif
00111 }
00112
00113
00114
00119 template <class T>
00120 class CkArrayElementRangeIterator : public CkLocIterator {
00121 private:
00122 T *dest;
00123 CkArray *mgr;
00124 int cur,lo,hi;
00125 public:
00126 CkArrayElementRangeIterator(T *dest_,int l,int h)
00127 :dest(dest_),mgr(0),cur(0),lo(l),hi(h) {}
00128
00132 int iterate(int start, CkArray *m) {
00133 cur = start;
00134 mgr = m;
00135 mgr->getLocMgr()->iterate(*this);
00136 cur -= start;
00137 return cur;
00138 }
00139
00141 void iterate(void)
00142 {
00143 int numGroups=CkpvAccess(_groupIDTable)->size();
00144 for(int i=0;i<numGroups;i++) {
00145 IrrGroup *obj = CkpvAccess(_groupTable)->find((*CkpvAccess(_groupIDTable))[i]).getObj();
00146 if (obj->isArrMgr())
00147 {
00148 mgr=(CkArray *)obj;
00149 mgr->getLocMgr()->iterate(*this);
00150 }
00151 }
00152 }
00153
00154
00155 virtual void addLocation (CkLocation &loc)
00156 {
00157 if (cur>=lo && cur<hi)
00158 {
00159 dest->add(cur,mgr->lookup(loc.getIndex()),mgr->getGroupID().idx);
00160 }
00161 cur++;
00162 }
00163
00164
00165 int getCount(void) {return cur;}
00166 };
00167
00172 template <class T>
00173 class CkObjectRangeIterator {
00174 private:
00175 T *dest;
00176 int cur,lo,hi;
00177 public:
00178 CkObjectRangeIterator(T *dest_,int l,int h)
00179 :dest(dest_),cur(0),lo(l),hi(h) {}
00180
00182 void iterate(void)
00183 {
00184 int numGroups=CkpvAccess(_groupIDTable)->size();
00185 for(int i=0;i<numGroups;i++) {
00186 CkGroupID groupID = (*CkpvAccess(_groupIDTable))[i];
00187 IrrGroup *obj = CkpvAccess(_groupTable)->find(groupID).getObj();
00188
00189
00190
00191
00192
00193
00194
00195 dest->add(cur,obj,groupID.idx);
00196 cur++;
00197
00198 }
00199 }
00200
00201
00202 int getCount(void) {return cur;}
00203 };
00204
00205 class ignoreAdd {
00206 public: void add(int cur,Chare *elt,int group) {}
00207 };
00208
00210 class CpdList_objectNames : public CpdListAccessor {
00211 PUP::er *pp;
00212 int curGroup;
00213 public:
00214 virtual const char * getPath(void) const {return "charm/objectNames";}
00215 virtual size_t getLength(void) const {
00216 CkObjectRangeIterator<ignoreAdd> it(0,0,0);
00217 it.iterate();
00218 return it.getCount();
00219 }
00220 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00221 pp=&p;
00222 CkObjectRangeIterator<CpdList_objectNames> it(this,req.lo,req.hi);
00223 it.iterate();
00224 }
00225 void add(int cur, Chare *obj, int group) {
00226 PUP::er &p=*pp;
00227 beginItem(p,cur);
00228 p.comment("id");
00229 char *n = (char*)malloc(30);
00230 int s=obj->ckDebugChareID(n, 30);
00231 CkAssert(s > 0);
00232 p(n,s);
00233 free(n);
00234 PUPn(group);
00235 p.comment("name");
00236 n=obj->ckDebugChareName();
00237 p(n,strlen(n));
00238 free(n);
00239 }
00240 };
00241
00244 class CpdList_object : public CpdListAccessor {
00245 PUP::er *pp;
00246 CpdListItemsRequest *reqq;
00247 public:
00248 virtual const char * getPath(void) const {return "charm/object";}
00249 virtual size_t getLength(void) const {
00250 CkObjectRangeIterator<ignoreAdd> it(0,0,0);
00251 it.iterate();
00252 return it.getCount();
00253 }
00254 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00255 pp=&p;
00256 reqq=&req;
00257 CkObjectRangeIterator<CpdList_object> it(this,req.lo,req.hi);
00258 it.iterate();
00259 }
00260 void add(int cur, Chare *obj, int group) {
00261 PUP::er &p=*pp;
00262 CpdListItemsRequest &req=*reqq;
00263 char *n = (char *)malloc(30);
00264 int s=obj->ckDebugChareID(n, 30);
00265 CkAssert(s > 0);
00266 if (req.extraLen == s && memcmp(req.extra, n, s) == 0) {
00267
00268 beginItem(p,cur);
00269 int type = obj->ckGetChareType();
00270 p.comment("type");
00271 const char *t = _chareTable[type]->name;
00272 p((char*)t,strlen(t));
00273 p.comment("value");
00274 int size = _chareTable[type]->size;
00275 p((char*)obj,size);
00276 }
00277 }
00278 };
00279
00281 class CpdList_arrayElementNames : public CpdListAccessor {
00282 PUP::er *pp;
00283 public:
00284 virtual const char * getPath(void) const {return "charm/arrayElementNames";}
00285 virtual size_t getLength(void) const {
00286 CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
00287 it.iterate();
00288 return it.getCount();
00289 }
00290 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00291 pp=&p;
00292 CkArrayElementRangeIterator<CpdList_arrayElementNames> it(this,req.lo,req.hi);
00293 it.iterate();
00294 }
00295 void add(int cur,Chare *e,int group)
00296 {
00297 ArrayElement *elt = (ArrayElement*)e;
00298 PUP::er &p=*pp;
00299 beginItem(p,cur);
00300 p.comment("name");
00301 char *n=elt->ckDebugChareName();
00302 p(n,strlen(n));
00303 free(n);
00304 }
00305 };
00306
00308 class CpdList_arrayElements : public CpdListAccessor {
00309 PUP::er *pp;
00310 public:
00311 virtual const char * getPath(void) const {return "charm/arrayElements";}
00312 virtual size_t getLength(void) const {
00313 CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
00314 it.iterate();
00315 return it.getCount();
00316 }
00317 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00318 pp=&p;
00319 CkArrayElementRangeIterator<CpdList_arrayElements> it(this,req.lo,req.hi);
00320 it.iterate();
00321 }
00322 void add(int cur, Chare *e, int group)
00323 {
00324 ArrayElement *elt = (ArrayElement*)e;
00325 PUP::er &p=*pp;
00326 beginItem(p,cur);
00327
00328
00329 p.comment("name");
00330 char *n=elt->ckDebugChareName();
00331 p(n,strlen(n));
00332 free(n);
00333 int type = elt->ckGetChareType();
00334 p.comment("type");
00335 const char *t = _chareTable[type]->name;
00336 p((char*)t,strlen(t));
00337 p.comment("value");
00338 int size = _chareTable[type]->size;
00339 p((char*)elt,size);
00340 }
00341 };
00342
00343 #ifndef __CYGWIN__
00344 #include <rpc/rpc.h>
00345 #endif
00346
00347 size_t hostInfoLength(void *) {return 1;}
00348
00349 void hostInfo(void *itemIter, pup_er pp, CpdListItemsRequest *req) {
00350 PUP::er &p = *(PUP::er *)pp;
00351 struct sockaddr_in addr;
00352 CpdListBeginItem(pp, 0);
00353 #if CMK_HAS_GET_MYADDRESS
00354 get_myaddress(&addr);
00355 #else
00356 CmiAbort("hostInfo: get_myaddress does not work on this machine");
00357 #endif
00358 char *address = (char*)&addr.sin_addr.s_addr;
00359 PUPv(address, 4);
00360 int pid = getpid();
00361 PUPn(pid);
00362 }
00363
00364
00365 CkpvExtern(void *,debugQueue);
00366
00367
00368
00369
00370 void CpdPupMessage(PUP::er &p, void *msg)
00371 {
00372 envelope *env=UsrToEnv(msg);
00373
00374 int size=env->getTotalsize();
00375 int prioBits=env->getPriobits();
00376 int from=env->getSrcPe();
00377 PUPn(from);
00378
00379 PUPn(prioBits);
00380 int userSize=size-sizeof(envelope)-sizeof(int)*CkPriobitsToInts(prioBits);
00381 PUPn(userSize);
00382 int msgType = env->getMsgIdx();
00383 PUPn(msgType);
00384 int envType = env->getMsgtype();
00385 PUPn(envType);
00386
00387
00388
00389 int ep=CkMessageToEpIdx(msg);
00390 PUPn(ep);
00391
00392
00393 if (envType == ForArrayEltMsg || envType == ArrayEltInitMsg) {
00394 int arrID = env->getsetArrayMgr().idx;
00395 PUPn(arrID);
00396 CkArrayIndex &idx = env->getsetArrayIndex();
00397 int nInts = idx.nInts;
00398 int dimension = idx.dimension;
00399 PUPn(nInts);
00400 PUPn(dimension);
00401 p.comment("index");
00402 if (dimension >=4 && dimension <=6) {
00403 p((short int *)idx.index, dimension);
00404 } else {
00405 p(idx.index, nInts);
00406 }
00407 } else if (envType == BocInitMsg || envType == NodeBocInitMsg ||
00408 envType == ForNodeBocMsg || envType == ForBocMsg) {
00409 int groupID = env->getGroupNum().idx;
00410 PUPn(groupID);
00411 } else if (envType == NewVChareMsg || envType == ForVidMsg || envType == FillVidMsg) {
00412 p.comment("ptr");
00413 void *ptr = env->getVidPtr();
00414 pup_pointer(&p, &ptr);
00415 } else if (envType == ForChareMsg) {
00416 p.comment("ptr");
00417 void *ptr = env->getObjPtr();
00418 pup_pointer(&p, &ptr);
00419 }
00420
00421
00422 p.comment("data");
00423 p.synchronize(PUP::sync_begin_object);
00424 if (_entryTable[ep]->messagePup!=NULL)
00425 _entryTable[ep]->messagePup(p,msg);
00426 else
00427 CkMessage::ckDebugPup(p,msg);
00428 p.synchronize(PUP::sync_end_object);
00429 }
00430
00431 struct ConditionalList {
00432 int count;
00433 int deliver;
00434 int msgs[1];
00435 };
00436 CkpvStaticDeclare(void *, lastBreakPointMsg);
00437 CpvExtern(void*, conditionalQueue);
00438 ConditionalList * conditionalShm = NULL;
00439
00440
00441 class CpdList_localQ : public CpdListAccessor {
00442
00443 public:
00444 CpdList_localQ() {}
00445 virtual const char * getPath(void) const {return "converse/localqueue";}
00446 virtual size_t getLength(void) const {
00447 int x = CdsFifo_Length((CdsFifo)(CkpvAccess(debugQueue)));
00448
00449
00450 if (CkpvAccess(lastBreakPointMsg) != NULL) x++;
00451 return x;
00452 }
00453 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00454 int length;
00455 void ** messages;
00456 int curObj=0;
00457 void *msg;
00458
00459 length = CdsFifo_Length((CdsFifo)(CpvAccess(conditionalQueue)));
00460 messages = CdsFifo_Enumerate(CpvAccess(conditionalQueue));
00461 for (curObj=-length; curObj<0; curObj++) {
00462 void *msg = messages[length+curObj];
00463 pupSingleMessage(p, curObj-1, msg);
00464 }
00465 delete[] messages;
00466
00467 curObj = 0;
00468 length = CdsFifo_Length((CdsFifo)(CkpvAccess(debugQueue)));
00469 messages = CdsFifo_Enumerate(CkpvAccess(debugQueue));
00470
00471 if (CkpvAccess(lastBreakPointMsg) != NULL) {
00472 beginItem(p, -1);
00473 envelope *env=(envelope *)UsrToEnv(CkpvAccess(lastBreakPointMsg));
00474 p.comment("name");
00475 char *type=(char*)"Breakpoint";
00476 p(type,strlen(type));
00477 p.comment("charmMsg");
00478 p.synchronize(PUP::sync_begin_object);
00479 CkUnpackMessage(&env);
00480 CpdPupMessage(p, EnvToUsr(env));
00481 p.synchronize(PUP::sync_end_object);
00482 }
00483
00484 for(curObj=req.lo; curObj<req.hi; curObj++)
00485 if ((curObj>=0) && (curObj<length))
00486 {
00487 void *msg=messages[curObj];
00488 pupSingleMessage(p, curObj, msg);
00489 }
00490 delete[] messages;
00491
00492 }
00493
00494 void pupSingleMessage(PUP::er &p, int curObj, void *msg) {
00495 beginItem(p,curObj);
00496 int isCharm=0;
00497 const char *type="Converse";
00498 p.comment("name");
00499 char name[128];
00500 if (msg == (void*)-1) {
00501 type="Sentinel";
00502 p((char*)type, strlen(type));
00503 return;
00504 }
00505 #if ! CMK_BIGSIM_CHARM
00506 if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";}
00507 if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";}
00508 #else
00509 isCharm=1; type="BG";
00510 #endif
00511 if (curObj < 0) type="Conditional";
00512 sprintf(name,"%s %d: %s (%d)","Message",curObj,type,CmiGetHandler(msg));
00513 p(name, strlen(name));
00514
00515 if (isCharm)
00516 {
00517 p.comment("charmMsg");
00518 p.synchronize(PUP::sync_begin_object);
00519 envelope *env=(envelope *)msg;
00520 CkUnpackMessage(&env);
00521
00522 CpdPupMessage(p, EnvToUsr(env));
00523
00524 p.synchronize(PUP::sync_end_object);
00525 }
00526 }
00527 };
00528
00529 class CpdList_message : public CpdListAccessor {
00530 virtual const char * getPath(void) const {return "converse/message";}
00531 virtual size_t getLength(void) const {return 1;}
00532 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00533 envelope *env = (envelope*)(((unsigned int)req.lo) + (((unsigned long)req.hi)<<32)+sizeof(CmiChunkHeader));
00534 beginItem(p, 0);
00535 const char *type="Converse";
00536 p.comment("name");
00537 char name[128];
00538 if (CmiGetHandler(env)==_charmHandlerIdx) {type="Local Charm";}
00539 if (CmiGetXHandler(env)==_charmHandlerIdx) {type="Network Charm";}
00540 sprintf(name,"%s 0: %s (%d)","Message",type,CmiGetHandler(env));
00541 p(name, strlen(name));
00542 p.comment("charmMsg");
00543 p.synchronize(PUP::sync_begin_object);
00544 CpdPupMessage(p, EnvToUsr(env));
00545 p.synchronize(PUP::sync_end_object);
00546 }
00547 };
00548
00549 static void CpdDeliverMessageInt(int msgNum) {
00550 void *m;
00551 void *debugQ=CkpvAccess(debugQueue);
00552 CdsFifo_Enqueue(debugQ, (void*)(-1));
00553 for (int i=0; i<msgNum; ++i) CdsFifo_Enqueue(debugQ, CdsFifo_Dequeue(debugQ));
00554 CkpvAccess(skipBreakpoint) = 1;
00555 char *queuedMsg = (char *)CdsFifo_Dequeue(debugQ);
00556 if (_conditionalDelivery==1) conditionalShm->msgs[conditionalShm->count++] = msgNum;
00557 if (_conditionalDelivery) {
00558 CmiReference(queuedMsg);
00559 CdsFifo_Enqueue(CpvAccess(conditionalQueue), queuedMsg);
00560 }
00561 #if CMK_BIGSIM_CHARM
00562 stopVTimer();
00563 BgProcessMessageDefault(cta(threadinfo), queuedMsg);
00564 startVTimer();
00565 #else
00566 CmiHandleMessage(queuedMsg);
00567 #endif
00568 CkpvAccess(skipBreakpoint) = 0;
00569 while ((m=CdsFifo_Dequeue(debugQ)) != (void*)(-1)) CdsFifo_Enqueue(debugQ, m);
00570 }
00571
00572 void CpdDeliverMessage(char * msg) {
00573 int msgNum;
00574 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);
00575
00576 CpdDeliverMessageInt(msgNum);
00577 }
00578
00579 void *CpdGetNextMessageConditional(CsdSchedulerState_t *s) {
00580 int len;
00581 void *msg;
00582 if ((msg=CdsFifo_Dequeue(s->localQ)) != NULL) return msg;
00583 CqsDequeue((Queue_struct*)s->schedQ,(void **)&msg);
00584 if (msg!=NULL) return msg;
00585 read(conditionalPipe[0], &len, 4);
00586 msg = CmiAlloc(len);
00587 read(conditionalPipe[0], msg, len);
00588 return msg;
00589 }
00590
00591 #include <sys/wait.h>
00592 #include <sys/ipc.h>
00593 #include <sys/shm.h>
00594
00595 extern "C" void CpdDeliverSingleMessage ();
00596
00597 static pid_t CpdConditional_SetupComm() {
00598 int pipefd[2][2];
00599 pipe(pipefd[0]);
00600 pipe(pipefd[1]);
00601
00602 if (conditionalShm == NULL) {
00603 struct shmid_ds dummy;
00604 int shmemid = shmget(IPC_PRIVATE, 1024*1024, IPC_CREAT | 0666);
00605 conditionalShm = (ConditionalList*)shmat(shmemid, NULL, 0);
00606 conditionalShm->count = 0;
00607 conditionalShm->deliver = 0;
00608 shmctl(shmemid, IPC_RMID, &dummy);
00609 }
00610
00611 pid_t pid = fork();
00612 if (pid > 0) {
00613 int bytes;
00614 CmiPrintf("parent %d\n",pid);
00615 close(pipefd[0][0]);
00616 close(pipefd[1][1]);
00617 conditionalPipe[0] = pipefd[1][0];
00618 conditionalPipe[1] = pipefd[0][1];
00619
00620 read(conditionalPipe[0], &bytes, 4);
00621 char *buf = (char*)malloc(bytes);
00622 read(conditionalPipe[0], buf, bytes);
00623 CcsSendReply(bytes,buf);
00624 free(buf);
00625 return pid;
00626 }
00627
00628
00629
00630 printf("child\n");
00631 _conditionalDelivery = 1;
00632 close(pipefd[0][1]);
00633 close(pipefd[1][0]);
00634 conditionalPipe[0] = pipefd[0][0];
00635 conditionalPipe[1] = pipefd[1][1];
00636 CpdGetNextMessage = CpdGetNextMessageConditional;
00637 return 0;
00638 }
00639
00640 void CpdEndConditionalDelivery(char *msg) {
00641 int msgNum;
00642 void *m;
00643 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);
00644 printf("%d messages:\n",conditionalShm->count);
00645 for (int i=0; i<conditionalShm->count; ++i)
00646 printf("message delivered %d\n",conditionalShm->msgs[i]);
00647 conditionalShm->count = msgNum;
00648 shmdt((char*)conditionalShm);
00649 _exit(0);
00650 }
00651
00652 extern "C" void CpdEndConditionalDeliver_master() {
00653 close(conditionalPipe[0]);
00654 conditionalPipe[0] = 0;
00655 close(conditionalPipe[1]);
00656 conditionalPipe[1] = 0;
00657 wait(NULL);
00658 int i;
00659
00660 if (conditionalShm->deliver > 0) {
00661
00662 for (i=0; i < conditionalShm->deliver; ++i) {
00663 int msgNum = conditionalShm->msgs[i];
00664 if (msgNum == -1) CpdDeliverSingleMessage();
00665 else CpdDeliverMessageInt(msgNum);
00666 }
00667
00668 for (i=conditionalShm->deliver; i < conditionalShm->count; ++i) {
00669 conditionalShm->msgs[i-conditionalShm->deliver] = conditionalShm->msgs[i];
00670 }
00671 conditionalShm->count -= conditionalShm->deliver;
00672 conditionalShm->deliver = 0;
00673 CmiMachineProgressImpl();
00674 }
00675 CkAssert(conditionalShm->count >= 0);
00676 if (conditionalShm->count == 0) {
00677 CcsSendReply(0,NULL);
00678 shmdt((char*)conditionalShm);
00679 conditionalShm = NULL;
00680 CkPrintf("Conditional delivery on %d concluded; normal mode resumed\n",CkMyPe());
00681 } else {
00682 if (CpdConditional_SetupComm()==0) {
00683
00684 _conditionalDelivery = 2;
00685 printf("new child: redelivering %d messages\n",conditionalShm->count);
00686 for (int i=0; i<conditionalShm->count; ++i) {
00687 int msgNum = conditionalShm->msgs[i];
00688 if (msgNum == -1) CpdDeliverSingleMessage();
00689 else CpdDeliverMessageInt(msgNum);
00690 }
00691 _conditionalDelivery = 1;
00692 CcsSendReply(0, NULL);
00693 }
00694 }
00695 }
00696
00697 void CpdDeliverMessageConditionally(char * msg) {
00698 int msgNum;
00699 void *m;
00700 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);
00701
00702
00703 if (CpdConditional_SetupComm()==0) {
00704 if (msgNum == -1) CpdDeliverSingleMessage();
00705 else CpdDeliverMessageInt(msgNum);
00706 }
00707 }
00708
00709 void CpdCommitConditionalDelivery(char * msg) {
00710 int msgNum;
00711 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &msgNum);\
00712 conditionalShm->deliver = msgNum;
00713 shmdt((char*)conditionalShm);
00714 _exit(0);
00715 }
00716
00717 class CpdList_msgStack : public CpdListAccessor {
00718 virtual const char * getPath(void) const {return "charm/messageStack";}
00719 virtual size_t getLength(void) const {
00720 return _debugData.length();
00721 }
00722 virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
00723 for (int i=0; i<_debugData.length(); ++i) {
00724 beginItem(p, i);
00725 void *obj = _debugData[i].obj;
00726 p.comment("obj");
00727 pup_pointer(&p, &obj);
00728 void *msg = _debugData[i].msg;
00729 p.comment("msg");
00730 pup_pointer(&p, &msg);
00731 }
00732 }
00733 };
00734
00735
00736
00737 typedef CkHashtableTslow<int,EntryInfo *> CpdBpFuncTable_t;
00738
00739 extern void CpdFreeze(void);
00740 extern void CpdUnFreeze(void);
00741 extern int CpdIsFrozen(void);
00742
00743 CpvStaticDeclare(int, _debugMsg);
00744 CpvStaticDeclare(int, _debugChare);
00745
00746 CpvStaticDeclare(CpdBpFuncTable_t *, breakPointEntryTable);
00747
00748
00749 CkpvStaticDeclare(void *, lastBreakPointObject);
00750 CkpvStaticDeclare(int, lastBreakPointIndex);
00751
00752 void CpdBreakPointInit()
00753 {
00754 CkpvInitialize(void *, lastBreakPointMsg);
00755 CkpvInitialize(void *, lastBreakPointObject);
00756 CkpvInitialize(int, lastBreakPointIndex);
00757 CpvInitialize(int, _debugMsg);
00758 CpvInitialize(int, _debugChare);
00759 CpvInitialize(CpdBpFuncTable_t *, breakPointEntryTable);
00760 CkpvAccess(lastBreakPointMsg) = NULL;
00761 CkpvAccess(lastBreakPointObject) = NULL;
00762 CkpvAccess(lastBreakPointIndex) = 0;
00763 CpvAccess(_debugMsg) = CkRegisterMsg("debug_msg",0,0,0,0);
00764 CpvAccess(_debugChare) = CkRegisterChare("debug_Chare",0,TypeChare);
00765 CkRegisterChareInCharm(CpvAccess(_debugChare));
00766 CpvAccess(breakPointEntryTable) = new CpdBpFuncTable_t(10,0.5,CkHashFunction_int,CkHashCompare_int );
00767 }
00768
00769 static void _call_freeze_on_break_point(void * msg, void * object)
00770 {
00771
00772
00773
00774
00775
00776 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkMessageToEpIdx(msg));
00777 if (CkpvAccess(skipBreakpoint) > 0 || CkpvAccess(_debugEntryTable)[CkMessageToEpIdx(msg)].isBreakpoint==CmiFalse) {
00778 CkAssert(breakPointEntryInfo != NULL);
00779 breakPointEntryInfo->call(msg, object);
00780 if (CkpvAccess(skipBreakpoint) > 0) CkpvAccess(skipBreakpoint) --;
00781 } else {
00782 CkpvAccess(lastBreakPointMsg) = msg;
00783 CkpvAccess(lastBreakPointObject) = object;
00784 CkpvAccess(lastBreakPointIndex) = CkMessageToEpIdx(msg);
00785 CpdNotify(CPD_BREAKPOINT,breakPointEntryInfo->name);
00786 CpdFreeze();
00787 #if CMK_BIGSIM_CHARM
00788 stopVTimer();
00789 ((workThreadInfo*)cta(threadinfo))->scheduler(-1);
00790 #endif
00791 }
00792 }
00793
00794
00795 extern "C"
00796 void CpdDeliverSingleMessage () {
00797 if (!CpdIsFrozen()) return;
00798 if ( (CkpvAccess(lastBreakPointMsg) != NULL) && (CkpvAccess(lastBreakPointObject) != NULL) ) {
00799 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkpvAccess(lastBreakPointIndex));
00800 if (breakPointEntryInfo != NULL) {
00801 if (_conditionalDelivery) {
00802 if (_conditionalDelivery==1) conditionalShm->msgs[conditionalShm->count++] = -1;
00803 void *env = UsrToEnv(CkpvAccess(lastBreakPointMsg));
00804 CmiReference(env);
00805 CdsFifo_Enqueue(CpvAccess(conditionalQueue),env);
00806 }
00807 breakPointEntryInfo->call(CkpvAccess(lastBreakPointMsg), CkpvAccess(lastBreakPointObject));
00808 }
00809 CkpvAccess(lastBreakPointMsg) = NULL;
00810 CkpvAccess(lastBreakPointObject) = NULL;
00811 #if CMK_BIGSIM_CHARM
00812 ((workThreadInfo*)cta(threadinfo))->stopScheduler();
00813 #endif
00814 }
00815 else {
00816
00817 if (!CdsFifo_Empty(CkpvAccess(debugQueue))) {
00818 CkpvAccess(skipBreakpoint) = 1;
00819 char *queuedMsg = (char *)CdsFifo_Dequeue(CkpvAccess(debugQueue));
00820 if (_conditionalDelivery) {
00821 if (_conditionalDelivery==1) conditionalShm->msgs[conditionalShm->count++] = 0;
00822 CmiReference(queuedMsg);
00823 CdsFifo_Enqueue(CpvAccess(conditionalQueue),queuedMsg);
00824 }
00825 #if CMK_BIGSIM_CHARM
00826 stopVTimer();
00827 BgProcessMessageDefault(cta(threadinfo), queuedMsg);
00828 startVTimer();
00829 #else
00830 CmiHandleMessage(queuedMsg);
00831 #endif
00832 CkpvAccess(skipBreakpoint) = 0;
00833 }
00834 }
00835 }
00836
00837
00838 extern "C"
00839 void CpdContinueFromBreakPoint ()
00840 {
00841 CpdUnFreeze();
00842 if ( (CkpvAccess(lastBreakPointMsg) != NULL) && (CkpvAccess(lastBreakPointObject) != NULL) )
00843 {
00844 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkpvAccess(lastBreakPointIndex));
00845 if (breakPointEntryInfo != NULL) {
00846 breakPointEntryInfo->call(CkpvAccess(lastBreakPointMsg), CkpvAccess(lastBreakPointObject));
00847 #if CMK_BIGSIM_CHARM
00848 ((workThreadInfo*)cta(threadinfo))->stopScheduler();
00849 #endif
00850 } else {
00851
00852
00853 }
00854 }
00855 CkpvAccess(lastBreakPointMsg) = NULL;
00856 CkpvAccess(lastBreakPointObject) = NULL;
00857 }
00858
00859
00860 void CpdSetBreakPoint (char *msg)
00861 {
00862 char functionName[128];
00863 int tableSize, tableIdx = 0;
00864 int reply = 0;
00865 sscanf(msg+CmiReservedHeaderSize, "%s", functionName);
00866 if (strlen(functionName) > 0)
00867 {
00868 tableSize = _entryTable.size();
00869
00870 tableIdx = atoi(functionName);
00871 if (tableIdx >= 0 && tableIdx < tableSize) {
00872 if (! CkpvAccess(_debugEntryTable)[tableIdx].isBreakpoint) {
00873 EntryInfo * breakPointEntryInfo = (EntryInfo *)CpvAccess(breakPointEntryTable)->get(tableIdx);
00874 if (breakPointEntryInfo == 0) {
00875 breakPointEntryInfo = new EntryInfo(_entryTable[tableIdx]->name, _entryTable[tableIdx]->call, 1, 0 );
00876
00877 CpvAccess(breakPointEntryTable)->put(tableIdx) = breakPointEntryInfo;
00878 _entryTable[tableIdx]->name = "debug_breakpoint_ep";
00879 _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
00880 } else {
00881 if (breakPointEntryInfo->msgIdx == 0) {
00882
00883 _entryTable[tableIdx]->name = "debug_breakpoint_ep";
00884 _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
00885 }
00886 breakPointEntryInfo->msgIdx ++;
00887
00888
00889
00890
00891 }
00892 CkpvAccess(_debugEntryTable)[tableIdx].isBreakpoint = CmiTrue;
00893 reply = ~0;
00894 }
00895 }
00896
00897 }
00898 CcsSendReply(sizeof(int), (void*)&reply);
00899
00900 }
00901
00902 void CpdQuitDebug()
00903 {
00904 CpdContinueFromBreakPoint();
00905 CkExit();
00906 }
00907
00908 void CpdRemoveBreakPoint (char *msg)
00909 {
00910 char functionName[128];
00911 int reply = 0;
00912 sscanf(msg+CmiReservedHeaderSize, "%s", functionName);
00913 if (strlen(functionName) > 0) {
00914 int idx = atoi(functionName);
00915 if (idx >= 0 && idx < _entryTable.size()) {
00916 if (CkpvAccess(_debugEntryTable)[idx].isBreakpoint) {
00917 EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(idx);
00918 if (breakPointEntryInfo != NULL) {
00919 if (--breakPointEntryInfo->msgIdx == 0) {
00920
00921 _entryTable[idx]->name = breakPointEntryInfo->name;
00922 _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
00923 }
00924 reply = ~0 ;
00925 CkpvAccess(_debugEntryTable)[idx].isBreakpoint = CmiFalse;
00926
00927
00928 }
00929 }
00930 }
00931 }
00932 CcsSendReply(sizeof(int), (void*)&reply);
00933 }
00934
00935 void CpdRemoveAllBreakPoints ()
00936 {
00937
00938 void *objPointer;
00939 void *keyPointer;
00940 int reply = 1;
00941 CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
00942 while(NULL!=(objPointer = it->next(&keyPointer)))
00943 {
00944 EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
00945 int idx = *(int *)keyPointer;
00946 if (--breakPointEntryInfo->msgIdx == 0) {
00947
00948 _entryTable[idx]->name = breakPointEntryInfo->name;
00949 _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
00950 }
00951 CkpvAccess(_debugEntryTable)[idx].isBreakpoint = CmiFalse;
00952 }
00953 CcsSendReply(sizeof(int), (void*)&reply);
00954 }
00955
00956 extern "C" int CpdIsCharmDebugMessage(void *msg) {
00957 envelope *env = (envelope*)msg;
00958
00959 return CmiGetHandler(msg) != _charmHandlerIdx || env->getMsgtype() == ForVidMsg ||
00960 env->getMsgtype() == FillVidMsg || _entryTable[env->getEpIdx()]->inCharm;
00961 }
00962
00963 #if CMK_BIGSIM_CHARM
00964 CpvExtern(int, _bgCcsHandlerIdx);
00965 extern "C" int CpdIsBgCharmDebugMessage(void *msg) {
00966 envelope *env = (envelope*)msg;
00967 if (CmiBgMsgFlag(msg) == BG_CLONE) {
00968 env=*(envelope**)(((char*)msg)+CmiBlueGeneMsgHeaderSizeBytes);
00969 }
00970 if ((((CmiBlueGeneMsgHeader*)env)->hID) == CpvAccess(_bgCcsHandlerIdx)) return 1;
00971
00972 if (CmiBgMsgHandle(env) == _charmHandlerIdx) {
00973 return env->getMsgtype() == ForVidMsg || env->getMsgtype() == FillVidMsg ||
00974 _entryTable[env->getEpIdx()]->inCharm;
00975 }
00976 return 1;
00977 }
00978 #endif
00979
00980 CpvExtern(char *, displayArgument);
00981
00982 void CpdStartGdb(void)
00983 {
00984 #if !defined(_WIN32) || defined(__CYGWIN__)
00985 FILE *f;
00986 char gdbScript[200];
00987 int pid;
00988 if (CpvAccess(displayArgument) != NULL)
00989 {
00990
00991 sprintf(gdbScript, "/tmp/cpdstartgdb.%d.%d", getpid(), CmiMyPe());
00992 f = fopen(gdbScript, "w");
00993 fprintf(f,"#!/bin/sh\n");
00994 fprintf(f,"cat > /tmp/start_gdb.$$ << END_OF_SCRIPT\n");
00995 fprintf(f,"shell /bin/rm -f /tmp/start_gdb.$$\n");
00996
00997 fprintf(f,"handle SIGWINCH nostop noprint\n");
00998 fprintf(f,"handle SIGWAITING nostop noprint\n");
00999 fprintf(f, "attach %d\n", getpid());
01000 fprintf(f,"END_OF_SCRIPT\n");
01001 fprintf(f, "DISPLAY='%s';export DISPLAY\n",CpvAccess(displayArgument));
01002 fprintf(f,"/usr/X11R6/bin/xterm ");
01003 fprintf(f," -title 'Node %d ' ",CmiMyPe());
01004 fprintf(f," -e /usr/bin/gdb -x /tmp/start_gdb.$$ \n");
01005 fprintf(f, "exit 0\n");
01006 fclose(f);
01007 if( -1 == chmod(gdbScript, 0755))
01008 {
01009 CmiPrintf("ERROR> chmod on script failed!\n");
01010 return;
01011 }
01012 pid = fork();
01013 if (pid < 0)
01014 { perror("ERROR> forking to run debugger script\n"); exit(1); }
01015 if (pid == 0)
01016 {
01017
01018 if (-1 == execvp(gdbScript, NULL))
01019 CmiPrintf ("Error> Could not Execute Debugger Script: %s\n",strerror
01020 (errno));
01021
01022 }
01023 }
01024 #endif
01025 }
01026
01027 extern "C" {
01028 size_t cpd_memory_length(void*);
01029 void cpd_memory_pup(void*,void*,CpdListItemsRequest*);
01030 void cpd_memory_leak(void*,void*,CpdListItemsRequest*);
01031 size_t cpd_memory_getLength(void*);
01032 void cpd_memory_get(void*,void*,CpdListItemsRequest*);
01033 }
01034
01035
01036 void CpdCharmInit()
01037 {
01038 CpdListRegister(new CpdListAccessor_c("memory/list",cpd_memory_length,0,cpd_memory_pup,0));
01039 CpdListRegister(new CpdListAccessor_c("memory/data",cpd_memory_getLength,0,cpd_memory_get,0,false));
01040
01041
01042 CcsRegisterHandler("debug/charm/bp/set",(CmiHandler)CpdSetBreakPoint);
01043 CcsSetMergeFn("debug/charm/bp/set",CcsMerge_logical_and);
01044 CcsRegisterHandler("debug/charm/bp/remove",(CmiHandler)CpdRemoveBreakPoint);
01045 CcsSetMergeFn("debug/charm/bp/remove",CcsMerge_logical_and);
01046 CcsRegisterHandler("debug/charm/bp/removeall",(CmiHandler)CpdRemoveAllBreakPoints);
01047 CcsSetMergeFn("debug/charm/bp/removeall",CmiReduceMergeFn_random);
01048 CcsRegisterHandler("debug/charm/continue",(CmiHandler)CpdContinueFromBreakPoint);
01049 CcsSetMergeFn("debug/charm/continue",CmiReduceMergeFn_random);
01050 CcsRegisterHandler("debug/charm/next",(CmiHandler)CpdDeliverSingleMessage);
01051 CcsSetMergeFn("debug/charm/next",CmiReduceMergeFn_random);
01052 CcsRegisterHandler("debug/converse/quit",(CmiHandler)CpdQuitDebug);
01053 CcsSetMergeFn("debug/converse/quit",CmiReduceMergeFn_random);
01054 CcsRegisterHandler("debug/converse/startgdb",(CmiHandler)CpdStartGdb);
01055 CpdListRegister(new CpdListAccessor_c("hostinfo",hostInfoLength,0,hostInfo,0));
01056 CpdListRegister(new CpdList_localQ());
01057 CcsRegisterHandler("debug/charm/deliver",(CmiHandler)CpdDeliverMessage);
01058 CcsRegisterHandler("debug/provisional/deliver",(CmiHandler)CpdDeliverMessageConditionally);
01059 CcsRegisterHandler("debug/provisional/rollback",(CmiHandler)CpdEndConditionalDelivery);
01060 CcsRegisterHandler("debug/provisional/commit",(CmiHandler)CpdCommitConditionalDelivery);
01061 CpdListRegister(new CpdList_arrayElementNames());
01062 CpdListRegister(new CpdList_arrayElements());
01063 CpdListRegister(new CpdList_objectNames());
01064 CpdListRegister(new CpdList_object());
01065 CpdListRegister(new CpdList_message());
01066 CpdListRegister(new CpdList_msgStack());
01067 CpdGetNextMessage = CsdNextMessage;
01068 CpdIsDebugMessage = CpdIsCharmDebugMessage;
01069 #if CMK_BIGSIM_CHARM
01070 CpdIsDebugMessage = CpdIsBgCharmDebugMessage;
01071 #endif
01072 }
01073
01074 #if CMK_BIGSIM_CHARM
01075 CpvExtern(int, _bgCcsHandlerIdx);
01076 CpvExtern(int, _bgCcsAck);
01077 extern "C" void req_fw_handler(char*);
01078 CkpvExtern(void *, debugQueue);
01079 CkpvExtern(int, freezeModeFlag);
01080 #include "blue_impl.h"
01081 extern void BgProcessMessageFreezeMode(threadInfo *, char *);
01082
01083 void CpdBgInit()
01084 {
01085
01086
01087
01088 int bgCcsHandlerIdx = CkRegisterHandler((CmiHandler)req_fw_handler);
01089 if (CpvAccess(_bgCcsHandlerIdx) == 0) CpvAccess(_bgCcsHandlerIdx) = bgCcsHandlerIdx;
01090 CkAssert(CpvAccess(_bgCcsHandlerIdx)==bgCcsHandlerIdx);
01091 CpvAccess(_bgCcsAck) ++;
01092 CcsReleaseMessages();
01093
01094 CkpvInitialize(int, freezeModeFlag);
01095 CkpvAccess(freezeModeFlag) = 0;
01096
01097 CkpvInitialize(void *, debugQueue);
01098 CkpvAccess(debugQueue) = CdsFifo_Create();
01099
01100 BgProcessMessage = BgProcessMessageFreezeMode;
01101 }
01102 #endif
01103
01104 #else
01105
01106 void CpdBreakPointInit() {}
01107 void CpdCharmInit() {}
01108 #if CMK_BIGSIM_CHARM
01109 void CpdBgInit() {}
01110 #endif
01111
01112 void CpdFinishInitialization() {}
01113
01114 void *CpdGetCurrentObject() {return NULL;}
01115 void *CpdGetCurrentMsg() {return NULL;}
01116 extern "C" void CpdEndConditionalDeliver_master() {}
01117
01118 void CpdBeforeEp(int ep, void *obj, void *msg) {}
01119 void CpdAfterEp(int ep) {}
01120
01121 #endif
01122