Added some more #ifdef BPATCH_LIBRARYs to eliminate some Dyninst API
[dyninst.git] / dyninstAPI / src / util.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  * util.C - support functions.
44  *
45  * $Log: util.C,v $
46  * Revision 1.19  1997/09/28 22:22:35  buck
47  * Added some more #ifdef BPATCH_LIBRARYs to eliminate some Dyninst API
48  * library dependencies on files in rtinst.
49  *
50  * Revision 1.18  1997/08/19 19:50:55  naim
51  * Adding support to dynamically link libdyninstRT by using dlopen on sparc-
52  * solaris - naim
53  *
54  * Revision 1.17  1997/06/23 17:13:52  tamches
55  * some additional hash functions
56  *
57  * Revision 1.16  1997/04/29 23:16:33  mjrg
58  * Changes for WindowsNT port
59  * Delayed check for DYNINST symbols to allow linking libdyninst dynamically
60  * Changed way paradyn and paradynd generate resource ids
61  * Changes to instPoint class in inst-x86.C to reduce size of objects
62  * Added initialization for process->threads to fork and attach constructors
63  *
64  * Revision 1.15  1997/03/18 19:44:32  buck
65  * first commit of dyninst library.  Also includes:
66  *      moving templates from paradynd to dyninstAPI
67  *      converting showError into a function (in showerror.C)
68  *      many ifdefs for BPATCH_LIBRARY in dyinstAPI/src.
69  *
70  * Revision 1.14  1997/02/26 23:43:10  mjrg
71  * First part on WindowsNT port: changes for compiling with Visual C++;
72  * moved unix specific code to unix.C
73  *
74  * Revision 1.13  1997/02/21 20:13:59  naim
75  * Moving files from paradynd to dyninstAPI + moving references to dataReqNode
76  * out of the ast class. The is the first pre-dyninstAPI commit! - naim
77  *
78  * Revision 1.12  1997/01/27 19:41:18  naim
79  * Part of the base instrumentation for supporting multithreaded applications
80  * (vectors of counter/timers) implemented for all current platforms +
81  * different bug fixes - naim
82  *
83  * Revision 1.11  1996/10/31 08:54:23  tamches
84  * added some time routines
85  *
86  * Revision 1.10  1996/08/16 21:20:14  tamches
87  * updated copyright for release 1.1
88  *
89  * Revision 1.9  1996/06/01 00:01:48  tamches
90  * addrHash replaced by addrHash16
91  *
92  * Revision 1.8  1996/05/11 23:16:17  tamches
93  * added addrHash
94  *
95  * Revision 1.7  1995/02/16 08:54:28  markc
96  * Corrected error in comments -- I put a "star slash" in the comment.
97  *
98  * Revision 1.6  1995/02/16  08:35:03  markc
99  * Changed igen interfaces to use strings/vectors rather than char igen-arrays
100  * Changed igen interfaces to use bool, not Boolean.
101  * Cleaned up symbol table parsing - favor properly labeled symbol table objects
102  * Updated binary search for modules
103  * Moved machine dependnent ptrace code to architecture specific files.
104  * Moved machine dependent code out of class process.
105  * Removed almost all compiler warnings.
106  * Use "posix" like library to remove compiler warnings
107  *
108  * Revision 1.5  1994/11/02  11:18:54  markc
109  * Remove old malloc wrappers.
110  *
111  * Revision 1.4  1994/09/22  02:27:37  markc
112  * Changed signature to intComp
113  *
114  */
115
116 #include "util/h/headers.h"
117 #ifndef BPATCH_LIBRARY
118 #include "rtinst/h/rtinst.h" // for time64
119 #endif
120 #include "dyninstAPI/src/util.h"
121
122 // TIMING code
123
124 #if defined(sparc_sun_solaris2_4)
125
126 #include <values.h>
127 #define EVERY 1
128 #define TIMINGunit 1.0e+09 // 1.0e+09 ns -> secs
129                            // 1.0e+06 ns -> mils
130                            // 1.0e+03 ns -> us 
131                            // 1.0e+00 ns
132
133 hrtime_t TIMINGtime1[MAX_N_TIMERS];
134 hrtime_t TIMINGtime2[MAX_N_TIMERS]; 
135 hrtime_t TIMINGcur[MAX_N_TIMERS];
136 hrtime_t TIMINGtot[MAX_N_TIMERS];
137 hrtime_t TIMINGmax[MAX_N_TIMERS];
138 hrtime_t TIMINGmin[MAX_N_TIMERS];
139 int TIMINGcounter[MAX_N_TIMERS];
140
141 #endif
142
143 // TIMING code
144
145 time64 firstRecordTime = 0; // time64 = long long int (rtinst/h/rtinst.h)
146 timeStamp getCurrentTime(bool firstRecordRelative)
147 {
148     static double previousTime=0.0;
149
150     double result = 0.0;
151
152 #if !defined(i386_unknown_nt4_0)
153     do {
154        struct timeval tv;
155        if (-1 == gettimeofday(&tv, NULL)) {
156           perror("getCurrentTime gettimeofday()");
157           return 0;
158        }
159
160        result = tv.tv_sec * 1.0;
161
162        assert(tv.tv_usec < 1000000);
163        double useconds_dbl = tv.tv_usec * 1.0;
164
165        result += useconds_dbl / 1000000.0;
166     } while (result < previousTime); // retry if we've gone backwards
167
168     previousTime = result;
169
170 #else
171     static double freq=0.0; // the counter frequency
172     LARGE_INTEGER time;
173
174     if (freq == 0.0)
175       if (QueryPerformanceFrequency(&time))
176         freq = (double)time.QuadPart;
177       else
178         assert(0);
179
180     if (QueryPerformanceCounter(&time))
181        result = (double)time.QuadPart/freq;
182     else
183        assert(0);
184 #endif
185
186     if (firstRecordRelative)
187        result -= firstRecordTime;
188
189     return result;
190 }
191
192 #ifndef BPATCH_LIBRARY
193 time64 getCurrWallTime() {
194    // like the above routine but doesn't return a double value representing
195    // # of seconds; instead, it returns a long long int representing the # of
196    // microseconds since the beginning of time.
197  
198    static time64 previousTime = 0;
199    time64 result;
200     
201 #if !defined(i386_unknown_nt4_0)
202    do {
203       struct timeval tv;
204       if (-1 == gettimeofday(&tv, NULL)) {
205          perror("getCurrWallTime gettimeofday()");
206          return 0;
207       }
208
209       result = tv.tv_sec;
210       result *= 1000000;
211       result += tv.tv_usec;
212    } while (result < previousTime);
213
214    previousTime = result;
215 #else
216     static double freq=0.0; // the counter frequency
217     LARGE_INTEGER time;
218
219     if (freq == 0.0)
220       if (QueryPerformanceFrequency(&time))
221         freq = (double)time.QuadPart;
222       else
223         assert(0);
224
225     if (QueryPerformanceCounter(&time))
226        result = (time64)(((double)time.QuadPart/freq)*1000000.0);
227     else
228        assert(0);
229 #endif
230
231    return result;
232 }
233
234 time64 userAndSysTime2uSecs(const timeval &uTime,
235                                         const timeval &sysTime) {
236    time64 result = uTime.tv_sec + sysTime.tv_sec;
237    result *= 1000000;
238
239    result += uTime.tv_usec + sysTime.tv_usec;
240
241    return result;
242 }
243 #endif
244
245 static unsigned addrHashCommon(unsigned addr) {
246    // inspired by hashs of string class
247
248    register unsigned result = 5381;
249
250    register unsigned accumulator = addr;
251    while (accumulator > 0) {
252       // We use 3 bits at a time from the address
253       result = (result << 4) + result + (accumulator & 0x07);
254       accumulator >>= 3;
255    }
256
257    return result;
258 }
259
260 unsigned addrHash(const unsigned iaddr) {
261    return addrHashCommon(iaddr);
262 }
263
264 unsigned addrHash4(const unsigned &iaddr) {
265    // call when you know that the low 2 bits are 0 (meaning they contribute
266    // nothing to an even hash distribution)
267    return addrHashCommon(iaddr >> 2);
268 }
269
270 unsigned addrHash16(const unsigned &iaddr) {
271    // call when you know that the low 4 bits are 0 (meaning they contribute
272    // nothing to an even hash distribution)
273    return addrHashCommon(iaddr >> 4);
274 }
275
276 #ifdef notdef
277 void
278 log_printf(const char* fmt, ...) {
279     va_list ap;
280     va_start(ap, fmt);
281     vsprintf(errorLine, fmt, ap);
282     va_end(ap);
283     logLine(errorLine);
284     // printf("%s", log_buffer);
285 }
286 #endif
287
288 void
289 pd_log_perror(const char* msg) {
290     sprintf(errorLine, "%s: %s\n", msg, sys_errlist[errno]);
291     logLine(errorLine);
292     // fprintf(stderr, "%s", log_buffer);
293 }
294
295 // TIMING code
296
297 #if defined(sparc_sun_solaris2_4)
298
299 void begin_timing(int id)
300 {
301   static bool first_time=true;
302   if (first_time) {
303     if (TIMINGunit==1.0e+09) sprintf(errorLine,"TIME in seconds\n");
304     else if (TIMINGunit==1.0e+06) sprintf(errorLine,"TIME in mil-seconds\n");
305     else if (TIMINGunit==1.0e+03) sprintf(errorLine,"TIME in micro-seconds\n");
306     else if (TIMINGunit==1.0e+00) sprintf(errorLine,"TIME in nano-seconds\n");
307     else sprintf(errorLine,"TIME with UNKNOWN units\n");
308     logLine(errorLine);
309     for (unsigned i=0;i<MAX_N_TIMERS;i++) {
310       TIMINGtime1[i]=0;
311       TIMINGtime2[i]=0;
312       TIMINGcur[i]=0;
313       TIMINGtot[i]=0;
314       TIMINGmax[i]=0;
315       TIMINGmin[i]=MAXINT;
316       TIMINGcounter[i]=0;
317     }
318     first_time=false;
319   }
320   TIMINGtime1[id]=gethrtime();
321 }
322
323 void end_timing(int id, char *func)
324 {
325   static bool first_time=true;
326   static FILE *fp=NULL;
327   if (first_time) {
328     first_time=false;
329     fp = fopen("timing.out","w");
330   }
331   TIMINGtime2[id]=gethrtime();
332   TIMINGcur[id]=TIMINGtime2[id]-TIMINGtime1[id];
333   if (TIMINGcur[id] > TIMINGmax[id]) TIMINGmax[id]=TIMINGcur[id];
334   if (TIMINGcur[id] < TIMINGmin[id]) TIMINGmin[id]=TIMINGcur[id];
335   TIMINGtot[id] += TIMINGcur[id];
336   TIMINGcounter[id]++;
337   if (!(TIMINGcounter[id]%EVERY)) {
338     sprintf(errorLine,"<%s> cur=%5.2f, avg=%5.2f, max=%5.2f, min=%5.2f, tot=%5.2f\n",func,TIMINGcur[id]/TIMINGunit,(TIMINGtot[id]/TIMINGcounter[id])/TIMINGunit,TIMINGmax[id]/TIMINGunit,TIMINGmin[id]/TIMINGunit,TIMINGtot[id]/TIMINGunit);
339     if (fp) {
340       fprintf(fp,"%s",P_strdup(errorLine));
341       fflush(fp);
342     } else {
343       logLine(errorLine);
344     }
345   }
346 }
347
348 #endif
349
350 // TIMING code
351
352