Add missing case for system time.
[dyninst.git] / rtinst / src / RTaix.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
18
19 /************************************************************************
20  * RTaix.c: clock access functions for aix.
21  *
22  * $Log: RTaix.c,v $
23  * Revision 1.4  1996/04/06 21:27:50  hollings
24  * Add missing case for system time.
25  *
26  * Revision 1.3  1996/02/13  16:21:57  hollings
27  * Fixed timer64 to be time64.
28  *
29  *
30  ************************************************************************/
31
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #include <malloc.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include "rtinst/h/rtinst.h"
38
39
40 static const double NANO_PER_USEC = 1.0e3;
41 static const long int MILLION       = 1000000;
42
43 /************************************************************************
44  * void DYNINSTos_init(void)
45  *
46  * os initialization function---currently null.
47 ************************************************************************/
48
49 void
50 DYNINSTos_init(void) {
51 }
52
53
54 /************************************************************************
55  * time64 DYNINSTgetCPUtime(void)
56  *
57  * return value is in usec units.
58 ************************************************************************/
59
60 time64
61 DYNINSTgetCPUtime(void) {
62      time64 now;
63      static time64 previous=0;
64      struct rusage ru;
65
66 try_again:    
67     if (!getrusage(RUSAGE_SELF, &ru)) {
68       now = (time64)ru.ru_utime.tv_sec + (time64)ru.ru_stime.tv_sec;
69       now *= (time64)1000000;
70       now += (time64)ru.ru_utime.tv_usec + (time64)ru.ru_stime.tv_usec;
71       if (now<previous) {
72         goto try_again;
73       }
74       previous=now;
75       return(now);
76     }
77     else {
78       perror("getrusage");
79       abort();
80     }
81 }
82
83
84 \f
85
86
87 /************************************************************************
88  * time64 DYNINSTgetWalltime(void)
89  *
90  * get the total walltime used by the monitored process.
91  * return value is in usec units.
92 ************************************************************************/
93
94 time64 DYNINSTgetWalltime(void) {
95     time64 now;
96     register unsigned int timeSec asm("5");
97     register unsigned int timeNano asm("6");
98     register unsigned int timeSec2 asm("7");
99
100     /* Need to read the first value twice to make sure it doesn't role
101      *   over while we are reading it.
102      */
103 retry:
104     asm("mfspr   5,4");         /* read high into register 5 - timeSec */
105     asm("mfspr   6,5");         /* read low into register 6 - timeNano */
106     asm("mfspr   7,4");         /* read high into register 7 - timeSec2 */
107
108     if (timeSec != timeSec2) goto retry;
109     /* convert to correct form. */
110     now = (time64)timeSec;
111     now *= (time64)MILLION;
112     now += (time64)timeNano/(time64)1000;
113     return(now);
114 }
115
116
117 /*
118  * Code to trap execvp call and munge command (for SP-2).
119  *
120  */
121 void DYNINSTexecvp(char *argv[])
122 {
123      int i;
124      int ret;
125      char *ch;
126      char *cmd;
127      int iCount;
128      int acount;
129      char *pdArgs;
130      char **newArgs;
131      static int inExecvp;
132
133      if (inExecvp) return;
134      inExecvp = 1;
135
136      cmd = argv[0];
137
138      /* this only applies to poe on the SP-2 */
139      if (strcmp(cmd, "poe")) return;
140
141      for (iCount=0; argv[iCount]; iCount++);
142
143      pdArgs = (char *) getenv("PARADYN_MASTER_INFO");
144      if (!pdArgs) {
145          fprintf(stdout, "unable to get PARADYN_MASTER_INFO\n");
146          fflush(stdout);
147          return;
148      }
149
150      /* extras for first arg, command, -runme, and null  */
151      for (ch=pdArgs, acount=4; *ch; ch++) if (*ch == ' ') acount++;
152      newArgs = calloc(sizeof(char*), iCount+acount);
153
154      newArgs[0] = "poe";
155      newArgs[1] = "paradynd";
156
157      /* skip white spave at start */
158      while (*pdArgs && *pdArgs == ' ') pdArgs++;
159      newArgs[2] = pdArgs;
160      for (ch=pdArgs, acount=3; *ch; ch++) {
161          if (*ch == ' ') {
162              *ch = '\0';
163              /* skip over null argument -caused by spaces in environment var */
164              if (!strlen(newArgs[acount-1])) acount--;
165              newArgs[acount++] = ++ch;
166          }
167      }
168      /* skip over null argument -caused by space at end of environment var */
169      if (!strlen(newArgs[acount-1])) acount--;
170
171      newArgs[acount++] = "-runme";
172      for (i=1; i < iCount; i++) {
173          newArgs[acount++] = argv[i];
174      }
175
176      newArgs[acount] = "";
177
178      /* generate an exit record about the process to paradynd */
179      DYNINSTprintCost();
180
181      /* Now call execvp with the correct arguments */
182      ret = execvp(cmd, newArgs);
183
184      fprintf(stderr, "execvp failed\n");
185      perror("execvp");
186      fflush(stderr);
187
188      exit(-1);
189
190      inExecvp = 0;
191      return;
192 }
193
194
195 /*
196  * DYNINSTgetRusage(id) - Return the value of various OS stats.
197  *
198  *    The id is an integer, and when they are changed, any metric that uses
199  *        DYNINSTgetRusage will also need to be updated.
200  *
201  */
202 int DYNINSTgetRusage(int id)
203 {
204     int ret;
205     int value;
206     struct rusage rusage;
207     struct rusage *DYNINSTrusagePtr;
208
209     ret = getrusage(RUSAGE_SELF, &rusage);
210     if (ret) {
211         perror("getrusage");
212     }
213     DYNINSTrusagePtr = &rusage;
214     switch (id) {
215         case 0: /* page faults */
216             value = DYNINSTrusagePtr->ru_minflt+DYNINSTrusagePtr->ru_majflt;
217             break;
218         case 1: /* swaps */
219             value = DYNINSTrusagePtr->ru_nswap;
220             break;
221         case 2: /* signals received */
222             value = DYNINSTrusagePtr->ru_nsignals;
223             break;
224         case 3: /* max rss */
225             value = DYNINSTrusagePtr->ru_maxrss;
226             break;
227         case 4: /* context switches */
228             value = DYNINSTrusagePtr->ru_nvcsw + DYNINSTrusagePtr->ru_nivcsw;
229             break;
230         case 5: /* system time - in mili-seconds */
231             value = 1000 * DYNINSTrusagePtr->ru_stime.tv_sec + 
232                            DYNINSTrusagePtr->ru_stime.tv_usec/1000;
233             break;
234         default:
235             value = 0;
236             break;
237     }
238     return value;
239 }