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