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