updated copyright for release 1.1
[dyninst.git] / rtinst / src / RTetc-aix.c
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * RTaix.c: clock access functions for aix.
44  *
45  * $Log: RTetc-aix.c,v $
46  * Revision 1.5  1996/08/16 21:27:27  tamches
47  * updated copyright for release 1.1
48  *
49  * Revision 1.4  1996/04/06 21:27:50  hollings
50  * Add missing case for system time.
51  *
52  * Revision 1.3  1996/02/13  16:21:57  hollings
53  * Fixed timer64 to be time64.
54  *
55  *
56  ************************************************************************/
57
58 #include <sys/time.h>
59 #include <sys/resource.h>
60 #include <malloc.h>
61 #include <stdlib.h>
62 #include <stdio.h>
63 #include "rtinst/h/rtinst.h"
64
65
66 static const double NANO_PER_USEC = 1.0e3;
67 static const long int MILLION       = 1000000;
68
69 /************************************************************************
70  * void DYNINSTos_init(void)
71  *
72  * os initialization function---currently null.
73 ************************************************************************/
74
75 void
76 DYNINSTos_init(void) {
77 }
78
79
80 /************************************************************************
81  * time64 DYNINSTgetCPUtime(void)
82  *
83  * return value is in usec units.
84 ************************************************************************/
85
86 time64
87 DYNINSTgetCPUtime(void) {
88      time64 now;
89      static time64 previous=0;
90      struct rusage ru;
91
92 try_again:    
93     if (!getrusage(RUSAGE_SELF, &ru)) {
94       now = (time64)ru.ru_utime.tv_sec + (time64)ru.ru_stime.tv_sec;
95       now *= (time64)1000000;
96       now += (time64)ru.ru_utime.tv_usec + (time64)ru.ru_stime.tv_usec;
97       if (now<previous) {
98         goto try_again;
99       }
100       previous=now;
101       return(now);
102     }
103     else {
104       perror("getrusage");
105       abort();
106     }
107 }
108
109
110 \f
111
112
113 /************************************************************************
114  * time64 DYNINSTgetWalltime(void)
115  *
116  * get the total walltime used by the monitored process.
117  * return value is in usec units.
118 ************************************************************************/
119
120 time64 DYNINSTgetWalltime(void) {
121     time64 now;
122     register unsigned int timeSec asm("5");
123     register unsigned int timeNano asm("6");
124     register unsigned int timeSec2 asm("7");
125
126     /* Need to read the first value twice to make sure it doesn't role
127      *   over while we are reading it.
128      */
129 retry:
130     asm("mfspr   5,4");         /* read high into register 5 - timeSec */
131     asm("mfspr   6,5");         /* read low into register 6 - timeNano */
132     asm("mfspr   7,4");         /* read high into register 7 - timeSec2 */
133
134     if (timeSec != timeSec2) goto retry;
135     /* convert to correct form. */
136     now = (time64)timeSec;
137     now *= (time64)MILLION;
138     now += (time64)timeNano/(time64)1000;
139     return(now);
140 }
141
142
143 /*
144  * Code to trap execvp call and munge command (for SP-2).
145  *
146  */
147 void DYNINSTexecvp(char *argv[])
148 {
149      int i;
150      int ret;
151      char *ch;
152      char *cmd;
153      int iCount;
154      int acount;
155      char *pdArgs;
156      char **newArgs;
157      static int inExecvp;
158
159      if (inExecvp) return;
160      inExecvp = 1;
161
162      cmd = argv[0];
163
164      /* this only applies to poe on the SP-2 */
165      if (strcmp(cmd, "poe")) return;
166
167      for (iCount=0; argv[iCount]; iCount++);
168
169      pdArgs = (char *) getenv("PARADYN_MASTER_INFO");
170      if (!pdArgs) {
171          fprintf(stdout, "unable to get PARADYN_MASTER_INFO\n");
172          fflush(stdout);
173          return;
174      }
175
176      /* extras for first arg, command, -runme, and null  */
177      for (ch=pdArgs, acount=4; *ch; ch++) if (*ch == ' ') acount++;
178      newArgs = calloc(sizeof(char*), iCount+acount);
179
180      newArgs[0] = "poe";
181      newArgs[1] = "paradynd";
182
183      /* skip white spave at start */
184      while (*pdArgs && *pdArgs == ' ') pdArgs++;
185      newArgs[2] = pdArgs;
186      for (ch=pdArgs, acount=3; *ch; ch++) {
187          if (*ch == ' ') {
188              *ch = '\0';
189              /* skip over null argument -caused by spaces in environment var */
190              if (!strlen(newArgs[acount-1])) acount--;
191              newArgs[acount++] = ++ch;
192          }
193      }
194      /* skip over null argument -caused by space at end of environment var */
195      if (!strlen(newArgs[acount-1])) acount--;
196
197      newArgs[acount++] = "-runme";
198      for (i=1; i < iCount; i++) {
199          newArgs[acount++] = argv[i];
200      }
201
202      newArgs[acount] = "";
203
204      /* generate an exit record about the process to paradynd */
205      DYNINSTprintCost();
206
207      /* Now call execvp with the correct arguments */
208      ret = execvp(cmd, newArgs);
209
210      fprintf(stderr, "execvp failed\n");
211      perror("execvp");
212      fflush(stderr);
213
214      exit(-1);
215
216      inExecvp = 0;
217      return;
218 }
219
220
221 /*
222  * DYNINSTgetRusage(id) - Return the value of various OS stats.
223  *
224  *    The id is an integer, and when they are changed, any metric that uses
225  *        DYNINSTgetRusage will also need to be updated.
226  *
227  */
228 int DYNINSTgetRusage(int id)
229 {
230     int ret;
231     int value;
232     struct rusage rusage;
233     struct rusage *DYNINSTrusagePtr;
234
235     ret = getrusage(RUSAGE_SELF, &rusage);
236     if (ret) {
237         perror("getrusage");
238     }
239     DYNINSTrusagePtr = &rusage;
240     switch (id) {
241         case 0: /* page faults */
242             value = DYNINSTrusagePtr->ru_minflt+DYNINSTrusagePtr->ru_majflt;
243             break;
244         case 1: /* swaps */
245             value = DYNINSTrusagePtr->ru_nswap;
246             break;
247         case 2: /* signals received */
248             value = DYNINSTrusagePtr->ru_nsignals;
249             break;
250         case 3: /* max rss */
251             value = DYNINSTrusagePtr->ru_maxrss;
252             break;
253         case 4: /* context switches */
254             value = DYNINSTrusagePtr->ru_nvcsw + DYNINSTrusagePtr->ru_nivcsw;
255             break;
256         case 5: /* system time - in mili-seconds */
257             value = 1000 * DYNINSTrusagePtr->ru_stime.tv_sec + 
258                            DYNINSTrusagePtr->ru_stime.tv_usec/1000;
259             break;
260         default:
261             value = 0;
262             break;
263     }
264     return value;
265 }