Added ability to start remote paradynd's
[dyninst.git] / paradynd / src / main.C
1 /*
2  * Main loop for the default paradynd.
3  *
4  * $Log: main.C,v $
5  * Revision 1.8  1994/04/01 20:06:41  hollings
6  * Added ability to start remote paradynd's
7  *
8  * Revision 1.7  1994/03/31  01:57:27  markc
9  * Added support for pauseProcess, continueProcess.  Added pvm interface code.
10  *
11  * Revision 1.6  1994/03/20  01:53:09  markc
12  * Added a buffer to each process structure to allow for multiple writers on the
13  * traceStream.  Replaced old inst-pvm.C.  Changed addProcess to return type
14  * int.
15  *
16  * Revision 1.5  1994/02/28  05:09:42  markc
17  * Added pvm hooks and ifdefs.
18  *
19  * Revision 1.4  1994/02/25  13:40:55  markc
20  * Added hooks for pvm support.
21  *
22  * Revision 1.3  1994/02/24  04:32:33  markc
23  * Changed header files to reflect igen changes.  main.C does not look at the number of command line arguments now.
24  *
25  * Revision 1.2  1994/02/01  18:46:52  hollings
26  * Changes for adding perfConsult thread.
27  *
28  * Revision 1.1  1994/01/27  20:31:27  hollings
29  * Iinital version of paradynd speaking dynRPC igend protocol.
30  *
31  *
32  */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/time.h>
37 #include <assert.h>
38
39 #include "util/h/list.h"
40 #include "rtinst/h/rtinst.h"
41
42 #include "symtab.h"
43 #include "process.h"
44 #include "inst.h"
45 #include "instP.h"
46 #include "ast.h"
47 #include "util.h"
48 #include "dyninstP.h"
49 #include "metric.h"
50 #include "dyninstRPC.SRVR.h"
51
52 dynRPC *tp;
53 extern void controllerMainLoop();
54 extern void initLibraryFunctions();
55
56 #ifdef PARADYND_PVM
57 static dynRPC *init_pvm_code(char *argv[], char *machine, int family,
58                              int type, int well_known_socket, int flag);
59 static char machine_name[80];
60 #endif     
61
62 int ready;
63
64 main(int argc, char *argv[])
65 {
66     int i, family, type, well_known_socket, flag;
67     char *machine;
68     metricList stuff;
69
70     initLibraryFunctions();
71
72     // process command line args passed in
73     // flag == 1 --> started by paradyn
74     assert (RPC_undo_arg_list (argc, argv, &machine, family, type,
75                        well_known_socket, flag) == 0);
76
77 #ifdef PARADYND_PVM
78     tp = init_pvm_code(argv, machine, family, type, well_known_socket, flag);
79 #else
80     if (!flag) {
81         int pid;
82
83
84         pid = fork();
85         if (pid == 0) {
86             close(0);
87             close(1);
88             close(2);
89
90             // setup socket
91             tp = new dynRPC(family, well_known_socket, type, machine, 
92                             NULL, NULL, 0);
93         } else if (pid > 0) {
94             printf("PARADYND %d\n", pid);
95             fflush(stdout);
96             _exit(-1);
97         } else {
98             fflush(stdout);
99             exit(-1);
100         }
101     } else {
102         // already setup on this FD.
103         tp = new dynRPC(0, NULL, NULL);
104     }
105 #endif
106
107     //
108     // tell client about our metrics.
109     //
110     stuff = getMetricList();
111     for (i=0; i < stuff->count; i++) {
112         tp->newMetricCallback(stuff->elements[i].info);
113         if (tp->callErr < 0) {
114             printf("RPC error\n");
115             exit(-1);
116         }
117     }
118
119     controllerMainLoop();
120 }
121
122 void dynRPC::addResource(String parent, String name)
123 {
124     resource pr;
125     extern resource findResource(char*);
126
127     pr = findResource(parent);
128     if (pr) (void) newResource(pr, NULL, name, 0.0);
129 }
130
131 void dynRPC::coreProcess(int pid)
132 {
133     process *proc;
134
135     proc = processList.find((void *) pid);
136     dumpCore(proc);
137 }
138
139 String dynRPC::getStatus(int pid)
140 {
141     process *proc;
142     extern char *getProcessStatus(process *proc);
143     char ret[50];
144
145     proc = processList.find((void *) pid);
146
147     if (!proc) {
148         sprintf (ret, "PID:%d not found for getStatus\n", pid);
149         return (ret);
150     }
151     else
152         return(getProcessStatus(proc));
153 }
154
155 //
156 // NOTE: This version of getAvailableMetrics assumes that new metrics are
157 //   NOT added during execution.
158 //
159 metricInfo_Array dynRPC::getAvailableMetrics(void)
160 {
161     int i;
162     static int inited;
163     static metricInfo_Array metInfo;
164
165     if (!inited) {
166         metricList stuff;
167
168         stuff = getMetricList();
169         metInfo.count = stuff->count;
170         metInfo.data = (metricInfo*) calloc(sizeof(metricInfo), metInfo.count);
171         for (i=0; i < metInfo.count; i++) {
172             metInfo.data[i] = stuff->elements[i].info;
173         }
174         inited = 1;
175     }
176     return(metInfo);
177 }
178
179 double dynRPC::getPredictedDataCost(String_Array focusString, String metric)
180 {
181     metric m;
182     double val;
183     resourceList l;
184
185     m = findMetric(metric);
186     l = findFocus(focusString.count, focusString.data);
187     if (!l) return(0.0);
188     val = guessCost(l, m);
189
190     return(val);
191 }
192
193 void dynRPC::disableDataCollection(int mid)
194 {
195     metricInstance mi;
196     extern void printResourceList(resourceList);
197
198     printf("disable of %s for RL =", getMetricName(mi->met));
199     printResourceList(mi->resList);
200     printf("\n");
201
202     mi = allMIs.find((void *) mid);
203     mi->disable();
204     allMIs.remove(mi);
205     delete(mi);
206 }
207
208 int dynRPC::enableDataCollection(String_Array foucsString,String metric)
209 {
210     int id;
211     metric m;
212     resourceList l;
213
214     m = findMetric(metric);
215     l = findFocus(foucsString.count, foucsString.data);
216     if (!l) return(-1);
217     id = startCollecting(l, m);
218     return(id);
219 }
220
221 //
222 // not implemented yet.
223 //
224 void dynRPC::setSampleRate(double sampleInterval)
225 {
226     return;
227 }
228
229 Boolean dynRPC::detachProgram(int program,Boolean pause)
230 {
231     return(detachProcess(program, pause));
232 }
233
234 //
235 // Continue all processes
236 //
237 void dynRPC::continueApplication()
238 {
239     struct List<process *> curr;
240
241     for (curr = processList; *curr; curr++) {
242         continueProcess(*curr);
243     }
244 }
245
246 //
247 // Continue a process
248 //
249 void dynRPC::continueProgram(int program)
250 {
251     struct List<process *> curr;
252
253     for (curr = processList; *curr; curr++) {
254         if ((*curr)->pid == pid) break;
255     }
256     if (*curr)
257         continueProcess(*curr);
258     else
259         printf("Can't continue PID %d\n", program);
260 }
261
262 //
263 //  Stop all processes 
264 //
265 Boolean dynRPC::pauseApplication()
266 {
267     struct List<process *> curr;
268
269     for (curr = processList; *curr; curr++) {
270         pauseProcess(*curr);
271     }
272     flushPtrace();
273     return TRUE;
274 }
275
276 //
277 //  Stop a single process
278 //
279 Boolean dynRPC::pauseProgram(int program)
280 {
281     struct List<process *> curr;
282
283     for (curr = processList; *curr; curr++) {
284         if ((*curr)->pid == program) break;
285     }
286     if (!(*curr)) {
287         printf("Can't pause PID %d\n", program);
288         return FALSE;
289     }
290     pauseProcess(*curr);
291     flushPtrace();
292     return TRUE;
293 }
294
295 Boolean dynRPC::startProgram(int program)
296 {
297     continueApplication();
298     return(False);
299 }
300
301 //
302 // This is not implemented yet.
303 //
304 Boolean dynRPC::attachProgram(int pid)
305 {
306     return(FALSE);
307 }
308
309 //
310 // start a new program for the tool.
311 //
312 int dynRPC::addExecutable(int argc,String_Array argv)
313 {
314     return(addProcess(argc, argv.data));
315 }
316
317 #ifdef PARADYND_PVM
318 dynRPC *
319 init_pvm_code(char *argv[], char *machine, int family,
320               int type, int well_known_socket, int flag)
321 {
322   dynRPC *temp;
323
324   extern int PDYN_initForPVM (char **, char *, int, int, int, int);
325
326   assert(PDYN_initForPVM (argv, machine, family, type, well_known_socket,
327                          flag) == 0);
328
329   // connect to paradyn
330   if (flag == 1)
331     temp = new dynRPC(0, NULL, NULL);
332   else
333     {
334       temp = new dynRPC(family, well_known_socket, type, machine, NULL, NULL);
335       temp->reportSelf (machine, argv[0], getpid());
336     }
337
338     return temp;
339 }
340
341 int
342 PDYND_report_to_paradyn (int pid, int argc, char **argv)
343 {
344     String_Array sa;
345
346     sa.count = argc;
347     sa.data = argv;
348     assert(!gethostname(machine_name, 99));
349
350     assert(tp);
351     tp->newProgramCallbackFunc(pid, argc, sa, machine_name);
352     return 0;
353 }
354 #endif