5fee4712835c988657549157105c092824f913fc
[charm.git] / src / conv-core / debug-conv.c
1 /*
2 Converse-level debugger support
3
4 Collected from convcore.c, conv-ccs.c, register.c by
5 Orion Sky Lawlor, olawlor@acm.org, 4/10/2001
6  */
7 #include <stdio.h> /*for sscanf*/
8 #include <string.h> /*for strcmp*/
9 #include "converse.h"
10 #include "conv-trace.h"
11 #include "queueing.h"
12 #include "conv-ccs.h"
13 #include <errno.h>
14
15 CpvExtern(int, freezeModeFlag);
16 CpvStaticDeclare(int, continueFlag);
17 CpvStaticDeclare(int, stepFlag);
18 CpvExtern(void *, debugQueue);
19 int _debugHandlerIdx;
20
21 char ** memoryBackup;
22
23 /** Specify if we are replaying the processor from message logs, thus disable delivering of messages */
24 int _replaySystem = 0;
25
26 #undef ConverseDeliver
27 int ConverseDeliver() {
28   return !_replaySystem;
29 }
30
31 #if ! CMK_HAS_NTOHL
32 uint32_t ntohl(uint32_t netlong) {
33   union { uint32_t i; unsigned char c[4]; } uaw;
34   uaw.i = netlong;
35   netlong = uaw.c[0]<<24 + uaw.c[1]<<16 + uaw.c[2]<<8 + uaw.c[3];
36   return netlong;
37 }
38 #endif
39
40 /***************************************************
41   The CCS interface to the debugger
42 */
43
44 #include <string.h>
45
46 #include "pup_c.h"
47
48 CpvDeclare(int, CpdSearchLeaks_Index);
49 CpvDeclare(int, CpdSearchLeaksDone_Index);
50 CpvStaticDeclare(CcsDelayedReply, leakSearchDelayedReply);
51
52 void CpdSearchLeaksDone(void *msg) {
53   CmiInt4 ok = 1;
54   CcsSendDelayedReply(CpvAccess(leakSearchDelayedReply), 4, &ok);
55   CmiFree(msg);
56 }
57
58 void CpdSearchLeaks(char * msg) {
59   LeakSearchInfo *info = (LeakSearchInfo *)(msg+CmiMsgHeaderSizeBytes);
60   if (CmiMyPe() == info->pe || (info->pe == -1 && CmiMyPe() == 0)) {
61     if (sizeof(char*) == 8) {
62       info->begin_data = (((CmiUInt8)ntohl(((int*)&info->begin_data)[0]))<<32) + ntohl(((int*)&info->begin_data)[1]);
63       info->end_data = (((CmiUInt8)ntohl(((int*)&info->end_data)[0]))<<32) + ntohl(((int*)&info->end_data)[1]);
64       info->begin_bss = (((CmiUInt8)ntohl(((int*)&info->begin_bss)[0]))<<32) + ntohl(((int*)&info->begin_bss)[1]);
65       info->end_bss = (((CmiUInt8)ntohl(((int*)&info->end_bss)[0]))<<32) + ntohl(((int*)&info->end_bss)[1]);
66     } else {
67       info->begin_data = ntohl((int)info->begin_data);
68       info->end_data = ntohl((int)info->end_data);
69       info->begin_bss = ntohl((int)info->begin_bss);
70       info->end_bss = (char*)(size_t)ntohl((size_t)info->end_bss);
71     }
72     info->quick = ntohl(info->quick);
73     info->pe = ntohl(info->pe);
74     CpvAccess(leakSearchDelayedReply) = CcsDelayReply();
75     if (info->pe == -1) {
76       CmiSetXHandler(msg, CpvAccess(CpdSearchLeaks_Index));
77       CmiSetHandler(msg, _debugHandlerIdx);
78       CmiSyncBroadcast(CmiMsgHeaderSizeBytes+sizeof(LeakSearchInfo), msg);
79     }
80   }
81   check_memory_leaks(info);
82   if (info->pe == CmiMyPe()) CpdSearchLeaksDone(msg);
83   else if (info->pe == -1) {
84     void *reduceMsg = CmiAlloc(0);
85     CmiSetHandler(reduceMsg, CpvAccess(CpdSearchLeaksDone_Index));
86     CmiReduce(reduceMsg, CmiMsgHeaderSizeBytes, CmiReduceMergeFn_random);
87     CmiFree(msg);
88   }
89   else CmiAbort("Received allocationTree request for another PE!");
90 }
91
92 void * (*CpdDebugGetAllocationTree)(int *) = NULL;
93 void (*CpdDebug_pupAllocationPoint)(pup_er p, void *data) = NULL;
94 void (*CpdDebug_deleteAllocationPoint)(void *ptr) = NULL;
95 void * (*CpdDebug_MergeAllocationTree)(int *size, void *data, void **remoteData, int numRemote) = NULL;
96 CpvDeclare(int, CpdDebugCallAllocationTree_Index);
97 CpvStaticDeclare(CcsDelayedReply, allocationTreeDelayedReply);
98
99 static void CpdDebugReturnAllocationTree(void *tree) {
100   pup_er sizer = pup_new_sizer();
101   char *buf;
102   pup_er packer;
103   int i;
104   CpdDebug_pupAllocationPoint(sizer, tree);
105   buf = (char *)malloc(pup_size(sizer));
106   packer = pup_new_toMem(buf);
107   CpdDebug_pupAllocationPoint(packer, tree);
108   /*CmiPrintf("size=%d tree:",pup_size(sizer));
109   for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
110   CmiPrintf("\n");*/
111   CcsSendDelayedReply(CpvAccess(allocationTreeDelayedReply), pup_size(sizer),buf);
112   pup_destroy(sizer);
113   pup_destroy(packer);
114   free(buf);
115 }
116
117 static void CpdDebugCallAllocationTree(char *msg)
118 {
119   int numNodes;
120   int forPE;
121   void *tree;
122   if (CpdDebugGetAllocationTree == NULL) {
123     CmiPrintf("Error> Invoked CpdDebugCalloAllocationTree but no function initialized.\nDid you forget to link in memory charmdebug?\n");
124     CcsSendReply(0, NULL);
125     return;
126   }
127   sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
128   if (CmiMyPe() == forPE) CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
129   if (forPE == -1 && CmiMyPe()==0) {
130     CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
131     CmiSetXHandler(msg, CpvAccess(CpdDebugCallAllocationTree_Index));
132     CmiSetHandler(msg, _debugHandlerIdx);
133     CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
134   }
135   tree = CpdDebugGetAllocationTree(&numNodes);
136   if (forPE == CmiMyPe()) CpdDebugReturnAllocationTree(tree);
137   else if (forPE == -1) CmiReduceStruct(tree, CpdDebug_pupAllocationPoint, CpdDebug_MergeAllocationTree,
138                                 CpdDebugReturnAllocationTree, CpdDebug_deleteAllocationPoint);
139   else CmiAbort("Received allocationTree request for another PE!");
140   CmiFree(msg);
141 }
142
143 void * (*CpdDebugGetMemStat)(void) = NULL;
144 void (*CpdDebug_pupMemStat)(pup_er p, void *data) = NULL;
145 void (*CpdDebug_deleteMemStat)(void *ptr) = NULL;
146 void * (*CpdDebug_mergeMemStat)(int *size, void *data, void **remoteData, int numRemote) = NULL;
147 CpvDeclare(int, CpdDebugCallMemStat_Index);
148 CpvStaticDeclare(CcsDelayedReply, memStatDelayedReply);
149
150 static void CpdDebugReturnMemStat(void *stat) {
151 #if CMK_CCS_AVAILABLE
152   pup_er sizerNet = pup_new_network_sizer();
153   pup_er sizer = pup_new_fmt(sizerNet);
154   char *buf;
155   pup_er packerNet;
156   pup_er packer;
157   int i;
158   CpdDebug_pupMemStat(sizer, stat);
159   buf = (char *)malloc(pup_size(sizer));
160   packerNet = pup_new_network_pack(buf);
161   packer = pup_new_fmt(packerNet);
162   CpdDebug_pupMemStat(packer, stat);
163   /*CmiPrintf("size=%d tree:",pup_size(sizer));
164   for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
165   CmiPrintf("\n");*/
166   CcsSendDelayedReply(CpvAccess(memStatDelayedReply), pup_size(sizer),buf);
167   pup_destroy(sizerNet);
168   pup_destroy(sizer);
169   pup_destroy(packerNet);
170   pup_destroy(packer);
171   free(buf);
172 #endif
173 }
174
175 static void CpdDebugCallMemStat(char *msg) {
176   int forPE;
177   void *stat;
178   if (CpdDebugGetMemStat == NULL) {
179     CmiPrintf("Error> Invoked CpdDebugCalloMemStat but no function initialized.\nDid you forget to link in memory charmdebug?\n");
180     CcsSendReply(0, NULL);
181     return;
182   }
183   sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
184   if (CmiMyPe() == forPE) CpvAccess(memStatDelayedReply) = CcsDelayReply();
185   if (forPE == -1 && CmiMyPe()==0) {
186     CpvAccess(memStatDelayedReply) = CcsDelayReply();
187     CmiSetXHandler(msg, CpvAccess(CpdDebugCallMemStat_Index));
188     CmiSetHandler(msg, _debugHandlerIdx);
189     CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
190   }
191   stat = CpdDebugGetMemStat();
192   if (forPE == CmiMyPe()) CpdDebugReturnMemStat(stat);
193   else if (forPE == -1) CmiReduceStruct(stat, CpdDebug_pupMemStat, CpdDebug_mergeMemStat,
194                                 CpdDebugReturnMemStat, CpdDebug_deleteMemStat);
195   else CmiAbort("Received allocationTree request for another PE!");
196   CmiFree(msg);
197 }
198
199 static void CpdDebugHandler(char *msg)
200 {
201     char name[128];
202     sscanf(msg+CmiReservedHeaderSize, "%s", name);
203
204     if (strcmp(name, "freeze") == 0) {
205       CpdFreeze();
206     }
207     else if (strcmp(name, "unfreeze") == 0) {
208       CpdUnFreeze();
209     }
210     else if (strncmp(name, "step", strlen("step")) == 0){
211       /*CmiPrintf("step received\n");*/
212       CpvAccess(stepFlag) = 1;
213       CpdUnFreeze();
214     }
215     else if (strncmp(name, "continue", strlen("continue")) == 0){
216       /*CmiPrintf("continue received\n");*/
217       CpvAccess(continueFlag) = 1;
218       CpdUnFreeze();
219     }
220 #if ! CMK_NO_SOCKETS
221     else if (strncmp(name, "status", strlen("status")) == 0) {
222       ChMessageInt_t reply[2];
223       reply[0] = ChMessageInt_new(CmiMyPe());
224       reply[1] = ChMessageInt_new(CpdIsFrozen() ? 0 : 1);
225       CcsSendReply(2*sizeof(ChMessageInt_t), reply);
226     }
227 #endif
228     else{
229       CmiPrintf("bad debugger command:%s received,len=%ld\n",name,strlen(name));
230     }
231     CmiFree(msg);
232 }
233
234
235 /* Deliver a single message in the queue while not unfreezing the program */
236 void CpdNext(void) {
237
238 }
239
240 /* This converse handler is used by the debugger itself, to send messages
241  * even when the scheduler is in freeze mode.
242  */
243 void handleDebugMessage(void *msg) {
244   CmiSetHandler(msg, CmiGetXHandler(msg));
245   CmiHandleMessage(msg);
246 }
247
248 /* Special scheduler-type loop only executed while in
249 freeze mode-- only executes CCS requests.
250 */
251 void CcsServerCheck(void);
252 extern int _isCcsHandlerIdx(int idx);
253 int (*CpdIsDebugMessage)(void *);
254
255 void CpdFreezeModeScheduler(void)
256 {
257 #if CMK_BLUEGENE_CHARM
258     CmiAbort("Cannot run CpdFreezeModeScheduler inside BigSim emulated environment");
259 #else
260 #if CMK_CCS_AVAILABLE
261     void *msg;
262     void *debugQ=CpvAccess(debugQueue);
263     CsdSchedulerState_t state;
264     CsdSchedulerState_new(&state);
265
266     /* While frozen, queue up messages */
267     while (CpvAccess(freezeModeFlag)) {
268 #if NODE_0_IS_CONVHOST
269       if (CmiMyPe()==0) CcsServerCheck(); /*Make sure we can get CCS messages*/
270 #endif
271       msg = CsdNextMessage(&state);
272
273       if (msg!=NULL) {
274         /*int hIdx=CmiGetHandler(msg);*/
275           /*
276           if(_isCcsHandlerIdx(hIdx))
277           / *A CCS request-- handle it immediately* /
278           {
279             CmiHandleMessage(msg);
280           }
281           else if (hIdx == _debugHandlerIdx ||
282                   (hIdx == CmiGetReductionHandler() && CmiGetReductionDestination() == CpdDebugReturnAllocationTree)) {
283             / * Debug messages should be handled immediately * /
284             CmiHandleMessage(msg);
285           } else */
286           if (CpdIsDebugMessage(msg)) {
287             CmiHandleMessage(msg);
288           }
289           else
290           /*An ordinary charm++ message-- queue it up*/
291             CdsFifo_Enqueue(debugQ, msg);
292       } else CmiNotifyIdle();
293     }
294     /* Before leaving freeze mode, execute the messages
295        in the order they would have executed before.*/
296     while (!CdsFifo_Empty(debugQ))
297     {
298         char *queuedMsg = (char *)CdsFifo_Dequeue(debugQ);
299         CmiHandleMessage(queuedMsg);
300     }
301 #endif
302 #endif
303 }
304
305 void CpdMemoryMarkClean(char *msg);
306
307 void CpdInit(void)
308 {
309 #if ! CMK_BLUEGENE_CHARM
310   CpvInitialize(int, freezeModeFlag);
311   CpvAccess(freezeModeFlag) = 0;
312
313   CpvInitialize(void *, debugQueue);
314   CpvAccess(debugQueue) = CdsFifo_Create();
315 #endif
316   
317   CcsRegisterHandler("ccs_debug", (CmiHandler)CpdDebugHandler);
318   CcsSetMergeFn("ccs_debug", CcsMerge_concat);
319
320   CcsRegisterHandler("ccs_debug_allocationTree", (CmiHandler)CpdDebugCallAllocationTree);
321   CpvInitialize(int, CpdDebugCallAllocationTree_Index);
322   CpvAccess(CpdDebugCallAllocationTree_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallAllocationTree);
323   
324   CcsRegisterHandler("ccs_debug_memStat", (CmiHandler)CpdDebugCallMemStat);
325   CpvInitialize(int, CpdDebugCallMemStat_Index);
326   CpvAccess(CpdDebugCallMemStat_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallMemStat);
327
328   CcsRegisterHandler("converse_memory_leak",(CmiHandler)CpdSearchLeaks);
329   CpvInitialize(int, CpdSearchLeaks_Index);
330   CpvAccess(CpdSearchLeaks_Index) = CmiRegisterHandler((CmiHandler)CpdSearchLeaks);
331   CpvInitialize(int, CpdSearchLeaksDone_Index);
332   CpvAccess(CpdSearchLeaksDone_Index) = CmiRegisterHandler((CmiHandler)CpdSearchLeaksDone);
333   
334   CcsRegisterHandler("converse_memory_mark",(CmiHandler)CpdMemoryMarkClean);
335   CcsSetMergeFn("converse_memory_mark", CcsMerge_concat);
336
337   _debugHandlerIdx = CmiRegisterHandler((CmiHandler)handleDebugMessage);
338 #if 0
339   CpdInitializeObjectTable();
340   CpdInitializeHandlerArray();
341   CpdInitializeBreakPoints();
342
343   /* To allow start in freeze state: */
344   msgListCleanup();
345   msgListCache();
346 #endif
347
348 }
349