2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
43 * util.C - support functions.
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.
50 * Revision 1.18 1997/08/19 19:50:55 naim
51 * Adding support to dynamically link libdyninstRT by using dlopen on sparc-
54 * Revision 1.17 1997/06/23 17:13:52 tamches
55 * some additional hash functions
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
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.
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
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
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
83 * Revision 1.11 1996/10/31 08:54:23 tamches
84 * added some time routines
86 * Revision 1.10 1996/08/16 21:20:14 tamches
87 * updated copyright for release 1.1
89 * Revision 1.9 1996/06/01 00:01:48 tamches
90 * addrHash replaced by addrHash16
92 * Revision 1.8 1996/05/11 23:16:17 tamches
95 * Revision 1.7 1995/02/16 08:54:28 markc
96 * Corrected error in comments -- I put a "star slash" in the comment.
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
108 * Revision 1.5 1994/11/02 11:18:54 markc
109 * Remove old malloc wrappers.
111 * Revision 1.4 1994/09/22 02:27:37 markc
112 * Changed signature to intComp
116 #include "util/h/headers.h"
117 #ifndef BPATCH_LIBRARY
118 #include "rtinst/h/rtinst.h" // for time64
120 #include "dyninstAPI/src/util.h"
124 #if defined(sparc_sun_solaris2_4)
128 #define TIMINGunit 1.0e+09 // 1.0e+09 ns -> secs
129 // 1.0e+06 ns -> mils
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];
145 time64 firstRecordTime = 0; // time64 = long long int (rtinst/h/rtinst.h)
146 timeStamp getCurrentTime(bool firstRecordRelative)
148 static double previousTime=0.0;
152 #if !defined(i386_unknown_nt4_0)
155 if (-1 == gettimeofday(&tv, NULL)) {
156 perror("getCurrentTime gettimeofday()");
160 result = tv.tv_sec * 1.0;
162 assert(tv.tv_usec < 1000000);
163 double useconds_dbl = tv.tv_usec * 1.0;
165 result += useconds_dbl / 1000000.0;
166 } while (result < previousTime); // retry if we've gone backwards
168 previousTime = result;
171 static double freq=0.0; // the counter frequency
175 if (QueryPerformanceFrequency(&time))
176 freq = (double)time.QuadPart;
180 if (QueryPerformanceCounter(&time))
181 result = (double)time.QuadPart/freq;
186 if (firstRecordRelative)
187 result -= firstRecordTime;
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.
198 static time64 previousTime = 0;
201 #if !defined(i386_unknown_nt4_0)
204 if (-1 == gettimeofday(&tv, NULL)) {
205 perror("getCurrWallTime gettimeofday()");
211 result += tv.tv_usec;
212 } while (result < previousTime);
214 previousTime = result;
216 static double freq=0.0; // the counter frequency
220 if (QueryPerformanceFrequency(&time))
221 freq = (double)time.QuadPart;
225 if (QueryPerformanceCounter(&time))
226 result = (time64)(((double)time.QuadPart/freq)*1000000.0);
234 time64 userAndSysTime2uSecs(const timeval &uTime,
235 const timeval &sysTime) {
236 time64 result = uTime.tv_sec + sysTime.tv_sec;
239 result += uTime.tv_usec + sysTime.tv_usec;
245 static unsigned addrHashCommon(unsigned addr) {
246 // inspired by hashs of string class
248 register unsigned result = 5381;
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);
260 unsigned addrHash(const unsigned iaddr) {
261 return addrHashCommon(iaddr);
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);
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);
278 log_printf(const char* fmt, ...) {
281 vsprintf(errorLine, fmt, ap);
284 // printf("%s", log_buffer);
289 pd_log_perror(const char* msg) {
290 sprintf(errorLine, "%s: %s\n", msg, sys_errlist[errno]);
292 // fprintf(stderr, "%s", log_buffer);
297 #if defined(sparc_sun_solaris2_4)
299 void begin_timing(int id)
301 static bool first_time=true;
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");
309 for (unsigned i=0;i<MAX_N_TIMERS;i++) {
320 TIMINGtime1[id]=gethrtime();
323 void end_timing(int id, char *func)
325 static bool first_time=true;
326 static FILE *fp=NULL;
329 fp = fopen("timing.out","w");
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];
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);
340 fprintf(fp,"%s",P_strdup(errorLine));