From 2ce15e79696fb684ecbe5f0c93b250e2f3d8b196 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 21 May 2003 21:18:29 +0000 Subject: Precise timer for Darwin (it's more accurate than timer-macosx.c) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10149 b3059339-0415-0410-9bf9-f77b7e298cf2 --- osdep/Makefile | 4 +- osdep/timer-darwin.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 osdep/timer-darwin.c (limited to 'osdep') diff --git a/osdep/Makefile b/osdep/Makefile index 808f2e3e7b..cc3ea85487 100644 --- a/osdep/Makefile +++ b/osdep/Makefile @@ -13,8 +13,8 @@ endif getch = getch2.c timer = timer-lx.c -ifeq ($(MACOSX),yes) -timer = timer-macosx.c +ifeq ($(TARGET_OS),Darwin) +timer = timer-darwin.c endif ifeq ($(TARGET_CYGWIN),yes) timer = timer-win2.c diff --git a/osdep/timer-darwin.c b/osdep/timer-darwin.c new file mode 100644 index 0000000000..a5b3516699 --- /dev/null +++ b/osdep/timer-darwin.c @@ -0,0 +1,169 @@ +/* + * Precise timer routines using Mach kernel-space timing. + * + * It reports to be accurate by ~20us, unless the task is preempted. + * + * (C) 2003 Dan Christiansen + * + * Released into the public domain. + */ + +#include +#include +#include + +#include +#include +#include + +#include "../config.h" +#include "../mp_msg.h" +#include "timer.h" + +/* Utility macros for mach_timespec_t - it uses nsec rather than usec */ + +/* returns time from t1 to t2, in seconds (as float) */ +#define diff_time(t1, t2) \ + (((t2).tv_sec - (t1).tv_sec) + \ + ((t2).tv_nsec - (t1).tv_nsec) / 1e9) + +/* returns time from t1 to t2, in microseconds (as integer) */ +#define udiff_time(t1, t2) \ + (((t2).tv_sec - (t1).tv_sec) * 1000000 + \ + ((t2).tv_nsec - (t1).tv_nsec) / 1000) + +/* returns float value of t, in seconds */ +#define time_to_float(t) \ + ((t).tv_sec + (t).tv_nsec / 1e9) + +/* returns integer value of t, in microseconds */ +#define time_to_usec(t) \ + ((t).tv_sec * 1000000 + (t).tv_nsec / 1000) + +/* sets ts to the value of f, in seconds */ +#define float_to_time(f, ts) \ + do { \ + (ts).tv_sec = (unsigned int)(f); \ + (ts).tv_nsec = (int)(((f) - (ts).sec) / 1000000000.0); \ + } while (0) + +/* sets ts to the value of i, in microseconds */ +#define usec_to_time(i, ts) \ + do { \ + (ts).tv_sec = (i) / 1000000; \ + (ts).tv_nsec = (i) % 1000000 * 1000; \ + } while (0) + +#define time_uadd(i, ts) \ + do { \ + (ts).tv_sec += (i) / 1000000; \ + (ts).tv_nsec += (i) % 1000000 * 1000; \ + while ((ts).tv_nsec > 1000000000) { \ + (ts).tv_sec++; \ + (ts).tv_nsec -= 1000000000; \ + } \ + } while (0) + + +/* global variables */ +static double relative_time, startup_time; +static double timebase_ratio; +static mach_port_t clock_port; + + +/* sleep usec_delay microseconds */ +int usec_sleep(int usec_delay) +{ + mach_timespec_t start_time, end_time; + + clock_get_time(clock_port, &start_time); + + end_time = start_time; + time_uadd(usec_delay, end_time); + + clock_sleep(clock_port, TIME_ABSOLUTE, end_time, NULL); + + clock_get_time(clock_port, &end_time); + + return usec_delay - udiff_time(start_time, end_time); +} + + +/* Returns current time in microseconds */ +unsigned int GetTimer() +{ + return (unsigned int)((mach_absolute_time() * timebase_ratio - startup_time) + * 1e6); +} + +/* Returns current time in milliseconds */ +unsigned int GetTimerMS() +{ + return (unsigned int)(GetTimer() / 1000); +} + +/* Returns time spent between now and last call in seconds */ +float GetRelativeTime() +{ + double last_time; + + if (!startup_time) + InitTimer(); + + last_time = relative_time; + + relative_time = mach_absolute_time() * timebase_ratio; + + return (float)(relative_time-last_time); +} + +/* Initialize timer, must be called at least once at start */ +void InitTimer() +{ + struct mach_timebase_info timebase; + + /* get base for mach_absolute_time() */ + mach_timebase_info(&timebase); + timebase_ratio = (double)timebase.numer / (double)timebase.denom + * (double)1e-9; + + /* get mach port for the clock */ + host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port); + + /* prepare for GetRelativeTime() */ + relative_time = startup_time = + (double)(mach_absolute_time() * timebase_ratio); +} + + +#if 0 +int main() +{ + const long delay = 0.001*1e6; + const unsigned short attempts = 100; + int i,j[attempts],t[attempts],r[attempts]; + double sqtotal; + double total; + + InitTimer(); + + for (i = 0; i < attempts; i++) { + t[i] = j[i] = GetTimer(); + r[i] = usec_sleep(delay); + j[i] = delay-(GetTimer() - j[i]); + fflush(stdout); + } + + for (i = 0; i < attempts; i++) { + sqtotal += j[i]*j[i]; + total += j[i]; + printf("%2i=%0.06g \tr: %9i\tj: %9i\tr - j:%9i\n", + i, t[i] / 1e6, r[i], j[i], r[i] - j[i]); + } + + printf("attempts: %i\ttotal=%g\trms=%g\tavg=%g\n", attempts, total, + sqrt(sqtotal/attempts),total/attempts); + + return 0; +} +#endif -- cgit v1.2.3