ntdll: Fix tick count calculation on Mac.
Inspired by a patch by Andrew Eikum. macOS's mach_absolute_time() stops counting when the computer goes to sleep/suspend/hibernate/etc. However, Windows's GetTickCount() does not stop counting. mach_continuous_time() matches Windows's behavior. BSD's CLOCK_MONOTONIC already counts asleep time. Unfortunately, there is no clock source on Linux which does exactly what we want. CLOCK_MONOTONIC_RAW is unaffected by NTP adjustment, but like mach_absolute_time() doesn't keep ticking when the computer is asleep. CLOCK_BOOTTIME does keep ticking, but it is affected by NTP adjustments. CLOCK_MONOTONIC has both problems. What's needed is a CLOCK_BOOTTIME_RAW, which would not be slewed by adjtimex(2) and would count time spent asleep. To avoid issues with skew and performance, this patch falls back to mach_absolute_time() on macOS if mach_continuous_time() is unavailable. Note that mach_continuous_time() was introduced in macOS 10.12, meaning that if the minimum version required is less than that, it will be linked weakly. Therefore we must check that it is nonnull before attempting to call it. Signed-off-by: Chip Davis <cdavis@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c6bafaa6d9
commit
289d456dd6
|
@ -17696,6 +17696,7 @@ for ac_func in \
|
|||
getopt_long_only \
|
||||
kqueue \
|
||||
lstat \
|
||||
mach_continuous_time \
|
||||
pipe2 \
|
||||
poll \
|
||||
port_create \
|
||||
|
|
|
@ -2171,6 +2171,7 @@ AC_CHECK_FUNCS(\
|
|||
getopt_long_only \
|
||||
kqueue \
|
||||
lstat \
|
||||
mach_continuous_time \
|
||||
pipe2 \
|
||||
poll \
|
||||
port_create \
|
||||
|
|
|
@ -78,6 +78,10 @@ static inline ULONGLONG monotonic_counter(void)
|
|||
static mach_timebase_info_data_t timebase;
|
||||
|
||||
if (!timebase.denom) mach_timebase_info( &timebase );
|
||||
#ifdef HAVE_MACH_CONTINUOUS_TIME
|
||||
if (&mach_continuous_time != NULL)
|
||||
return mach_continuous_time() * timebase.numer / timebase.denom / 100;
|
||||
#endif
|
||||
return mach_absolute_time() * timebase.numer / timebase.denom / 100;
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
struct timespec ts;
|
||||
|
|
|
@ -111,6 +111,10 @@ static inline ULONGLONG monotonic_counter(void)
|
|||
static mach_timebase_info_data_t timebase;
|
||||
|
||||
if (!timebase.denom) mach_timebase_info( &timebase );
|
||||
#ifdef HAVE_MACH_CONTINUOUS_TIME
|
||||
if (&mach_continuous_time != NULL)
|
||||
return mach_continuous_time() * timebase.numer / timebase.denom / 100;
|
||||
#endif
|
||||
return mach_absolute_time() * timebase.numer / timebase.denom / 100;
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
struct timespec ts;
|
||||
|
|
|
@ -554,6 +554,9 @@
|
|||
/* Define to 1 if you have the <machine/sysarch.h> header file. */
|
||||
#undef HAVE_MACHINE_SYSARCH_H
|
||||
|
||||
/* Define to 1 if you have the `mach_continuous_time' function. */
|
||||
#undef HAVE_MACH_CONTINUOUS_TIME
|
||||
|
||||
/* Define to 1 if you have the <mach/machine.h> header file. */
|
||||
#undef HAVE_MACH_MACHINE_H
|
||||
|
||||
|
|
|
@ -529,6 +529,10 @@ unsigned int get_tick_count(void)
|
|||
static mach_timebase_info_data_t timebase;
|
||||
|
||||
if (!timebase.denom) mach_timebase_info( &timebase );
|
||||
#ifdef HAVE_MACH_CONTINUOUS_TIME
|
||||
if (&mach_continuous_time != NULL)
|
||||
return mach_continuous_time() * timebase.numer / timebase.denom / 1000000;
|
||||
#endif
|
||||
return mach_absolute_time() * timebase.numer / timebase.denom / 1000000;
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
struct timespec ts;
|
||||
|
|
Loading…
Reference in New Issue