comparison osdep/timer-darwin.c @ 10148:139b44930abc

Precise timer for Darwin (it's more accurate than timer-macosx.c)
author alex
date Wed, 21 May 2003 21:18:29 +0000
parents
children 56b59bcdee80
comparison
equal deleted inserted replaced
10147:f2725d6717bd 10148:139b44930abc
1 /*
2 * Precise timer routines using Mach kernel-space timing.
3 *
4 * It reports to be accurate by ~20us, unless the task is preempted.
5 *
6 * (C) 2003 Dan Christiansen
7 *
8 * Released into the public domain.
9 */
10
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14
15 #include <mach/mach_time.h>
16 #include <mach/mach.h>
17 #include <mach/clock.h>
18
19 #include "../config.h"
20 #include "../mp_msg.h"
21 #include "timer.h"
22
23 /* Utility macros for mach_timespec_t - it uses nsec rather than usec */
24
25 /* returns time from t1 to t2, in seconds (as float) */
26 #define diff_time(t1, t2) \
27 (((t2).tv_sec - (t1).tv_sec) + \
28 ((t2).tv_nsec - (t1).tv_nsec) / 1e9)
29
30 /* returns time from t1 to t2, in microseconds (as integer) */
31 #define udiff_time(t1, t2) \
32 (((t2).tv_sec - (t1).tv_sec) * 1000000 + \
33 ((t2).tv_nsec - (t1).tv_nsec) / 1000)
34
35 /* returns float value of t, in seconds */
36 #define time_to_float(t) \
37 ((t).tv_sec + (t).tv_nsec / 1e9)
38
39 /* returns integer value of t, in microseconds */
40 #define time_to_usec(t) \
41 ((t).tv_sec * 1000000 + (t).tv_nsec / 1000)
42
43 /* sets ts to the value of f, in seconds */
44 #define float_to_time(f, ts) \
45 do { \
46 (ts).tv_sec = (unsigned int)(f); \
47 (ts).tv_nsec = (int)(((f) - (ts).sec) / 1000000000.0); \
48 } while (0)
49
50 /* sets ts to the value of i, in microseconds */
51 #define usec_to_time(i, ts) \
52 do { \
53 (ts).tv_sec = (i) / 1000000; \
54 (ts).tv_nsec = (i) % 1000000 * 1000; \
55 } while (0)
56
57 #define time_uadd(i, ts) \
58 do { \
59 (ts).tv_sec += (i) / 1000000; \
60 (ts).tv_nsec += (i) % 1000000 * 1000; \
61 while ((ts).tv_nsec > 1000000000) { \
62 (ts).tv_sec++; \
63 (ts).tv_nsec -= 1000000000; \
64 } \
65 } while (0)
66
67
68 /* global variables */
69 static double relative_time, startup_time;
70 static double timebase_ratio;
71 static mach_port_t clock_port;
72
73
74 /* sleep usec_delay microseconds */
75 int usec_sleep(int usec_delay)
76 {
77 mach_timespec_t start_time, end_time;
78
79 clock_get_time(clock_port, &start_time);
80
81 end_time = start_time;
82 time_uadd(usec_delay, end_time);
83
84 clock_sleep(clock_port, TIME_ABSOLUTE, end_time, NULL);
85
86 clock_get_time(clock_port, &end_time);
87
88 return usec_delay - udiff_time(start_time, end_time);
89 }
90
91
92 /* Returns current time in microseconds */
93 unsigned int GetTimer()
94 {
95 return (unsigned int)((mach_absolute_time() * timebase_ratio - startup_time)
96 * 1e6);
97 }
98
99 /* Returns current time in milliseconds */
100 unsigned int GetTimerMS()
101 {
102 return (unsigned int)(GetTimer() / 1000);
103 }
104
105 /* Returns time spent between now and last call in seconds */
106 float GetRelativeTime()
107 {
108 double last_time;
109
110 if (!startup_time)
111 InitTimer();
112
113 last_time = relative_time;
114
115 relative_time = mach_absolute_time() * timebase_ratio;
116
117 return (float)(relative_time-last_time);
118 }
119
120 /* Initialize timer, must be called at least once at start */
121 void InitTimer()
122 {
123 struct mach_timebase_info timebase;
124
125 /* get base for mach_absolute_time() */
126 mach_timebase_info(&timebase);
127 timebase_ratio = (double)timebase.numer / (double)timebase.denom
128 * (double)1e-9;
129
130 /* get mach port for the clock */
131 host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port);
132
133 /* prepare for GetRelativeTime() */
134 relative_time = startup_time =
135 (double)(mach_absolute_time() * timebase_ratio);
136 }
137
138
139 #if 0
140 int main()
141 {
142 const long delay = 0.001*1e6;
143 const unsigned short attempts = 100;
144 int i,j[attempts],t[attempts],r[attempts];
145 double sqtotal;
146 double total;
147
148 InitTimer();
149
150 for (i = 0; i < attempts; i++) {
151 t[i] = j[i] = GetTimer();
152 r[i] = usec_sleep(delay);
153 j[i] = delay-(GetTimer() - j[i]);
154 fflush(stdout);
155 }
156
157 for (i = 0; i < attempts; i++) {
158 sqtotal += j[i]*j[i];
159 total += j[i];
160 printf("%2i=%0.06g \tr: %9i\tj: %9i\tr - j:%9i\n",
161 i, t[i] / 1e6, r[i], j[i], r[i] - j[i]);
162 }
163
164 printf("attempts: %i\ttotal=%g\trms=%g\tavg=%g\n", attempts, total,
165 sqrt(sqtotal/attempts),total/attempts);
166
167 return 0;
168 }
169 #endif