]> git.sesse.net Git - vlc/blobdiff - src/misc/mtime.c
mtime: Minimize imprecision and prevent overflow on darwin.
[vlc] / src / misc / mtime.c
index 940505de0ca39f9fb5d9c5253e75c0fad9092be8..115dbe9ffc6cce42a2ef2e9a5dde211a035b9fd1 100644 (file)
@@ -214,13 +214,18 @@ mtime_t mdate( void )
 #elif defined( USE_APPLE_MACH )
     pthread_once(&mtime_timebase_info_once, mtime_init_timebase);
     uint64_t date = mach_absolute_time();
+    mach_timebase_info_data_t tb = mtime_timebase_info;
 
-    /* Convert to nanoseconds */
-    date *= mtime_timebase_info.numer;
-    date /= mtime_timebase_info.denom;
+    /* tb.denom is uint32_t, switch to 64 bits to prevent overflow. */
+    uint64_t denom = tb.denom;
 
-    /* Convert to microseconds */
-    res = date / 1000;
+    /* Switch to microsecs */
+    denom *= 1000LL;
+
+    /* Split the division to prevent overflow */
+    lldiv_t d = lldiv (tb.numer, denom);
+
+    res = (d.quot * date) + ((d.rem * date) / denom);
 
 #elif defined( WIN32 ) || defined( UNDER_CE )
     /* We don't need the real date, just the value of a high precision timer */
@@ -235,12 +240,6 @@ mtime_t mdate( void )
 
     res = (d.quot * 1000000) + ((d.rem * 1000000) / freq.QuadPart);
 
-#elif defined(USE_APPLE_MACH)
-    /* The version that should be used, if it was cancelable */
-    pthread_once(&mtime_timebase_info_once, mtime_init_timebase);
-    uint64_t mach_time = date * 1000 * mtime_timebase_info.denom / mtime_timebase_info.numer;
-    mach_wait_until(mach_time);
-
 #else
     struct timeval tv_date;