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