Mercurial > mplayer.hg
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 |