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