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