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