changes to support changing the sampling rate: dynRPC::setSampleRate changes
[dyninst.git] / paradynd / src / dynrpc.C
1 /*
2  * Copyright (c) 1993, 1994 Barton P. Miller, Jeff Hollingsworth,
3  *     Bruce Irvin, Jon Cargille, Krishna Kunchithapadam, Karen
4  *     Karavanic, Tia Newhall, Mark Callaghan.  All rights reserved.
5  * 
6  * This software is furnished under the condition that it may not be
7  * provided or otherwise made available to, or used by, any other
8  * person, except as provided for by the terms of applicable license
9  * agreements.  No title to or ownership of the software is hereby
10  * transferred.  The name of the principals may not be used in any
11  * advertising or publicity related to this software without specific,
12  * written prior authorization.  Any use of this software must include
13  * the above copyright notice.
14  *
15  */
16
17 #ifndef lint
18 static char Copyright[] = "@(#) Copyright (c) 1993, 1994 Barton P. Miller, \
19   Jeff Hollingsworth, Bruce Irvin, Jon Cargille, Krishna Kunchithapadam, \
20   Karen Karavanic, Tia Newhall, Mark Callaghan.  All rights reserved.";
21
22 static char rcsid[] = "@(#) /p/paradyn/CVSROOT/core/paradynd/src/dynrpc.C,v 1.18 1995/05/18 10:32:35 markc Exp";
23 #endif
24
25
26 /*
27  * File containing lots of dynRPC function definitions for the paradynd..
28  *
29  * $Log: dynrpc.C,v $
30  * Revision 1.23  1995/11/03 00:06:05  newhall
31  * changes to support changing the sampling rate: dynRPC::setSampleRate changes
32  *     the value of DYNINSTsampleMultiple, implemented image::findInternalSymbol
33  * fix so that SIGKILL is not being forwarded to CM5 applications.
34  *
35  * Revision 1.22  1995/10/19  22:36:39  mjrg
36  * Added callback function for paradynd's to report change in status of application.
37  * Added Exited status for applications.
38  * Removed breakpoints from CM5 applications.
39  * Added search for executables in a given directory.
40  *
41  * Revision 1.21  1995/09/26  20:17:44  naim
42  * Adding error messages using showErrorCallback function for paradynd
43  *
44  * Revision 1.20  1995/09/18  22:41:33  mjrg
45  * added directory command.
46  *
47  * Revision 1.19  1995/08/24  15:03:48  hollings
48  * AIX/SP-2 port (including option for split instruction/data heaps)
49  * Tracing of rexec (correctly spawns a paradynd if needed)
50  * Added rtinst function to read getrusage stats (can now be used in metrics)
51  * Critical Path
52  * Improved Error reporting in MDL sematic checks
53  * Fixed MDL Function call statement
54  * Fixed bugs in TK usage (strings passed where UID expected)
55  *
56  * Revision 1.18  1995/05/18  10:32:35  markc
57  * Replaced process dict with process map
58  * Get metric definitions from two locations (internal, and mdl)
59  *
60  * Revision 1.17  1995/02/16  08:53:08  markc
61  * Corrected error in comments -- I put a "star slash" in the comment.
62  *
63  * Revision 1.16  1995/02/16  08:33:12  markc
64  * Changed igen interfaces to use strings/vectors rather than char igen-arrays
65  * Changed igen interfaces to use bool, not Boolean.
66  * Cleaned up symbol table parsing - favor properly labeled symbol table objects
67  * Updated binary search for modules
68  * Moved machine dependnent ptrace code to architecture specific files.
69  * Moved machine dependent code out of class process.
70  * Removed almost all compiler warnings.
71  * Use "posix" like library to remove compiler warnings
72  *
73  * Revision 1.15  1995/01/26  18:11:54  jcargill
74  * Updated igen-generated includes to new naming convention
75  *
76  * Revision 1.14  1994/11/12  17:28:46  rbi
77  * improved status reporting for applications pauses
78  *
79  * Revision 1.13  1994/11/09  18:39:58  rbi
80  * the "Don't Blame Me" commit
81  *
82  * Revision 1.12  1994/11/06  09:53:08  jcargill
83  * Fixed early paradynd startup problem; resources sent by paradyn were
84  * being added incorrectly at the root level.
85  *
86  * Revision 1.11  1994/11/03  16:12:19  rbi
87  * Eliminated argc from addExecutable interface.
88  *
89  * Revision 1.10  1994/11/02  11:04:44  markc
90  * Replaced iterators.
91  *
92  * Revision 1.9  1994/10/13  07:24:38  krisna
93  * solaris porting and updates
94  *
95  * Revision 1.8  1994/09/22  16:02:25  markc
96  * Removed #include "resource.h"
97  *
98  * Revision 1.7  1994/09/22  01:53:48  markc
99  * Made system includes extern "C"
100  * added const to char* args to stop compiler warnings
101  * changed string to char*
102  * declare classes as classes, not structs
103  * use igen methods to access igen member vars
104  *
105  * Revision 1.6  1994/08/08  20:13:36  hollings
106  * Added suppress instrumentation command.
107  *
108  * Revision 1.5  1994/07/28  22:40:36  krisna
109  * changed definitions/declarations of xalloc functions to conform to alloc.
110  *
111  * Revision 1.4  1994/07/26  19:56:42  hollings
112  * commented out print statements.
113  *
114  * Revision 1.3  1994/07/20  23:22:48  hollings
115  * added code to record time spend generating instrumentation.
116  *
117  * Revision 1.2  1994/07/14  23:30:22  hollings
118  * Hybrid cost model added.
119  *
120  * Revision 1.1  1994/07/14  14:45:48  jcargill
121  * Added new file for dynRPC functions, and a default (null) function for
122  * processArchDependentTraceStream, and the cm5 version.
123  *
124  */
125
126 #include "symtab.h"
127 #include "process.h"
128 #include "inst.h"
129 #include "instP.h"
130 #include "ast.h"
131 #include "util.h"
132 #include "dyninstP.h"
133 #include "metric.h"
134 #include "internalMetrics.h"
135 #include "dyninstRPC.xdr.SRVR.h"
136 #include "dyninst.h"
137 #include "stats.h"
138 #include "resource.h"
139 #include "paradynd/src/mdld.h"
140 #include "paradynd/src/init.h"
141 #include "showerror.h"
142 #include "util/h/sys.h" 
143
144 #define ONEMILLION 1000000
145 // default to once a second.
146 float samplingRate = 1.0;
147 float currSamplingRate = BASEBUCKETWIDTH;
148
149 void dynRPC::printStats(void)
150 {
151   printDyninstStats();
152 }
153
154 // TODO -- use a different creation time
155 void dynRPC::addResource(u_int parent_id, u_int id, string name)
156 {
157   resource *parent = resource::findResource(parent_id);
158   if (!parent) return;
159   resource::newResource(parent, name, id);
160 }
161
162 void dynRPC::coreProcess(int id)
163 {
164   process *proc = findProcess(id);
165   if (proc)
166     proc->dumpCore("core.out");
167 }
168
169 string dynRPC::getStatus(int id)
170 {
171   char ret[50];
172   process *proc = findProcess(id);
173   if (!proc) {
174     sprintf (ret, "PID:%d not found for getStatus\n", id);
175     return (ret);
176   } else 
177     return (proc->getProcessStatus());
178 }
179
180 vector<T_dyninstRPC::metricInfo> dynRPC::getAvailableMetrics(void) {
181   vector<T_dyninstRPC::metricInfo> metInfo;
182   unsigned size = internalMetric::allInternalMetrics.size();
183   for (unsigned u=0; u<size; u++)
184     metInfo += internalMetric::allInternalMetrics[u]->getInfo();
185
186   mdl_get_info(metInfo);
187   return(metInfo);
188 }
189
190 double dynRPC::getPredictedDataCost(vector<u_int> focus, string metName)
191 {
192     if (!metName.length()) return(0.0);
193     return (guessCost(metName, focus));
194 }
195
196 double dynRPC::getCurrentHybridCost(void)
197 {
198     statusLine("returning cost measurements");
199     return(currentHybridValue);
200 }
201
202 void dynRPC::disableDataCollection(int mid)
203 {
204     float cost;
205     metricDefinitionNode *mi;
206
207     if (!allMIs.defines(mid)) {
208       sprintf(errorLine, "Internal error: disableDataCollection mid %d not found\n", mid);
209       logLine(errorLine);
210       showErrorCallback(61,(const char *) errorLine);
211       return;
212     }
213
214     mi = allMIs[mid];
215     // cout << "disable of " << mi->getFullName() << endl; 
216
217     cost = mi->originalCost();
218
219     currentPredictedCost -= cost;
220
221     mi->disable();
222     allMIs.undef(mid);
223     delete(mi);
224 }
225
226 bool dynRPC::setTracking(unsigned target, bool mode)
227 {
228     resource *res = resource::findResource(target);
229     if (res) {
230         if (res->isResourceDescendent(moduleRoot)) {
231             image::changeLibFlag(res, (bool) mode);
232             res->suppress(true);
233             return(true);
234         } else {
235             // un-supported resource hierarchy.
236             return(false);
237         }
238     } else {
239       // cout << "Set tracking target " << target << " not found\n";
240       return(false);
241     }
242 }
243
244 void dynRPC::resourceInfoResponse(vector<string> resource_name, u_int resource_id) {
245   resource *res = resource::findResource(resource_name);
246   if (res)
247     res->set_id(resource_id);
248 }
249
250 // TODO -- startCollecting  Returns -1 on failure ?
251 int dynRPC::enableDataCollection(vector<u_int> focus, string met, int gid)
252 {
253     int id;
254     totalInstTime.start();
255     id = startCollecting(met, focus, gid);
256     totalInstTime.stop();
257     // cout << "Enabled " << met << " = " << id << endl;
258     return(id);
259 }
260
261
262 //
263 // computes new sample multiple value, and modifies the value of the
264 // symbol _DYNINSTsampleMultiple which will affect the frequency with
265 // which performance data is sent to the paradyn process 
266 //
267 void dynRPC::setSampleRate(double sampleInterval)
268 {
269     // TODO: implement this:
270     // want to change value of DYNINSTsampleMultiple to corr. to new
271     // sampleInterval (sampleInterval % baseSampleInterval) 
272     // if the sampleInterval is less than the BASESAMPLEINTERVAL ignore
273     // use currSamplingRate to determine if the change to DYNINSTsampleMultiple
274     // needs to be made
275
276     if(sampleInterval != currSamplingRate){
277         int *sample_multiple = new int; 
278         *sample_multiple = 
279             (int)(((sampleInterval)*ONEMILLION)/BASESAMPLEINTERVAL);
280           
281         // setSampleMultiple(sample_multiple);
282         // set the sample multiple in all processes
283         unsigned p_size = processVec.size();
284         for (unsigned u=0; u<p_size; u++){
285             internalSym *ret_sym = 0; 
286             if(!(ret_sym = processVec[u]->symbols->findInternalSymbol(
287                                 "DYNINSTsampleMultiple",true))){
288                 sprintf(errorLine, "error2 in dynRPC::setSampleRate\n");
289                 logLine(errorLine);
290                 P_abort();
291             }
292             Address addr = ret_sym->getAddr();
293             processVec[u]->writeDataSpace((caddr_t)addr,sizeof(int),
294                                           (caddr_t)sample_multiple);
295         }
296         currSamplingRate = sampleInterval;
297     }
298     return;
299 }
300
301 bool dynRPC::detachProgram(int program, bool pause)
302 {
303   process *proc = findProcess(program);
304   if (proc)
305     return(proc->detach(pause));
306   else
307     return false;
308 }
309
310 //
311 // Continue all processes
312 //
313 void dynRPC::continueApplication(void)
314 {
315     continueAllProcesses();
316     statusLine("application running");
317 }
318
319 //
320 // Continue a process
321 //
322 void dynRPC::continueProgram(int program)
323 {
324     process *proc = findProcess(program);
325     if (!proc) {
326       sprintf(errorLine, "Internal error: cannot continue PID %d\n", program);
327       logLine(errorLine);
328       showErrorCallback(62,(const char *) errorLine);
329     }
330     proc->continueProc();
331 }
332
333 //
334 //  Stop all processes 
335 //
336 bool dynRPC::pauseApplication(void)
337 {
338     pauseAllProcesses();
339     return true;
340 }
341
342 //
343 //  Stop a single process
344 //
345 bool dynRPC::pauseProgram(int program)
346 {
347     process *proc = findProcess(program);
348     if (!proc) {
349       sprintf(errorLine, "Internal error: cannot pause PID %d\n", program);
350       logLine(errorLine);
351       showErrorCallback(63,(const char *) errorLine);
352       return false;
353     }
354     return (proc->pause());
355 }
356
357 bool dynRPC::startProgram(int program)
358 {
359     statusLine("starting application");
360     continueAllProcesses();
361     return(false);
362 }
363
364 //
365 // This is not implemented yet.
366 //
367 bool dynRPC::attachProgram(int id)
368 {
369     return(false);
370 }
371
372 //
373 // start a new program for the tool.
374 //
375 int dynRPC::addExecutable(vector<string> argv, string dir, bool stopAtFirstBreak)
376 {
377   vector<string> envp;
378   return(addProcess(argv, envp, dir, stopAtFirstBreak));
379 }
380
381 //
382 // CM5 processes only: continue the process that is stopped waiting for the CM5 node
383 // daemon to start.
384 //
385 void dynRPC::nodeDaemonReady() {
386   continueProcWaitingForDaemon();
387 }