aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ode-0.9/ode/src/timer.cpp
diff options
context:
space:
mode:
authordan miller2007-10-19 05:24:38 +0000
committerdan miller2007-10-19 05:24:38 +0000
commitf205de7847da7ae1c10212d82e7042d0100b4ce0 (patch)
tree9acc9608a6880502aaeda43af52c33e278e95b9c /libraries/ode-0.9/ode/src/timer.cpp
parenttrying to fix my screwup part deux (diff)
downloadopensim-SC_OLD-f205de7847da7ae1c10212d82e7042d0100b4ce0.zip
opensim-SC_OLD-f205de7847da7ae1c10212d82e7042d0100b4ce0.tar.gz
opensim-SC_OLD-f205de7847da7ae1c10212d82e7042d0100b4ce0.tar.bz2
opensim-SC_OLD-f205de7847da7ae1c10212d82e7042d0100b4ce0.tar.xz
from the start... checking in ode-0.9
Diffstat (limited to 'libraries/ode-0.9/ode/src/timer.cpp')
-rw-r--r--libraries/ode-0.9/ode/src/timer.cpp421
1 files changed, 421 insertions, 0 deletions
diff --git a/libraries/ode-0.9/ode/src/timer.cpp b/libraries/ode-0.9/ode/src/timer.cpp
new file mode 100644
index 0000000..f754bf1
--- /dev/null
+++ b/libraries/ode-0.9/ode/src/timer.cpp
@@ -0,0 +1,421 @@
1/*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
22
23/*
24
25TODO
26----
27
28* gettimeofday() and the pentium time stamp counter return the real time,
29 not the process time. fix this somehow!
30
31*/
32
33#include <ode/common.h>
34#include <ode/timer.h>
35
36// misc defines
37#define ALLOCA dALLOCA16
38
39//****************************************************************************
40// implementation for windows based on the multimedia performance counter.
41
42#ifdef WIN32
43
44#include "windows.h"
45
46static inline void getClockCount (unsigned long cc[2])
47{
48 LARGE_INTEGER a;
49 QueryPerformanceCounter (&a);
50 cc[0] = a.LowPart;
51 cc[1] = a.HighPart;
52}
53
54
55static inline void serialize()
56{
57}
58
59
60static inline double loadClockCount (unsigned long cc[2])
61{
62 LARGE_INTEGER a;
63 a.LowPart = cc[0];
64 a.HighPart = cc[1];
65 return double(a.QuadPart);
66}
67
68
69double dTimerResolution()
70{
71 return 1.0/dTimerTicksPerSecond();
72}
73
74
75double dTimerTicksPerSecond()
76{
77 static int query=0;
78 static double hz=0.0;
79 if (!query) {
80 LARGE_INTEGER a;
81 QueryPerformanceFrequency (&a);
82 hz = double(a.QuadPart);
83 query = 1;
84 }
85 return hz;
86}
87
88#endif
89
90//****************************************************************************
91// implementation based on the pentium time stamp counter. the timer functions
92// can be serializing or non-serializing. serializing will ensure that all
93// instructions have executed and data has been written back before the cpu
94// time stamp counter is read. the CPUID instruction is used to serialize.
95
96#if defined(PENTIUM) && !defined(WIN32)
97
98// we need to know the clock rate so that the timing function can report
99// accurate times. this number only needs to be set accurately if we're
100// doing performance tests and care about real-world time numbers - otherwise,
101// just ignore this. i have not worked out how to determine this number
102// automatically yet.
103
104#define PENTIUM_HZ (500e6)
105
106static inline void getClockCount (unsigned long cc[2])
107{
108#ifndef X86_64_SYSTEM
109 asm volatile (
110 "rdtsc\n"
111 "movl %%eax,(%%esi)\n"
112 "movl %%edx,4(%%esi)\n"
113 : : "S" (cc) : "%eax","%edx","cc","memory");
114#else
115 asm volatile (
116 "rdtsc\n"
117 "movl %%eax,(%%rsi)\n"
118 "movl %%edx,4(%%rsi)\n"
119 : : "S" (cc) : "%eax","%edx","cc","memory");
120#endif
121}
122
123
124static inline void serialize()
125{
126#ifndef X86_64_SYSTEM
127 asm volatile (
128 "mov $0,%%eax\n"
129 "push %%ebx\n"
130 "cpuid\n"
131 "pop %%ebx\n"
132 : : : "%eax","%ecx","%edx","cc","memory");
133#else
134 asm volatile (
135 "mov $0,%%rax\n"
136 "push %%rbx\n"
137 "cpuid\n"
138 "pop %%rbx\n"
139 : : : "%rax","%rcx","%rdx","cc","memory");
140#endif
141}
142
143
144static inline double loadClockCount (unsigned long a[2])
145{
146 double ret;
147#ifndef X86_64_SYSTEM
148 asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
149 "cc","memory");
150#else
151 asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
152 "cc","memory");
153#endif
154 return ret;
155}
156
157
158double dTimerResolution()
159{
160 return 1.0/PENTIUM_HZ;
161}
162
163
164double dTimerTicksPerSecond()
165{
166 return PENTIUM_HZ;
167}
168
169#endif
170
171//****************************************************************************
172// otherwise, do the implementation based on gettimeofday().
173
174#if !defined(PENTIUM) && !defined(WIN32)
175
176#ifndef macintosh
177
178#include <sys/time.h>
179#include <unistd.h>
180
181
182static inline void getClockCount (unsigned long cc[2])
183{
184 struct timeval tv;
185 gettimeofday (&tv,0);
186 cc[0] = tv.tv_usec;
187 cc[1] = tv.tv_sec;
188}
189
190#else // macintosh
191
192#include <MacTypes.h>
193#include <Timer.h>
194
195static inline void getClockCount (unsigned long cc[2])
196{
197 UnsignedWide ms;
198 Microseconds (&ms);
199 cc[1] = ms.lo / 1000000;
200 cc[0] = ms.lo - ( cc[1] * 1000000 );
201}
202
203#endif
204
205
206static inline void serialize()
207{
208}
209
210
211static inline double loadClockCount (unsigned long a[2])
212{
213 return a[1]*1.0e6 + a[0];
214}
215
216
217double dTimerResolution()
218{
219 unsigned long cc1[2],cc2[2];
220 getClockCount (cc1);
221 do {
222 getClockCount (cc2);
223 }
224 while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
225 do {
226 getClockCount (cc1);
227 }
228 while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
229 double t1 = loadClockCount (cc1);
230 double t2 = loadClockCount (cc2);
231 return (t1-t2) / dTimerTicksPerSecond();
232}
233
234
235double dTimerTicksPerSecond()
236{
237 return 1000000;
238}
239
240#endif
241
242//****************************************************************************
243// stop watches
244
245void dStopwatchReset (dStopwatch *s)
246{
247 s->time = 0;
248 s->cc[0] = 0;
249 s->cc[1] = 0;
250}
251
252
253void dStopwatchStart (dStopwatch *s)
254{
255 serialize();
256 getClockCount (s->cc);
257}
258
259
260void dStopwatchStop (dStopwatch *s)
261{
262 unsigned long cc[2];
263 serialize();
264 getClockCount (cc);
265 double t1 = loadClockCount (s->cc);
266 double t2 = loadClockCount (cc);
267 s->time += t2-t1;
268}
269
270
271double dStopwatchTime (dStopwatch *s)
272{
273 return s->time / dTimerTicksPerSecond();
274}
275
276//****************************************************************************
277// code timers
278
279// maximum number of events to record
280#define MAXNUM 100
281
282static int num = 0; // number of entries used in event array
283static struct {
284 unsigned long cc[2]; // clock counts
285 double total_t; // total clocks used in this slot.
286 double total_p; // total percentage points used in this slot.
287 int count; // number of times this slot has been updated.
288 char *description; // pointer to static string
289} event[MAXNUM];
290
291
292// make sure all slot totals and counts reset to 0 at start
293
294static void initSlots()
295{
296 static int initialized=0;
297 if (!initialized) {
298 for (int i=0; i<MAXNUM; i++) {
299 event[i].count = 0;
300 event[i].total_t = 0;
301 event[i].total_p = 0;
302 }
303 initialized = 1;
304 }
305}
306
307
308void dTimerStart (const char *description)
309{
310 initSlots();
311 event[0].description = const_cast<char*> (description);
312 num = 1;
313 serialize();
314 getClockCount (event[0].cc);
315}
316
317
318void dTimerNow (const char *description)
319{
320 if (num < MAXNUM) {
321 // do not serialize
322 getClockCount (event[num].cc);
323 event[num].description = const_cast<char*> (description);
324 num++;
325 }
326}
327
328
329void dTimerEnd()
330{
331 if (num < MAXNUM) {
332 serialize();
333 getClockCount (event[num].cc);
334 event[num].description = "TOTAL";
335 num++;
336 }
337}
338
339//****************************************************************************
340// print report
341
342static void fprintDoubleWithPrefix (FILE *f, double a, char *fmt)
343{
344 if (a >= 0.999999) {
345 fprintf (f,fmt,a);
346 return;
347 }
348 a *= 1000.0;
349 if (a >= 0.999999) {
350 fprintf (f,fmt,a);
351 fprintf (f,"m");
352 return;
353 }
354 a *= 1000.0;
355 if (a >= 0.999999) {
356 fprintf (f,fmt,a);
357 fprintf (f,"u");
358 return;
359 }
360 a *= 1000.0;
361 fprintf (f,fmt,a);
362 fprintf (f,"n");
363}
364
365
366void dTimerReport (FILE *fout, int average)
367{
368 int i;
369 size_t maxl;
370 double ccunit = 1.0/dTimerTicksPerSecond();
371 fprintf (fout,"\nTimer Report (");
372 fprintDoubleWithPrefix (fout,ccunit,"%.2f ");
373 fprintf (fout,"s resolution)\n------------\n");
374 if (num < 1) return;
375
376 // get maximum description length
377 maxl = 0;
378 for (i=0; i<num; i++) {
379 size_t l = strlen (event[i].description);
380 if (l > maxl) maxl = l;
381 }
382
383 // calculate total time
384 double t1 = loadClockCount (event[0].cc);
385 double t2 = loadClockCount (event[num-1].cc);
386 double total = t2 - t1;
387 if (total <= 0) total = 1;
388
389 // compute time difference for all slots except the last one. update totals
390 double *times = (double*) ALLOCA (num * sizeof(double));
391 for (i=0; i < (num-1); i++) {
392 double t1 = loadClockCount (event[i].cc);
393 double t2 = loadClockCount (event[i+1].cc);
394 times[i] = t2 - t1;
395 event[i].count++;
396 event[i].total_t += times[i];
397 event[i].total_p += times[i]/total * 100.0;
398 }
399
400 // print report (with optional averages)
401 for (i=0; i<num; i++) {
402 double t,p;
403 if (i < (num-1)) {
404 t = times[i];
405 p = t/total * 100.0;
406 }
407 else {
408 t = total;
409 p = 100.0;
410 }
411 fprintf (fout,"%-*s %7.2fms %6.2f%%",maxl,event[i].description,
412 t*ccunit * 1000.0, p);
413 if (average && i < (num-1)) {
414 fprintf (fout," (avg %7.2fms %6.2f%%)",
415 (event[i].total_t / event[i].count)*ccunit * 1000.0,
416 event[i].total_p / event[i].count);
417 }
418 fprintf (fout,"\n");
419 }
420 fprintf (fout,"\n");
421}