- Linux-x86 support changes
[dyninst.git] / pdutil / src / Timer.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 // Timer.C
43
44 #include "util/h/Timer.h"
45
46 timer::timer()
47 : usecs_(0), ssecs_(0), wsecs_(0), cu_(0), cs_(0), cw_(0),
48   state_(STOPPED),
49 #if defined(i386_unknown_nt4_0)
50   CYCLES_PER_SEC_(CLK_TCK), // TODO: is this right?
51 #else
52   CYCLES_PER_SEC_(sysconf(_SC_CLK_TCK)), 
53 #endif
54   MICROSECS_PER_SEC_(1.0e6),
55   NANOSECS_PER_SEC_(1.0e9)
56 {
57 }
58
59 timer::timer(const timer& t)
60     : usecs_(t.usecs_), ssecs_(t.ssecs_), wsecs_(t.wsecs_),
61     cu_(t.cu_), cs_(t.cs_), cw_(t.cw_), state_(t.state_),
62     CYCLES_PER_SEC_(t.CYCLES_PER_SEC_), MICROSECS_PER_SEC_(t.MICROSECS_PER_SEC_),
63     NANOSECS_PER_SEC_(t.NANOSECS_PER_SEC_)
64 {
65 }
66
67 timer::~timer() {}
68
69 timer&
70 timer::operator=(const timer& t) {
71     if (this != &t) {
72         usecs_ = t.usecs_; ssecs_ = t.ssecs_; wsecs_ = t.wsecs_;
73         cu_    = t.cu_;    cs_    = t.cs_;    cw_    = t.cw_;
74         state_ = t.state_;
75     }
76     return *this;
77 }
78
79 timer&
80 timer::operator+=(const timer& t) {
81     timer st = t; st.stop();
82     usecs_ += st.usecs_;
83     ssecs_ += st.ssecs_;
84     wsecs_ += st.wsecs_;
85     return *this;
86 }
87
88 timer
89 timer::operator+(const timer& t) const {
90     timer ret = *this;
91     return ret += t;
92 }
93
94 void
95 timer::clear() {
96     usecs_ = ssecs_ = wsecs_ = 0;
97     cu_    = cs_    = cw_    = 0;
98     state_ = STOPPED;
99 }
100
101 void
102 timer::start() {
103     get_current(cu_, cs_, cw_);
104     state_ = RUNNING;
105 }
106
107 void
108 timer::stop() {
109     if (state_ == RUNNING) {
110         double cu, cs, cw;
111         get_current(cu, cs, cw);
112
113         usecs_ += (cu - cu_);
114         ssecs_ += (cs - cs_);
115         wsecs_ += (cw - cw_);
116         state_ = STOPPED;
117     }
118 }
119
120 double
121 timer::usecs() const {
122     return usecs_;
123 }
124
125 double
126 timer::ssecs() const {
127     return ssecs_;
128 }
129
130 double
131 timer::wsecs() const {
132     return wsecs_;
133 }
134
135 bool
136 timer::is_running() const {
137     return (state_ == RUNNING);
138 }
139
140 #if defined(notdef)
141 void
142 timer::print(ostream& os) {
143     timer_state ostate = state_;
144     if (ostate == RUNNING) {
145         stop();
146     }
147
148     os << "{"
149        << " usecs=" << usecs_
150        << " ssecs=" << ssecs_
151        << " wsecs=" << wsecs_
152        << " }";
153
154     if (ostate == RUNNING) {
155         start();
156     }
157 }
158 #endif
159
160 \f
161
162
163 /************************************************************************
164  * architecture/operating system specific timer functions.
165 ************************************************************************/
166
167
168 \f
169
170
171 #undef HAVE_GET_CURRENT_DEFINITION
172
173
174 \f
175
176 #if defined(i386_unknown_nt4_0)
177 #if !defined(HAVE_GET_CURRENT_DEFINITION)
178 #define HAVE_GET_CURRENT_DEFINITION
179
180 #include <sys/timeb.h>
181 #include <time.h>
182 #include <winbase.h>
183 #include <limits.h>
184
185 void
186 timer::get_current(double& u, double& s, double& w) {
187   /*
188     u = user time
189     s = system time
190     w = wall time
191   */
192
193   struct _timeb tb;
194   _ftime(&tb);
195   w = (double)tb.time + (double)tb.millitm/1000.0;
196
197   FILETIME kernelT, userT, creatT, exitT;
198   if (GetProcessTimes(GetCurrentProcess(), &creatT, &exitT, &kernelT, &userT)) {
199     timer t;
200     s = ((double)kernelT.dwHighDateTime * ((double)_UI32_MAX + 1.0)
201         + (double)kernelT.dwLowDateTime)*100.0 / t.NANOSECS_PER_SEC();
202     u = ((double)userT.dwHighDateTime * ((double)_UI32_MAX + 1.0)
203         + (double)userT.dwLowDateTime)*100.0 / t.NANOSECS_PER_SEC();
204   } else {
205     u = 0;
206     s = 0;
207   }
208 }
209
210 #endif /* !defined(HAVE_GET_CURRENT_DEFINITION) */
211 #endif /* defined(i386_unknown_nt4_0) */
212
213
214 \f
215
216
217 #if defined(sparc_sun_solaris2_4) || defined(i386_unknown_solaris2_5)
218 #if !defined(HAVE_GET_CURRENT_DEFINITION)
219 #define HAVE_GET_CURRENT_DEFINITION
220
221 #include <sys/time.h>
222 #include <sys/times.h>
223
224 void
225 timer::get_current(double& u, double& s, double& w) {
226     timer t;
227     u = gethrvtime() / t.NANOSECS_PER_SEC();
228
229     struct tms tb;
230     if (times(&tb) == -1) {
231       P_perror("times");
232       P_abort();
233     }
234     s = tb.tms_stime / t.CYCLES_PER_SEC();
235
236     w = gethrtime() / t.NANOSECS_PER_SEC();
237 }
238
239 #endif /* !defined(HAVE_GET_CURRENT_DEFINITION) */
240 #endif /* defined(sparc_sun_solaris2_4) */
241
242
243 \f
244
245
246 #if !defined(HAVE_GET_CURRENT_DEFINITION)
247 #define HAVE_GET_CURRENT_DEFINITION
248
249 #include <sys/types.h>
250 #include <sys/time.h>
251 #include <sys/times.h>
252
253 #if !defined(rs6000_ibm_aix4_1) && !defined(i386_unknown_linux2_0)
254    // aix 4.1 and linux don't need or agree with the following declaration:
255 extern "C" gettimeofday(struct timeval *tp, struct timezone *tzp);
256 #endif
257
258 void
259 timer::get_current(double& u, double& s, double& w) {
260     struct tms     tb;
261     struct timeval tv;
262     if (times(&tb) == -1) {
263         perror("times");
264         abort();
265     }
266     if (gettimeofday(&tv, 0) == -1) {
267       P_perror("gettimeofday");
268       P_abort();
269     }
270
271     timer t;
272     u = tb.tms_utime / t.CYCLES_PER_SEC();
273     s = tb.tms_stime / t.CYCLES_PER_SEC();
274     w = (tv.tv_sec + tv.tv_usec/t.MICROSECS_PER_SEC());
275 }
276 #endif /* !defined(HAVE_GET_CURRENT_DEFINITION) */