There were some bugs in how the time was accessed, fixed those; I also
[dyninst.git] / rtinst / src / RTaix.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: RTaix.c,v $
46  * Revision 1.9  1997/02/18 21:34:37  sec
47  * There were some bugs in how the time was accessed, fixed those; I also
48  * removed DYNISTexecvp which is buggy, and is never called (it was called
49  * for MPI stuff, but I replaced it with some modifications for poe/mpi in
50  * paradyn/DMthread).
51  *
52  * Revision 1.8  1997/01/27 19:43:31  naim
53  * Part of the base instrumentation for supporting multithreaded applications
54  * (vectors of counter/timers) implemented for all current platforms +
55  * different bug fixes - naim
56  *
57  * Revision 1.7  1997/01/16 22:19:34  tamches
58  * added proper param names to DYNINSTos_init
59  *
60  * Revision 1.6  1997/01/16 20:55:45  tamches
61  * params to DYNINSTos_init
62  *
63  * Revision 1.5  1996/08/16 21:27:27  tamches
64  * updated copyright for release 1.1
65  *
66  * Revision 1.4  1996/04/06 21:27:50  hollings
67  * Add missing case for system time.
68  *
69  * Revision 1.3  1996/02/13  16:21:57  hollings
70  * Fixed timer64 to be time64.
71  *
72  *
73  ************************************************************************/
74
75 #include <malloc.h>
76 #include <stdlib.h>
77 #include <stdio.h>
78 #include <errno.h>
79 #include <unistd.h>
80 #include <string.h>
81 #include <assert.h>
82 #include <signal.h>
83 #include <sys/reg.h>
84 #include <sys/ptrace.h>
85 #include <sys/ldr.h>
86 #include <sys/time.h>
87 #include <sys/resource.h>
88
89 #include "rtinst/h/rtinst.h"
90
91 #if defined(MT_THREAD)
92 #include <sys/thread.h>
93 #endif
94
95 static const double NANO_PER_USEC   = 1.0e3;
96 static const long int MILLION       = 1000000;
97
98 /************************************************************************
99  * void DYNINSTos_init(void)
100  *
101  * os initialization function---currently null.
102 ************************************************************************/
103
104 void
105 DYNINSTos_init(int calledByFork, int calledByAttach) {
106 }
107
108
109 /************************************************************************
110  * time64 DYNINSTgetCPUtime(void)
111  *
112  * return value is in usec units.
113 ************************************************************************/
114
115 time64 DYNINSTgetCPUtime(void) 
116 {
117   time64        now;
118   static time64 prevTime = 0;
119   struct rusage ru;
120
121   do {
122     if (!getrusage(RUSAGE_SELF, &ru)) {
123       now = (time64) ru.ru_utime.tv_sec + (time64) ru.ru_stime.tv_sec;
124       now *= (time64) 1000000;
125       now += (time64) ru.ru_utime.tv_usec + (time64) ru.ru_stime.tv_usec;
126     } else {
127       perror("getrusage");
128       abort();
129     }
130   } while(prevTime > now);
131
132   prevTime = now;
133   return(now);
134 }
135
136
137
138
139
140 /************************************************************************
141  * time64 DYNINSTgetWalltime(void)
142  *
143  * get the total walltime used by the monitored process.
144  * return value is in usec units.
145 ************************************************************************/
146
147 time64 DYNINSTgetWalltime(void)
148 {
149   static time64 prevTime = 0;
150   time64        now;
151
152   register unsigned int timeSec asm("5");
153   register unsigned int timeNano asm("6");
154   register unsigned int timeSec2 asm("7");
155   
156   /* Need to read the first value twice to make sure it doesn't role
157    *   over while we are reading it.
158    */
159   do {
160     asm("mfspr   5,4");         /* read high into register 5 - timeSec */
161     asm("mfspr   6,5");         /* read low into register 6 - timeNano */
162     asm("mfspr   7,4");         /* read high into register 7 - timeSec2 */
163   } while(timeSec != timeSec2);
164   
165   /* convert to correct form. */
166   now = (time64) timeSec;
167   now *= (time64) MILLION;
168   now += (time64) timeNano/ (time64) 1000;
169
170   if(prevTime > now) {
171     fprintf(stderr, "ERROR:  prevTime (%f) > now (%f)\n", 
172             (double) prevTime, (double) now);
173     return(prevTime);
174   } else {
175     prevTime = now;
176     return(now);
177   }
178 }
179
180
181 /*
182  * DYNINSTgetRusage(id) - Return the value of various OS stats.
183  *
184  *    The id is an integer, and when they are changed, any metric that uses
185  *        DYNINSTgetRusage will also need to be updated.
186  *
187  */
188 int DYNINSTgetRusage(int id)
189 {
190
191     int ret;
192     int value;
193     struct rusage rusage;
194     struct rusage *DYNINSTrusagePtr;
195
196     ret = getrusage(RUSAGE_SELF, &rusage);
197     if (ret) {
198         perror("getrusage");
199     }
200     DYNINSTrusagePtr = &rusage;
201     switch (id) {
202         case 0: /* page faults */
203             value = DYNINSTrusagePtr->ru_minflt+DYNINSTrusagePtr->ru_majflt;
204             break;
205         case 1: /* swaps */
206             value = DYNINSTrusagePtr->ru_nswap;
207             break;
208         case 2: /* signals received */
209             value = DYNINSTrusagePtr->ru_nsignals;
210             break;
211         case 3: /* max rss */
212             value = DYNINSTrusagePtr->ru_maxrss;
213             break;
214         case 4: /* context switches */
215             value = DYNINSTrusagePtr->ru_nvcsw + DYNINSTrusagePtr->ru_nivcsw;
216             break;
217         case 5: /* system time - in mili-seconds */
218             value = 1000 * DYNINSTrusagePtr->ru_stime.tv_sec + 
219                            DYNINSTrusagePtr->ru_stime.tv_usec/1000;
220             break;
221         default:
222             value = 0;
223             break;
224     }
225     return value;
226 }
227
228 #if defined(MT_THREAD)
229 extern unsigned hash_lookup(unsigned key);
230 extern unsigned initialize_done;
231 extern void initialize_hash(unsigned total);
232 extern void initialize_free(unsigned total);
233 extern unsigned hash_insert(unsigned k);
234
235 int DYNINSTthreadSelf(void) {
236   return(thread_self());
237 }
238
239 int DYNINSTthreadPos(void) {
240   if (initialize_done) {
241     return(hash_lookup(DYNINSTthreadSelf()));
242   } else {
243     initialize_free(MAX_NUMBER_OF_THREADS);
244     initialize_hash(MAX_NUMBER_OF_THREADS);
245     initialize_done=1;
246     return(hash_insert(DYNINSTthreadSelf()));
247   }
248 }
249 #endif