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