Mercurial > mplayer.hg
comparison osdep/timer-darwin.c @ 12954:f9755d9c479a
Native darwin timer update.
Patch by Dan Christiansen <danchr@daimi.au.dk>
author | wight |
---|---|
date | Wed, 04 Aug 2004 15:48:43 +0000 |
parents | d12758db79aa |
children | 3029f9e4f2ac |
comparison
equal
deleted
inserted
replaced
12953:27e983508347 | 12954:f9755d9c479a |
---|---|
1 /* | 1 /* |
2 * Precise timer routines using Mach kernel-space timing. | 2 * Precise timer routines using Mach timing |
3 * | 3 * |
4 * It reports to be accurate by ~20us, unless the task is preempted. | 4 * Copyright (c) 2003-2004, Dan Villiom Podlaski Christiansen |
5 * | 5 * |
6 * (C) 2003 Dan Christiansen | 6 * Permission is hereby granted, free of charge, to any person |
7 * obtaining a copy of this software and associated documentation | |
8 * files (the "Software"), to deal in the Software without | |
9 * restriction, including without limitation the rights to use, copy, | |
10 * modify, merge, publish, distribute, sublicense, and/or sell copies | |
11 * of the Software, and to permit persons to whom the Software is | |
12 * furnished to do so, subject to the following conditions: | |
7 * | 13 * |
8 * Released into the public domain. | 14 * The above copyright notice and this permission notice shall be |
15 * included in all copies or substantial portions of the Software. | |
9 */ | 16 */ |
10 | 17 |
11 #include <unistd.h> | 18 #include <unistd.h> |
12 #include <stdlib.h> | 19 #include <stdlib.h> |
13 #include <stdio.h> | 20 #include <time.h> |
14 | 21 #include <math.h> |
22 #include <sys/time.h> | |
15 #include <mach/mach_time.h> | 23 #include <mach/mach_time.h> |
16 #include <mach/mach.h> | |
17 #include <mach/clock.h> | |
18 | 24 |
19 #include "../config.h" | 25 #include "../config.h" |
20 #include "../mp_msg.h" | 26 #include "../mp_msg.h" |
21 #include "timer.h" | 27 #include "timer.h" |
22 | 28 |
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 */ | 29 /* global variables */ |
69 static double relative_time, startup_time; | 30 static double relative_time, startup_time; |
70 static double timebase_ratio; | 31 static double timebase_ratio; |
71 static mach_port_t clock_port; | |
72 | 32 |
33 const char *timer_name = "Darwin accurate"; | |
73 | 34 |
74 /* sleep usec_delay microseconds */ | 35 /* the core sleep function, uses floats and is used in MPlayer G2 */ |
36 float sleep_accurate(float time_frame) | |
37 { | |
38 uint64_t deadline = time_frame / timebase_ratio + mach_absolute_time(); | |
39 | |
40 mach_wait_until(deadline); | |
41 | |
42 return (mach_absolute_time() - deadline) * timebase_ratio; | |
43 } | |
44 | |
45 /* wrapper for MPlayer G1 */ | |
75 int usec_sleep(int usec_delay) | 46 int usec_sleep(int usec_delay) |
76 { | 47 { |
77 #if 0 | 48 return sleep_accurate(usec_delay / 1e6) * 1e6; |
78 mach_timespec_t start_time, end_time; | |
79 | |
80 clock_get_time(clock_port, &start_time); | |
81 | |
82 end_time = start_time; | |
83 time_uadd(usec_delay, end_time); | |
84 | |
85 clock_sleep(clock_port, TIME_ABSOLUTE, end_time, NULL); | |
86 | |
87 clock_get_time(clock_port, &end_time); | |
88 | |
89 return usec_delay - udiff_time(start_time, end_time); | |
90 #else | |
91 usleep(usec_delay); | |
92 #endif | |
93 } | 49 } |
94 | 50 |
95 | 51 |
96 /* Returns current time in microseconds */ | 52 /* current time in microseconds */ |
97 unsigned int GetTimer() | 53 unsigned int GetTimer() |
98 { | 54 { |
99 return (unsigned int)((mach_absolute_time() * timebase_ratio - startup_time) | 55 return (unsigned int)((mach_absolute_time() * timebase_ratio - startup_time) |
100 * 1e6); | 56 * 1e6); |
101 } | 57 } |
102 | 58 |
103 /* Returns current time in milliseconds */ | 59 /* current time in milliseconds */ |
104 unsigned int GetTimerMS() | 60 unsigned int GetTimerMS() |
105 { | 61 { |
106 return (unsigned int)(GetTimer() / 1000); | 62 return (unsigned int)(GetTimer() / 1000); |
107 } | 63 } |
108 | 64 |
109 /* Returns time spent between now and last call in seconds */ | 65 /* time spent between now and last call in seconds */ |
110 float GetRelativeTime() | 66 float GetRelativeTime() |
111 { | 67 { |
112 double last_time; | 68 double last_time = relative_time; |
113 | 69 |
114 last_time = relative_time; | 70 if (!relative_time) |
71 InitTimer(); | |
115 | 72 |
116 relative_time = mach_absolute_time() * timebase_ratio; | 73 relative_time = mach_absolute_time() * timebase_ratio; |
117 | 74 |
118 return (float)(relative_time-last_time); | 75 return (float)(relative_time-last_time); |
119 } | 76 } |
120 | 77 |
121 /* Initialize timer, must be called at least once at start */ | 78 /* initialize timer, must be called at least once at start */ |
122 void InitTimer() | 79 void InitTimer() |
123 { | 80 { |
124 struct mach_timebase_info timebase; | 81 struct mach_timebase_info timebase; |
125 | 82 |
126 /* get base for mach_absolute_time() */ | |
127 mach_timebase_info(&timebase); | 83 mach_timebase_info(&timebase); |
128 timebase_ratio = (double)timebase.numer / (double)timebase.denom | 84 timebase_ratio = (double)timebase.numer / (double)timebase.denom |
129 * (double)1e-9; | 85 * (double)1e-9; |
130 | 86 |
131 /* get mach port for the clock */ | |
132 host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port); | |
133 | |
134 /* prepare for GetRelativeTime() */ | |
135 relative_time = startup_time = | 87 relative_time = startup_time = |
136 (double)(mach_absolute_time() * timebase_ratio); | 88 (double)(mach_absolute_time() * timebase_ratio); |
137 } | 89 } |
138 | 90 |
91 #if 0 | |
92 #include <stdio.h> | |
139 | 93 |
140 #if 0 | 94 int main() { |
141 int main() | 95 int i,j, r, c = 200; |
142 { | 96 long long t = 0; |
143 const long delay = 0.001*1e6; | |
144 const unsigned short attempts = 100; | |
145 int i,j[attempts],t[attempts],r[attempts]; | |
146 double sqtotal; | |
147 double total; | |
148 | 97 |
149 InitTimer(); | 98 InitTimer(); |
150 | 99 |
151 for (i = 0; i < attempts; i++) { | 100 for (i = 0; i < c; i++) { |
152 t[i] = j[i] = GetTimer(); | 101 const int delay = rand() / (RAND_MAX / 1e5); |
153 r[i] = usec_sleep(delay); | 102 j = GetTimer(); |
154 j[i] = delay-(GetTimer() - j[i]); | 103 #if 1 |
155 fflush(stdout); | 104 r = usec_sleep(delay); |
105 #else | |
106 r = sleep_accurate(delay / 1e6) * 1e6; | |
107 #endif | |
108 j = (GetTimer() - j) - delay; | |
109 printf("sleep time:%8i %5i (%i)\n", delay, j, j - r); | |
110 t += j - r; | |
156 } | 111 } |
112 fprintf(stderr, "average error:\t%lli\n", t / c); | |
157 | 113 |
158 for (i = 0; i < attempts; i++) { | |
159 sqtotal += j[i]*j[i]; | |
160 total += j[i]; | |
161 printf("%2i=%0.06g \tr: %9i\tj: %9i\tr - j:%9i\n", | |
162 i, t[i] / 1e6, r[i], j[i], r[i] - j[i]); | |
163 } | |
164 | |
165 printf("attempts: %i\ttotal=%g\trms=%g\tavg=%g\n", attempts, total, | |
166 sqrt(sqtotal/attempts),total/attempts); | |
167 | |
168 return 0; | 114 return 0; |
169 } | 115 } |
170 #endif | 116 #endif |