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