Added flag "-debug" to charmc for usage with charmdebug.
[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 CpvStaticDeclare(int, freezeModeFlag);
16 CpvStaticDeclare(int, continueFlag);
17 CpvStaticDeclare(int, stepFlag);
18 CpvDeclare(void *, debugQueue);
19 int _debugHandlerIdx;
20 CpvDeclare(int, skipBreakpoint); /* This is a counter of how many breakpoints we should skip */
21
22 /***************************************************
23   The CCS interface to the debugger
24 */
25
26 #include <string.h>
27
28 #include "pup_c.h"
29 void * (*CpdDebugGetAllocationTree)(int *);
30 void (*CpdDebug_pupAllocationPoint)(pup_er p, void *data);
31 void (*CpdDebug_deleteAllocationPoint)(void *ptr);
32 void * (*CpdDebug_MergeAllocationTree)(void *data, void **remoteData, int numRemote);
33 CpvDeclare(int, CpdDebugCallAllocationTree_Index);
34 CpvStaticDeclare(CcsDelayedReply, allocationTreeDelayedReply);
35
36 static void CpdDebugReturnAllocationTree(void *tree) {
37   pup_er sizer = pup_new_sizer();
38   char *buf;
39   pup_er packer;
40   int i;
41   CpdDebug_pupAllocationPoint(sizer, tree);
42   buf = (char *)malloc(pup_size(sizer));
43   packer = pup_new_toMem(buf);
44   CpdDebug_pupAllocationPoint(packer, tree);
45   /*CmiPrintf("size=%d tree:",pup_size(sizer));
46   for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
47   CmiPrintf("\n");*/
48   CcsSendDelayedReply(CpvAccess(allocationTreeDelayedReply), pup_size(sizer),buf);
49   pup_destroy(sizer);
50   pup_destroy(packer);
51   free(buf);
52 }
53
54 static void CpdDebugCallAllocationTree(char *msg)
55 {
56   int numNodes;
57   int forPE;
58   void *tree;
59   sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
60   if (CmiMyPe() == forPE) CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
61   if (forPE == -1 && CmiMyPe()==0) {
62     CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
63     CmiSetXHandler(msg, CpvAccess(CpdDebugCallAllocationTree_Index));
64     CmiSetHandler(msg, _debugHandlerIdx);
65     CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
66   }
67   tree = CpdDebugGetAllocationTree(&numNodes);
68   if (forPE == CmiMyPe()) CpdDebugReturnAllocationTree(tree);
69   else if (forPE == -1) CmiReduceStruct(tree, CpdDebug_pupAllocationPoint, CpdDebug_MergeAllocationTree,
70                                 CpdDebugReturnAllocationTree, CpdDebug_deleteAllocationPoint);
71   else CmiAbort("Received allocationTree request for another PE!");
72   CmiFree(msg);
73 }
74
75 static void CpdDebugHandler(char *msg)
76 {
77     char name[128];
78     sscanf(msg+CmiMsgHeaderSizeBytes, "%s", name);
79
80     if (strcmp(name, "freeze") == 0) {
81       CpdFreeze();
82     }
83     else if (strcmp(name, "unfreeze") == 0) {
84       CpdUnFreeze();
85     }
86     else if (strncmp(name, "step", strlen("step")) == 0){
87       CmiPrintf("step received\n");
88       CpvAccess(stepFlag) = 1;
89       CpdUnFreeze();
90     }
91     else if (strncmp(name, "continue", strlen("continue")) == 0){
92       CmiPrintf("continue received\n");
93       CpvAccess(continueFlag) = 1;
94       CpdUnFreeze();
95     }
96 #if 0
97     else if (strncmp(name, "setBreakPoint", strlen("setBreakPoint")) == 0){
98       CmiPrintf("setBreakPoint received\n");
99       temp = strstr(name, "#");
100       temp++;
101       setBreakPoints(temp);
102     }
103 #endif
104     else{
105       CmiPrintf("bad debugger command:%s received,len=%ld\n",name,strlen(name));
106     }
107 }
108
109
110 /*
111  Start the freeze-- call will not return until unfrozen
112  via a CCS request.
113  */
114 void CpdFreeze(void)
115 {
116   if (CpvAccess(freezeModeFlag)) return; /*Already frozen*/
117   CpvAccess(freezeModeFlag) = 1;
118   CpdFreezeModeScheduler();
119 }
120
121 void CpdUnFreeze(void)
122 {
123   CpvAccess(freezeModeFlag) = 0;
124 }
125
126 int CpdIsFrozen(void) {
127   return CpvAccess(freezeModeFlag);
128 }
129
130 /* Deliver a single message in the queue while not unfreezing the program */
131 void CpdNext(void) {
132   
133 }
134
135 /* This converse handler is used by the debugger itself, to send messages
136  * even when the scheduler is in freeze mode.
137  */
138 void handleDebugMessage(void *msg) {
139   CmiSetHandler(msg, CmiGetXHandler(msg));
140   CmiHandleMessage(msg);
141 }
142
143 /* Special scheduler-type loop only executed while in
144 freeze mode-- only executes CCS requests.
145 */
146 void CcsServerCheck(void);
147 extern int _isCcsHandlerIdx(int idx);
148 extern int _charmHandlerIdx;
149
150 void CpdFreezeModeScheduler(void)
151 {
152 #if CMK_CCS_AVAILABLE
153     void *msg;
154     void *debugQ=CpvAccess(debugQueue);
155     CsdSchedulerState_t state;
156     CsdSchedulerState_new(&state);
157
158     /* While frozen, queue up messages */
159     while (CpvAccess(freezeModeFlag)) {
160 #if NODE_0_IS_CONVHOST
161       CcsServerCheck(); /*Make sure we can get CCS messages*/
162 #endif
163       msg = CsdNextMessage(&state);
164
165       if (msg!=NULL) {
166           int hIdx=CmiGetHandler(msg);
167           /*
168           if(_isCcsHandlerIdx(hIdx))
169           / *A CCS request-- handle it immediately* /
170           {
171             CmiHandleMessage(msg);
172           }
173           else if (hIdx == _debugHandlerIdx ||
174                   (hIdx == CmiGetReductionHandler() && CmiGetReductionDestination() == CpdDebugReturnAllocationTree)) {
175             / * Debug messages should be handled immediately * /
176             CmiHandleMessage(msg);
177           } else */
178           if (hIdx != _charmHandlerIdx || isDebugMessage(msg)) {
179             CmiHandleMessage(msg);
180           }
181           else
182           /*An ordinary charm++ message-- queue it up*/
183             CdsFifo_Enqueue(debugQ, msg);
184       } else CmiNotifyIdle();
185     }
186     /* Before leaving freeze mode, execute the messages 
187        in the order they would have executed before.*/
188     while (!CdsFifo_Empty(debugQ))
189     {
190         char *queuedMsg = (char *)CdsFifo_Dequeue(debugQ);
191         CmiHandleMessage(queuedMsg);
192     }
193 #endif
194 }
195
196
197 void CpdInit(void)
198 {
199   CpvInitialize(int, freezeModeFlag);
200   CpvAccess(freezeModeFlag) = 0;
201
202   CpvInitialize(void *, debugQueue);
203   CpvAccess(debugQueue) = CdsFifo_Create();
204
205   CcsRegisterHandler("ccs_debug", (CmiHandler)CpdDebugHandler);
206   CcsRegisterHandler("ccs_debug_allocationTree", (CmiHandler)CpdDebugCallAllocationTree);
207   CpvInitialize(int, CpdDebugCallAllocationTree_Index);
208   CpvAccess(CpdDebugCallAllocationTree_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallAllocationTree);
209   
210   _debugHandlerIdx = CmiRegisterHandler((CmiHandler)handleDebugMessage);
211 #if 0
212   CpdInitializeObjectTable();
213   CpdInitializeHandlerArray();
214   CpdInitializeBreakPoints();
215
216   /* To allow start in freeze state: */
217   msgListCleanup();
218   msgListCache();
219 #endif
220   
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238