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