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 CMI_EXTERNC_VARIABLE int _replaySystem;
32 int _replaySystem = 0;
33 int _conditionalDelivery = 0;
35 #undef ConverseDeliver
37 int ConverseDeliver(int pe) {
38 return !_replaySystem && (!_conditionalDelivery || pe==CmiMyPe());
43 uint32_t ntohl(uint32_t netlong) {
45 u_long ntohl(u_long netlong) {
47 union { uint32_t i; unsigned char c[4]; } uaw;
49 netlong = uaw.c[0]<<24 + uaw.c[1]<<16 + uaw.c[2]<<8 + uaw.c[3];
56 #include <arpa/inet.h>
57 #include <netinet/in.h>
61 /***************************************************
62 The CCS interface to the debugger
70 void check_memory_leaks(LeakSearchInfo *info);
72 CpvDeclare(int, CpdSearchLeaks_Index);
73 CpvDeclare(int, CpdSearchLeaksDone_Index);
74 CpvStaticDeclare(CcsDelayedReply, leakSearchDelayedReply);
76 void CpdSearchLeaksDone(void *msg) {
78 CcsSendDelayedReply(CpvAccess(leakSearchDelayedReply), 4, &ok);
82 void CpdSearchLeaks(char * msg) {
83 LeakSearchInfo *info = (LeakSearchInfo *)(msg+CmiMsgHeaderSizeBytes);
84 if (CmiMyPe() == info->pe || (info->pe == -1 && CmiMyPe() == 0)) {
86 info->begin_data = (char*)(
87 (((CmiUInt8)ntohl(((int*)&info->begin_data)[0]))<<32) + ntohl(((int*)&info->begin_data)[1]));
88 info->end_data = (char*)(
89 (((CmiUInt8)ntohl(((int*)&info->end_data)[0]))<<32) + ntohl(((int*)&info->end_data)[1]));
90 info->begin_bss = (char*)(
91 (((CmiUInt8)ntohl(((int*)&info->begin_bss)[0]))<<32) + ntohl(((int*)&info->begin_bss)[1]));
92 info->end_bss = (char*)(
93 (((CmiUInt8)ntohl(((int*)&info->end_bss)[0]))<<32) + ntohl(((int*)&info->end_bss)[1]));
95 info->begin_data = (char*)(ntohl((int)info->begin_data));
96 info->end_data = (char*)(ntohl((int)info->end_data));
97 info->begin_bss = (char*)(ntohl((int)info->begin_bss));
98 info->end_bss = (char*)(ntohl((int)info->end_bss));
100 info->quick = ntohl(info->quick);
101 info->pe = ntohl(info->pe);
102 CpvAccess(leakSearchDelayedReply) = CcsDelayReply();
103 if (info->pe == -1) {
104 CmiSetXHandler(msg, CpvAccess(CpdSearchLeaks_Index));
105 CmiSetHandler(msg, _debugHandlerIdx);
106 CmiSyncBroadcast(CmiMsgHeaderSizeBytes+sizeof(LeakSearchInfo), msg);
109 check_memory_leaks(info);
110 if (info->pe == CmiMyPe()) CpdSearchLeaksDone(msg);
111 else if (info->pe == -1) {
112 void *reduceMsg = CmiAlloc(0);
113 CmiSetHandler(reduceMsg, CpvAccess(CpdSearchLeaksDone_Index));
114 CmiReduce(reduceMsg, CmiMsgHeaderSizeBytes, CmiReduceMergeFn_random);
117 else CmiAbort("Received allocationTree request for another PE!");
120 void * (*CpdDebugGetAllocationTree)(int *) = NULL;
121 void (*CpdDebug_pupAllocationPoint)(pup_er p, void *data) = NULL;
122 void (*CpdDebug_deleteAllocationPoint)(void *ptr) = NULL;
123 void * (*CpdDebug_MergeAllocationTree)(int *size, void *data, void **remoteData, int numRemote) = NULL;
124 CpvDeclare(int, CpdDebugCallAllocationTree_Index);
125 CpvStaticDeclare(CcsDelayedReply, allocationTreeDelayedReply);
127 static void CpdDebugReturnAllocationTree(void *tree) {
128 pup_er sizer = pup_new_sizer();
132 CpdDebug_pupAllocationPoint(sizer, tree);
133 buf = (char *)malloc(pup_size(sizer));
134 packer = pup_new_toMem(buf);
135 CpdDebug_pupAllocationPoint(packer, tree);
136 /*CmiPrintf("size=%d tree:",pup_size(sizer));
137 for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
139 CcsSendDelayedReply(CpvAccess(allocationTreeDelayedReply), pup_size(sizer),buf);
145 static void CpdDebugCallAllocationTree(char *msg)
150 if (CpdDebugGetAllocationTree == NULL) {
151 CmiPrintf("Error> Invoked CpdDebugCalloAllocationTree but no function initialized.\nDid you forget to link in memory charmdebug?\n");
152 CcsSendReply(0, NULL);
155 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
156 if (CmiMyPe() == forPE) CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
157 if (forPE == -1 && CmiMyPe()==0) {
158 CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
159 CmiSetXHandler(msg, CpvAccess(CpdDebugCallAllocationTree_Index));
160 CmiSetHandler(msg, _debugHandlerIdx);
161 CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
163 tree = CpdDebugGetAllocationTree(&numNodes);
164 if (forPE == CmiMyPe()) CpdDebugReturnAllocationTree(tree);
165 else if (forPE == -1) CmiReduceStruct(tree, CpdDebug_pupAllocationPoint, CpdDebug_MergeAllocationTree,
166 CpdDebugReturnAllocationTree, CpdDebug_deleteAllocationPoint);
167 else CmiAbort("Received allocationTree request for another PE!");
171 void * (*CpdDebugGetMemStat)(void) = NULL;
172 void (*CpdDebug_pupMemStat)(pup_er p, void *data) = NULL;
173 void (*CpdDebug_deleteMemStat)(void *ptr) = NULL;
174 void * (*CpdDebug_mergeMemStat)(int *size, void *data, void **remoteData, int numRemote) = NULL;
175 CpvDeclare(int, CpdDebugCallMemStat_Index);
176 CpvStaticDeclare(CcsDelayedReply, memStatDelayedReply);
178 static void CpdDebugReturnMemStat(void *stat) {
179 #if CMK_CCS_AVAILABLE
180 pup_er sizerNet = pup_new_network_sizer();
181 pup_er sizer = pup_new_fmt(sizerNet);
186 CpdDebug_pupMemStat(sizer, stat);
187 buf = (char *)malloc(pup_size(sizer));
188 packerNet = pup_new_network_pack(buf);
189 packer = pup_new_fmt(packerNet);
190 CpdDebug_pupMemStat(packer, stat);
191 /*CmiPrintf("size=%d tree:",pup_size(sizer));
192 for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
194 CcsSendDelayedReply(CpvAccess(memStatDelayedReply), pup_size(sizer),buf);
195 pup_destroy(sizerNet);
197 pup_destroy(packerNet);
203 static void CpdDebugCallMemStat(char *msg) {
206 if (CpdDebugGetMemStat == NULL) {
207 CmiPrintf("Error> Invoked CpdDebugCalloMemStat but no function initialized.\nDid you forget to link in memory charmdebug?\n");
208 CcsSendReply(0, NULL);
211 sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
212 if (CmiMyPe() == forPE) CpvAccess(memStatDelayedReply) = CcsDelayReply();
213 if (forPE == -1 && CmiMyPe()==0) {
214 CpvAccess(memStatDelayedReply) = CcsDelayReply();
215 CmiSetXHandler(msg, CpvAccess(CpdDebugCallMemStat_Index));
216 CmiSetHandler(msg, _debugHandlerIdx);
217 CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
219 stat = CpdDebugGetMemStat();
220 if (forPE == CmiMyPe()) CpdDebugReturnMemStat(stat);
221 else if (forPE == -1) CmiReduceStruct(stat, CpdDebug_pupMemStat, CpdDebug_mergeMemStat,
222 CpdDebugReturnMemStat, CpdDebug_deleteMemStat);
223 else CmiAbort("Received allocationTree request for another PE!");
227 static void CpdDebugHandlerStatus(char *msg) {
229 ChMessageInt_t reply[2];
230 reply[0] = ChMessageInt_new(CmiMyPe());
231 reply[1] = ChMessageInt_new(CpdIsFrozen() ? 0 : 1);
232 CcsSendReply(2*sizeof(ChMessageInt_t), reply);
237 static void CpdDebugHandlerFreeze(char *msg) {
243 /* Deliver a single message in the queue while not unfreezing the program */
248 /* This converse handler is used by the debugger itself, to send messages
249 * even when the scheduler is in freeze mode.
251 void handleDebugMessage(void *msg) {
252 CmiSetHandler(msg, CmiGetXHandler(msg));
253 CmiHandleMessage(msg);
256 /* Special scheduler-type loop only executed while in
257 freeze mode-- only executes CCS requests.
260 void CcsServerCheck(void);
261 extern int _isCcsHandlerIdx(int idx);
262 int (*CpdIsDebugMessage)(void *);
263 void * (*CpdGetNextMessage)(CsdSchedulerState_t*);
265 void CpdFreezeModeScheduler(void)
268 CmiAbort("Cannot run CpdFreezeModeScheduler inside BigSim emulated environment");
270 #if CMK_CCS_AVAILABLE
272 void *debugQ=CpvAccess(debugQueue);
273 CsdSchedulerState_t state;
274 CsdSchedulerState_new(&state);
276 /* While frozen, queue up messages */
277 while (CpvAccess(freezeModeFlag)) {
278 #if NODE_0_IS_CONVHOST
279 if (CmiMyPe()==0) CcsServerCheck(); /*Make sure we can get CCS messages*/
281 msg = CpdGetNextMessage(&state);
284 /*int hIdx=CmiGetHandler(msg);*/
286 if(_isCcsHandlerIdx(hIdx))
287 / *A CCS request-- handle it immediately* /
289 CmiHandleMessage(msg);
291 else if (hIdx == _debugHandlerIdx ||
292 (hIdx == CmiGetReductionHandler() && CmiGetReductionDestination() == CpdDebugReturnAllocationTree)) {
293 / * Debug messages should be handled immediately * /
294 CmiHandleMessage(msg);
296 if (conditionalPipe[1]!=0 && _conditionalDelivery==0) {
297 // Since we are conditionally delivering, forward all messages to the child
298 int bytes = SIZEFIELD(msg); // reqLen+((int)(reqData-((char*)hdr)))+CmiReservedHeaderSize;
299 if (write(conditionalPipe[1], &bytes, 4) != 4) {
300 CmiAbort("Writing msg len to child failed!");
302 if (write(conditionalPipe[1], msg, bytes) != bytes) {
303 CmiAbort("Writing msg data to child failed!");
306 if (CpdIsDebugMessage(msg)) {
307 CmiHandleMessage(msg);
310 /*An ordinary charm++ message-- queue it up*/
311 CdsFifo_Enqueue(debugQ, msg);
312 } else CmiNotifyIdle();
314 /* Before leaving freeze mode, execute the messages
315 in the order they would have executed before.*/
316 while (!CdsFifo_Empty(debugQ))
318 char *queuedMsg = (char *)CdsFifo_Dequeue(debugQ);
319 CmiHandleMessage(queuedMsg);
326 void CpdMemoryMarkClean(char *msg);
330 #if ! CMK_BIGSIM_CHARM
331 CpvInitialize(int, freezeModeFlag);
332 CpvAccess(freezeModeFlag) = 0;
334 CpvInitialize(void *, debugQueue);
335 CpvAccess(debugQueue) = CdsFifo_Create();
338 CpvInitialize(void *, conditionalQueue);
339 CpvAccess(conditionalQueue) = CdsFifo_Create();
341 CcsRegisterHandler("debug/converse/freeze", (CmiHandler)CpdDebugHandlerFreeze);
342 CcsRegisterHandler("debug/converse/status", (CmiHandler)CpdDebugHandlerStatus);
343 CcsSetMergeFn("debug/converse/status", CcsMerge_concat);
345 CcsRegisterHandler("debug/memory/allocationTree", (CmiHandler)CpdDebugCallAllocationTree);
346 CpvInitialize(int, CpdDebugCallAllocationTree_Index);
347 CpvAccess(CpdDebugCallAllocationTree_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallAllocationTree);
349 CcsRegisterHandler("debug/memory/stat", (CmiHandler)CpdDebugCallMemStat);
350 CpvInitialize(int, CpdDebugCallMemStat_Index);
351 CpvAccess(CpdDebugCallMemStat_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallMemStat);
353 CcsRegisterHandler("debug/memory/leak",(CmiHandler)CpdSearchLeaks);
354 CpvInitialize(int, CpdSearchLeaks_Index);
355 CpvAccess(CpdSearchLeaks_Index) = CmiRegisterHandler((CmiHandler)CpdSearchLeaks);
356 CpvInitialize(int, CpdSearchLeaksDone_Index);
357 CpvAccess(CpdSearchLeaksDone_Index) = CmiRegisterHandler((CmiHandler)CpdSearchLeaksDone);
359 CcsRegisterHandler("debug/memory/mark",(CmiHandler)CpdMemoryMarkClean);
360 CcsSetMergeFn("debug/memory/mark", CcsMerge_concat);
362 _debugHandlerIdx = CmiRegisterHandler((CmiHandler)handleDebugMessage);
364 CpdInitializeObjectTable();
365 CpdInitializeHandlerArray();
366 CpdInitializeBreakPoints();
368 /* To allow start in freeze state: */
375 /* If CharmDebug is attached, try to send it a message and wait */
376 void CpdAborting(const char *message) {
377 #if CMK_CCS_AVAILABLE
378 if (CpvAccess(cmiArgDebugFlag)) {
379 CpdNotify(CPD_ABORT, message);