Added callback function for paradynd's to report change in status of application.
[dyninst.git] / paradynd / src / inst-sunos.C
1
2 /*
3  * inst-sunos.C - sunos specifc code for paradynd.
4  *
5  * $Log: inst-sunos.C,v $
6  * Revision 1.31  1995/10/19 22:36:41  mjrg
7  * Added callback function for paradynd's to report change in status of application.
8  * Added Exited status for applications.
9  * Removed breakpoints from CM5 applications.
10  * Added search for executables in a given directory.
11  *
12  * Revision 1.30  1995/09/26  20:17:46  naim
13  * Adding error messages using showErrorCallback function for paradynd
14  *
15  * Revision 1.29  1995/08/24  15:04:03  hollings
16  * AIX/SP-2 port (including option for split instruction/data heaps)
17  * Tracing of rexec (correctly spawns a paradynd if needed)
18  * Added rtinst function to read getrusage stats (can now be used in metrics)
19  * Critical Path
20  * Improved Error reporting in MDL sematic checks
21  * Fixed MDL Function call statement
22  * Fixed bugs in TK usage (strings passed where UID expected)
23  *
24  * Revision 1.28  1995/05/30  05:04:58  krisna
25  * upgrade from solaris-2.3 to solaris-2.4.
26  * architecture-os based include protection of header files.
27  * removed architecture-os dependencies in generic sources.
28  * changed ST_* symbol names to PDST_* (to avoid conflict on HPUX)
29  *
30  * Revision 1.27  1995/05/18  10:35:25  markc
31  * Removed tag dictionary
32  *
33  * Revision 1.26  1995/03/10  19:33:49  hollings
34  * Fixed several aspects realted to the cost model:
35  *     track the cost of the base tramp not just mini-tramps
36  *     correctly handle inst cost greater than an imm format on sparc
37  *     print starts at end of pvm apps.
38  *     added option to read a file with more accurate data for predicted cost.
39  *
40  * Revision 1.25  1995/02/16  08:53:29  markc
41  * Corrected error in comments -- I put a "star slash" in the comment.
42  *
43  * Revision 1.24  1995/02/16  08:33:28  markc
44  * Changed igen interfaces to use strings/vectors rather than char igen-arrays
45  * Changed igen interfaces to use bool, not Boolean.
46  * Cleaned up symbol table parsing - favor properly labeled symbol table objects
47  * Updated binary search for modules
48  * Moved machine dependnent ptrace code to architecture specific files.
49  * Moved machine dependent code out of class process.
50  * Removed almost all compiler warnings.
51  * Use "posix" like library to remove compiler warnings
52  *
53  * Revision 1.23  1995/01/26  18:12:00  jcargill
54  * Updated igen-generated includes to new naming convention
55  *
56  * Revision 1.22  1994/11/11  10:44:03  markc
57  * Remove non-emergency prints
58  * Changed others to use statusLine
59  *
60  * Revision 1.21  1994/11/11  10:11:40  markc
61  * Used correct arg order for RPC_make_arg_list
62  *
63  * Revision 1.20  1994/11/11  07:04:55  markc
64  * Added code to bundle extra command line argument.
65  *
66  * Revision 1.19  1994/11/10  18:58:02  jcargill
67  * The "Don't Blame Me Either" commit
68  *
69  * Revision 1.18  1994/11/09  18:40:10  rbi
70  * the "Don't Blame Me" commit
71  *
72  * Revision 1.17  1994/11/02  11:06:19  markc
73  * Removed redundant code into inst.C
74  * Provide "tag" dictionary for known functions.
75  *
76  * Revision 1.16  1994/10/13  07:24:45  krisna
77  * solaris porting and updates
78  *
79  * Revision 1.15  1994/09/30  19:47:05  rbi
80  * Basic instrumentation for CMFortran
81  *
82  * Revision 1.14  1994/09/22  01:58:53  markc
83  * Enter handles for primitiveCosts into stringPool
84  * changed libraryList to List<libraryFunc*>
85  *
86  * Revision 1.13  1994/09/20  18:18:25  hollings
87  * added code to use actual clock speed for cost model numbers.
88  *
89  * Revision 1.12  1994/08/17  18:11:59  markc
90  * Changed the execv to execvp.
91  * Changed arglist in forkProcess.
92  *
93  * Revision 1.11  1994/07/22  19:16:36  hollings
94  * moved computePauseTimeMetric here, and added lib func calls for cmmd routines.
95  *
96  * Revision 1.10  1994/07/15  20:22:03  hollings
97  * fixed 64 bit record to be 32 bits.
98  *
99  * Revision 1.9  1994/07/14  23:30:26  hollings
100  * Hybrid cost model added.
101  *
102  * Revision 1.8  1994/07/12  19:46:57  jcargill
103  * Removed old code, added ability for fork paradyndCM5 when nodes start.
104  *
105  * Revision 1.7  1994/07/05  03:26:04  hollings
106  * observed cost model
107  *
108  * Revision 1.6  1994/06/29  02:52:29  hollings
109  * Added metricDefs-common.{C,h}
110  * Added module level performance data
111  * cleanedup types of inferrior addresses instrumentation defintions
112  * added firewalls for large branch displacements due to text+data over 2meg.
113  * assorted bug fixes.
114  *
115  * Revision 1.5  1994/06/27  18:56:49  hollings
116  * removed printfs.  Now use logLine so it works in the remote case.
117  * added internalMetric class.
118  * added extra paramter to metric info for aggregation.
119  *
120  * Revision 1.4  1994/03/26  20:50:47  jcargill
121  * Changed the pause/continue code.  Now it really stops, instead of
122  * spin looping.
123  *
124  * Revision 1.3  1994/03/22  21:03:14  hollings
125  * Made it possible to add new processes (& paradynd's) via addExecutable.
126  *
127  * Revision 1.2  1994/03/20  01:53:07  markc
128  * Added a buffer to each process structure to allow for multiple writers on the
129  * traceStream.  Replaced old inst-pvm.C.  Changed addProcess to return type
130  * int.
131  *
132  * Revision 1.1  1994/02/07  17:38:48  hollings
133  * Added inst-sunos to split cm-5 code from standard sunos code.
134  *
135  *
136  *
137  */
138 char inst_sunos_ident[] = "@(#) /p/paradyn/CVSROOT/core/paradynd/src/inst-sunos.C,v 1.28 1995/05/30 05:04:58 krisna Exp";
139
140 #include "os.h"
141 #include "metric.h"
142 #include "dyninst.h"
143 #include "rtinst/h/trace.h"
144 #include "symtab.h"
145 #include "process.h"
146 #include "inst.h"
147 #include "instP.h"
148 #include "ast.h"
149 #include "ptrace_emul.h"
150 #include "dyninstRPC.xdr.SRVR.h"
151 #include "util.h"
152 #include "stats.h"
153 #include "main.h"
154 #include "perfStream.h"
155 #include "context.h"
156 #include "showerror.h"
157
158 string process::getProcessStatus() const {
159    char ret[80];
160
161    switch (status()) {
162         case running:
163             sprintf(ret, "%d running", pid);
164             break;
165         case neonatal:
166             sprintf(ret, "%d neonatal", pid);
167             break;
168         case stopped:
169             sprintf(ret, "%d stopped", pid);
170             break;
171         case exited:
172             sprintf(ret, "%d exited", pid);
173             break;
174         default:
175             sprintf(ret, "%d UNKNOWN State", pid);
176             break;
177     }
178     return(ret);
179 }
180
181 //
182 // All costs are based on Measurements on a SPARC station 10/40.
183 //
184 void initPrimitiveCost()
185 {
186     /* Need to add code here to collect values for other machines */
187
188     // these happen async of the rest of the system.
189     primitiveCosts["DYNINSTalarmExpire"] = 1;
190     primitiveCosts["DYNINSTsampleValues"] = 1;
191     primitiveCosts["DYNINSTreportTimer"] = 1;
192     primitiveCosts["DYNINSTreportCounter"] = 1;
193     primitiveCosts["DYNINSTreportCost"] = 1;
194     primitiveCosts["DYNINSTreportNewTags"] = 1;
195     primitiveCosts["DYNINSTprintCost"] = 1;
196
197     // this doesn't really take any time
198     primitiveCosts["DYNINSTbreakPoint"] = 1;
199
200     // this happens before we start keeping time.
201     primitiveCosts["DYNINSTinit"] = 1;
202
203     // isthmus acutal numbers from 7/3/94 -- jkh
204     // 240 ns
205     primitiveCosts["DYNINSTincrementCounter"] = 16;
206     // 240 ns
207     primitiveCosts["DYNINSTdecrementCounter"] = 16;
208 #ifdef sparc_sun_solaris2_4
209     // Solaris measured 
210     // clock == 39.173MHz
211     // cost per call DYNINSTstartWallTimer 11.700000 usec 
212     // cost per call DYNINSTstopWallTimer 22.550000 usec 
213     // cost per call DYNINSTstartProcessTimer 14.650000 usec 
214     // cost per call DYNINSTstopProcessTimer 24.550000 usec 
215     logLine("Solaris dyninst costs being used");
216
217     primitiveCosts["DYNINSTstartWallTimer"] = 468;
218     primitiveCosts["DYNINSTstopWallTimer"] = 900;
219     primitiveCosts["DYNINSTstartProcessTimer"] = 574;
220     primitiveCosts["DYNINSTstopProcessTimer"] = 961;
221 #else
222     // 23.39 usec * 85 mhz (SS-5)
223     primitiveCosts["DYNINSTstartWallTimer"] = 1988;
224     // 48.05 usec * 85 mhz (SS-5)
225     primitiveCosts["DYNINSTstopWallTimer"] = 4084;
226     // 1.61 usec * 85 Mhz (measured on a SS-5)
227     // 25 cycles (read clock) +  26 (startProcessTimer)
228     primitiveCosts["DYNINSTstartProcessTimer"] = 51;
229      // 3.38 usec * 85 mhz (measured on a SS-5)
230     // 61 cycles + 2*25 cycles to read clock
231     primitiveCosts["DYNINSTstopProcessTimer"] = 111;
232 #endif
233 }
234
235 int flushPtrace()
236 {
237     return(0);
238 }
239
240 void forkNodeProcesses(process *curr, traceHeader *hr, traceFork *fr)
241 {
242     int childPid;
243     char command[256];
244     char application[256];
245     char app_pid[20];
246     char num_nodes[20]; 
247  
248     process *parent = findProcess(fr->ppid);
249     if (!parent) {
250       sprintf(errorLine, "In forkNodeProcesses, parent id %d unknown", fr->ppid);
251       statusLine(errorLine);
252       showErrorCallback(51, (const char *) errorLine);
253       return;
254     }
255
256     /* Build arglist */
257     sprintf (command, "%sCM5", process::programName.string_of());
258     sprintf (application, "%s", (curr->symbols->file()).string_of());
259     sprintf (app_pid, "%d", curr->pid);
260     sprintf (num_nodes, "%d", fr->npids);
261
262     /*
263      * It would be nice if this weren't sensitive to the size of
264      * arg_list.  For the moment, only arg_list[0] --> arg_list[6]
265      * are written by RPC_make_arg_list
266      * This is a small-time hack.
267      */
268
269     char *argv[20];
270     argv[0] = command;
271     argv[1] = application;
272     argv[2] = app_pid;
273     argv[3] = num_nodes;
274
275     // IF these are change, check out the delete below
276     argv[4] = P_strdup(process::arg_list[0].string_of());
277     argv[5] = P_strdup(process::arg_list[1].string_of());
278     argv[6] = P_strdup(process::arg_list[2].string_of());
279     argv[7] = P_strdup(process::arg_list[3].string_of());
280     argv[8] = P_strdup(process::arg_list[4].string_of());
281     argv[9] = P_strdup(process::arg_list[5].string_of());
282     argv[10] = P_strdup(process::arg_list[6].string_of());
283     argv[11] = NULL;
284
285     if ((childPid=fork()) == 0) {               /* child */
286       P_execvp (command, argv);
287       logLine("Exec failed in paradynd to start paradyndCM5\n");
288       showErrorCallback(56, "");
289       P_abort();
290     } else {                    /* parent */
291       sprintf (errorLine, "forked child process (pid=%d)", childPid);
292       statusLine(errorLine);
293     }
294
295     for (int di=4; di<=10; di++)
296       delete argv[di];
297
298     // There is no need to stop the process here, since the process stops itself
299     // after calling forkNodeProcess.
300
301     /* Mark the cm-process as running now */
302     // curr->status = running;
303     //    pauseAllProcesses();
304 }
305
306
307 /*
308  * Define the various classes of library functions to inst. 
309  *
310  */
311 void initLibraryFunctions()
312 {
313     /* should record waiting time in read/write, but have a conflict with
314      *   use of these functions by our inst code.
315      *   This happens when a CPUtimer that is stopped is stopped again by the
316      *   write.  It is then started again at the end of the write and should
317      *   not be running then.  We could let timers go negative, but this
318      *   causes a problem when inst is inserted into already running code.
319      *   Not sure what the best fix is - jkh 10/4/93
320      *
321      */
322 #ifdef notdef
323     tagDict["write"] = TAG_LIB_FUNC | TAG_IO_OUT;
324     tagDict["read"] = TAG_LIB_FUNC | TAG_IO_IN;
325
326     tagDict["send"] = TAG_LIB_FUNC | TAG_CPU_STATE | TAG_MSG_SEND;
327     tagDict["sendmsg"] = TAG_LIB_FUNC | TAG_CPU_STATE | TAG_MSG_SEND;
328     tagDict["sendto"] = TAG_LIB_FUNC | TAG_CPU_STATE | TAG_MSG_SEND;
329
330     tagDict["rev"] = TAG_LIB_FUNC | TAG_CPU_STATE | TAG_MSG_RECV;
331     tagDict["recvmsg"] = TAG_LIB_FUNC | TAG_CPU_STATE | TAG_MSG_RECV;
332     tagDict["recvfrom"] = TAG_LIB_FUNC | TAG_CPU_STATE | TAG_MSG_RECV;
333
334     tagDict["DYNINSTalarmExpire"] = TAG_LIB_FUNC;
335     tagDict["DYNINSTsampleValues"] = TAG_LIB_FUNC;
336     tagDict[EXIT_NAME] = TAG_LIB_FUNC;
337     tagDict["fork"] = TAG_LIB_FUNC;
338
339     tagDict["cmmd_debug"] = TAG_LIB_FUNC;
340     tagDict["CMRT_init"] = TAG_LIB_FUNC;
341     tagDict["CMMD_send"] = TAG_LIB_FUNC;
342     tagDict["CMMD_receive"] = TAG_LIB_FUNC;
343     tagDict["CMMD_receive_block"] = TAG_LIB_FUNC;
344     tagDict["CMMD_send_block"] = TAG_LIB_FUNC;
345     tagDict["CMMD_send_async"] = TAG_LIB_FUNC;
346     tagDict["CMMD_send_async"] = TAG_LIB_FUNC;
347
348     tagDict["main"] = 0;
349 #endif
350 }
351  
352 float computePauseTimeMetric()
353 {
354     timeStamp now;
355     timeStamp elapsed=0.0;
356
357     now = getCurrentTime(false);
358     if (firstRecordTime) {
359         elapsed = elapsedPauseTime;
360         if (isApplicationPaused())
361             elapsed += now - startPause;
362
363         assert(elapsed >= 0.0); 
364         return(elapsed);
365     } else {
366         return(0.0);
367     }
368 }
369
370 void osDependentInst(process *proc) {
371 }