2 Converse-level debugger support
4 Collected from convcore.C, conv-ccs.C, register.C by
5 Orion Sky Lawlor, olawlor@acm.org, 4/10/2001
7 #include <stdio.h> /*for sscanf*/
8 #include <string.h> /*for strcmp*/
10 #include "conv-trace.h"
20 CpvCExtern(int, freezeModeFlag);
21 CpvStaticDeclare(int, continueFlag);
22 CpvStaticDeclare(int, stepFlag);
23 CpvCExtern(void *, debugQueue);
24 CpvDeclare(void*, conditionalQueue);
25 int conditionalPipe[2] = {0, 0};
30 /** Specify if we are replaying the processor from message logs, thus disable delivering of messages */
31 extern int _replaySystem;
32 int _replaySystem = 0;
33 int _conditionalDelivery = 0;
35 #undef ConverseDeliver
36 int ConverseDeliver(int pe) {
37 return !_replaySystem && (!_conditionalDelivery || pe==CmiMyPe());
42 uint32_t ntohl(uint32_t netlong) {
44 u_long ntohl(u_long netlong) {
46 union { uint32_t i; unsigned char c[4]; } uaw;
48 netlong = uaw.c[0]<<24 + uaw.c[1]<<16 + uaw.c[2]<<8 + uaw.c[3];
55 #include <arpa/inet.h>
56 #include <netinet/in.h>
60 /***************************************************
61 The CCS interface to the debugger
68 void check_memory_leaks(LeakSearchInfo *info);
70 CpvDeclare(int, CpdSearchLeaks_Index);
71 CpvDeclare(int, CpdSearchLeaksDone_Index);
72 CpvStaticDeclare(CcsDelayedReply, leakSearchDelayedReply);
74 void CpdSearchLeaksDone(void *msg) {
76 CcsSendDelayedReply(CpvAccess(leakSearchDelayedReply), 4, &ok);
80 void CpdSearchLeaks(char * msg) {
81 LeakSearchInfo *info = (LeakSearchInfo *)(msg+CmiMsgHeaderSizeBytes);
82 if (CmiMyPe() == info->pe || (info->pe == -1 && CmiMyPe() == 0)) {
84 info->begin_data = (char*)(
85 (((CmiUInt8)ntohl(((int*)&info->begin_data)[0]))<<32) + ntohl(((int*)&info->begin_data)[1]));
86 info->end_data = (char*)(
87 (((CmiUInt8)ntohl(((int*)&info->end_data)[0]))<<32) + ntohl(((int*)&info->end_data)[1]));
88 info->begin_bss = (char*)(
89 (((CmiUInt8)ntohl(((int*)&info->begin_bss)[0]))<<32) + ntohl(((int*)&info->begin_bss)[1]));
90 info->end_bss = (char*)(
91 (((CmiUInt8)ntohl(((int*)&info->end_bss)[0]))<<32) + ntohl(((int*)&info->end_bss)[1]));
93 info->begin_data = (char*)(ntohl((int)info->begin_data));
94 info->end_data = (char*)(ntohl((int)info->end_data));
95 info->begin_bss = (char*)(ntohl((int)info->begin_bss));
96 info->end_bss = (char*)(ntohl((int)info->end_bss));
98 info->quick = ntohl(info->quick);
99 info->pe = ntohl(info->pe);
100 CpvAccess(leakSearchDelayedReply) = CcsDelayReply();
101 if (info->pe == -1) {
102 CmiSetXHandler(msg, CpvAccess(CpdSearchLeaks_Index));
103 CmiSetHandler(msg, _debugHandlerIdx);
104 CmiSyncBroadcast(CmiMsgHeaderSizeBytes+sizeof(LeakSearchInfo), msg);
107 check_memory_leaks(info);
108 if (info->pe == CmiMyPe()) CpdSearchLeaksDone(msg);
109 else if (info->pe == -1) {
110 void *reduceMsg = CmiAlloc(0);
111 CmiSetHandler(reduceMsg, CpvAccess(CpdSearchLeaksDone_Index));
112 CmiReduce(reduceMsg, CmiMsgHeaderSizeBytes, CmiReduceMergeFn_random);
115 else CmiAbort("Received allocationTree request for another PE!");
118 void * (*CpdDebugGetAllocationTree)(int *) = NULL;
119 void (*CpdDebug_pupAllocationPoint)(pup_er p, void *data) = NULL;
120 void (*CpdDebug_deleteAllocationPoint)(void *ptr) = NULL;
121 void * (*CpdDebug_MergeAllocationTree)(int *size, void *data, void **remoteData, int numRemote) = NULL;
122 CpvDeclare(int, CpdDebugCallAllocationTree_Index);
123 CpvStaticDeclare(CcsDelayedReply, allocationTreeDelayedReply);
125 static void CpdDebugReturnAllocationTree(void *tree) {
126 pup_er sizer = pup_new_sizer();
130 CpdDebug_pupAllocationPoint(sizer, tree);
131 buf = (char *)malloc(pup_size(sizer));
132 packer = pup_new_toMem(buf);
133 CpdDebug_pupAllocationPoint(packer, tree);
134 /*CmiPrintf("size=%d tree:",pup_size(sizer));
135 for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
137 CcsSendDelayedReply(CpvAccess(allocationTreeDelayedReply), pup_size(sizer),buf);
143 static void CpdDebugCallAllocationTree(char *msg)
148 if (CpdDebugGetAllocationTree == NULL) {
149 CmiPrintf("Error> Invoked CpdDebugCalloAllocationTree but no function initialized.\nDid you forget to link in memory charmdebug?\n");
150 CcsSendReply(0, NULL);
153 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
154 if (CmiMyPe() == forPE) CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
155 if (forPE == -1 && CmiMyPe()==0) {
156 CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
157 CmiSetXHandler(msg, CpvAccess(CpdDebugCallAllocationTree_Index));
158 CmiSetHandler(msg, _debugHandlerIdx);
159 CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
161 tree = CpdDebugGetAllocationTree(&numNodes);
162 if (forPE == CmiMyPe()) CpdDebugReturnAllocationTree(tree);
163 else if (forPE == -1) CmiReduceStruct(tree, CpdDebug_pupAllocationPoint, CpdDebug_MergeAllocationTree,
164 CpdDebugReturnAllocationTree, CpdDebug_deleteAllocationPoint);
165 else CmiAbort("Received allocationTree request for another PE!");
169 void * (*CpdDebugGetMemStat)(void) = NULL;
170 void (*CpdDebug_pupMemStat)(pup_er p, void *data) = NULL;
171 void (*CpdDebug_deleteMemStat)(void *ptr) = NULL;
172 void * (*CpdDebug_mergeMemStat)(int *size, void *data, void **remoteData, int numRemote) = NULL;
173 CpvDeclare(int, CpdDebugCallMemStat_Index);
174 CpvStaticDeclare(CcsDelayedReply, memStatDelayedReply);
176 static void CpdDebugReturnMemStat(void *stat) {
177 #if CMK_CCS_AVAILABLE
178 pup_er sizerNet = pup_new_network_sizer();
179 pup_er sizer = pup_new_fmt(sizerNet);
184 CpdDebug_pupMemStat(sizer, stat);
185 buf = (char *)malloc(pup_size(sizer));
186 packerNet = pup_new_network_pack(buf);
187 packer = pup_new_fmt(packerNet);
188 CpdDebug_pupMemStat(packer, stat);
189 /*CmiPrintf("size=%d tree:",pup_size(sizer));
190 for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
192 CcsSendDelayedReply(CpvAccess(memStatDelayedReply), pup_size(sizer),buf);
193 pup_destroy(sizerNet);
195 pup_destroy(packerNet);
201 static void CpdDebugCallMemStat(char *msg) {
204 if (CpdDebugGetMemStat == NULL) {
205 CmiPrintf("Error> Invoked CpdDebugCalloMemStat but no function initialized.\nDid you forget to link in memory charmdebug?\n");
206 CcsSendReply(0, NULL);
209 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
210 if (CmiMyPe() == forPE) CpvAccess(memStatDelayedReply) = CcsDelayReply();
211 if (forPE == -1 && CmiMyPe()==0) {
212 CpvAccess(memStatDelayedReply) = CcsDelayReply();
213 CmiSetXHandler(msg, CpvAccess(CpdDebugCallMemStat_Index));
214 CmiSetHandler(msg, _debugHandlerIdx);
215 CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
217 stat = CpdDebugGetMemStat();
218 if (forPE == CmiMyPe()) CpdDebugReturnMemStat(stat);
219 else if (forPE == -1) CmiReduceStruct(stat, CpdDebug_pupMemStat, CpdDebug_mergeMemStat,
220 CpdDebugReturnMemStat, CpdDebug_deleteMemStat);
221 else CmiAbort("Received allocationTree request for another PE!");
225 static void CpdDebugHandlerStatus(char *msg) {
227 ChMessageInt_t reply[2];
228 reply[0] = ChMessageInt_new(CmiMyPe());
229 reply[1] = ChMessageInt_new(CpdIsFrozen() ? 0 : 1);
230 CcsSendReply(2*sizeof(ChMessageInt_t), reply);
235 static void CpdDebugHandlerFreeze(char *msg) {
241 /* Deliver a single message in the queue while not unfreezing the program */
246 /* This converse handler is used by the debugger itself, to send messages
247 * even when the scheduler is in freeze mode.
249 void handleDebugMessage(void *msg) {
250 CmiSetHandler(msg, CmiGetXHandler(msg));
251 CmiHandleMessage(msg);
254 /* Special scheduler-type loop only executed while in
255 freeze mode-- only executes CCS requests.
257 void CcsServerCheck(void);
258 extern int _isCcsHandlerIdx(int idx);
259 int (*CpdIsDebugMessage)(void *);
260 void * (*CpdGetNextMessage)(CsdSchedulerState_t*);
262 void CpdFreezeModeScheduler(void)
265 CmiAbort("Cannot run CpdFreezeModeScheduler inside BigSim emulated environment");
267 #if CMK_CCS_AVAILABLE
269 void *debugQ=CpvAccess(debugQueue);
270 CsdSchedulerState_t state;
271 CsdSchedulerState_new(&state);
273 /* While frozen, queue up messages */
274 while (CpvAccess(freezeModeFlag)) {
275 #if NODE_0_IS_CONVHOST
276 if (CmiMyPe()==0) CcsServerCheck(); /*Make sure we can get CCS messages*/
278 msg = CpdGetNextMessage(&state);
281 /*int hIdx=CmiGetHandler(msg);*/
283 if(_isCcsHandlerIdx(hIdx))
284 / *A CCS request-- handle it immediately* /
286 CmiHandleMessage(msg);
288 else if (hIdx == _debugHandlerIdx ||
289 (hIdx == CmiGetReductionHandler() && CmiGetReductionDestination() == CpdDebugReturnAllocationTree)) {
290 / * Debug messages should be handled immediately * /
291 CmiHandleMessage(msg);
293 if (conditionalPipe[1]!=0 && _conditionalDelivery==0) {
294 // Since we are conditionally delivering, forward all messages to the child
295 int bytes = SIZEFIELD(msg); // reqLen+((int)(reqData-((char*)hdr)))+CmiReservedHeaderSize;
296 if (write(conditionalPipe[1], &bytes, 4) != 4) {
297 CmiAbort("Writing msg len to child failed!");
299 if (write(conditionalPipe[1], msg, bytes) != bytes) {
300 CmiAbort("Writing msg data to child failed!");
303 if (CpdIsDebugMessage(msg)) {
304 CmiHandleMessage(msg);
307 /*An ordinary charm++ message-- queue it up*/
308 CdsFifo_Enqueue(debugQ, msg);
309 } else CmiNotifyIdle();
311 /* Before leaving freeze mode, execute the messages
312 in the order they would have executed before.*/
313 while (!CdsFifo_Empty(debugQ))
315 char *queuedMsg = (char *)CdsFifo_Dequeue(debugQ);
316 CmiHandleMessage(queuedMsg);
322 void CpdMemoryMarkClean(char *msg);
326 #if ! CMK_BIGSIM_CHARM
327 CpvInitialize(int, freezeModeFlag);
328 CpvAccess(freezeModeFlag) = 0;
330 CpvInitialize(void *, debugQueue);
331 CpvAccess(debugQueue) = CdsFifo_Create();
334 CpvInitialize(void *, conditionalQueue);
335 CpvAccess(conditionalQueue) = CdsFifo_Create();
337 CcsRegisterHandler("debug/converse/freeze", (CmiHandler)CpdDebugHandlerFreeze);
338 CcsRegisterHandler("debug/converse/status", (CmiHandler)CpdDebugHandlerStatus);
339 CcsSetMergeFn("debug/converse/status", CcsMerge_concat);
341 CcsRegisterHandler("debug/memory/allocationTree", (CmiHandler)CpdDebugCallAllocationTree);
342 CpvInitialize(int, CpdDebugCallAllocationTree_Index);
343 CpvAccess(CpdDebugCallAllocationTree_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallAllocationTree);
345 CcsRegisterHandler("debug/memory/stat", (CmiHandler)CpdDebugCallMemStat);
346 CpvInitialize(int, CpdDebugCallMemStat_Index);
347 CpvAccess(CpdDebugCallMemStat_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallMemStat);
349 CcsRegisterHandler("debug/memory/leak",(CmiHandler)CpdSearchLeaks);
350 CpvInitialize(int, CpdSearchLeaks_Index);
351 CpvAccess(CpdSearchLeaks_Index) = CmiRegisterHandler((CmiHandler)CpdSearchLeaks);
352 CpvInitialize(int, CpdSearchLeaksDone_Index);
353 CpvAccess(CpdSearchLeaksDone_Index) = CmiRegisterHandler((CmiHandler)CpdSearchLeaksDone);
355 CcsRegisterHandler("debug/memory/mark",(CmiHandler)CpdMemoryMarkClean);
356 CcsSetMergeFn("debug/memory/mark", CcsMerge_concat);
358 _debugHandlerIdx = CmiRegisterHandler((CmiHandler)handleDebugMessage);
360 CpdInitializeObjectTable();
361 CpdInitializeHandlerArray();
362 CpdInitializeBreakPoints();
364 /* To allow start in freeze state: */
371 /* If CharmDebug is attached, try to send it a message and wait */
372 void CpdAborting(const char *message) {
373 #if CMK_CCS_AVAILABLE
374 if (CpvAccess(cmiArgDebugFlag)) {
375 CpdNotify(CPD_ABORT, message);