[PATCH] ntdll: Fix tick count calculation on Mac.
Huw Davies
huw at codeweavers.com
Tue Nov 26 03:07:10 CST 2019
On Mon, Nov 25, 2019 at 05:45:25PM -0600, Chip Davis wrote:
> 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 at codeweavers.com>
> ---
> configure.ac | 1 +
> dlls/ntdll/time.c | 4 ++++
> 2 files changed, 5 insertions(+)
>
> diff --git a/configure.ac b/configure.ac
> index 754dbe8b36e..2a049909a65 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2206,6 +2206,7 @@ AC_CHECK_FUNCS(\
> getopt_long_only \
> kqueue \
> lstat \
> + mach_continuous_time \
> pipe2 \
> poll \
> port_create \
> diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c
> index 91e5887b879..4e3d5583c7b 100644
> --- a/dlls/ntdll/time.c
> +++ b/dlls/ntdll/time.c
> @@ -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;
I should have mentioned this before, but note that for performance reasons there's
a second implementation of monotonic_counter() in kernel32. Additionally there's
get_tick_count() in the wineserver.
Did you check that all of the other calls serviced by
monotonic_counter() (e.g. NtQueryPerformanceCounter() and
RtlQueryUnbiasedInterruptTime()) continue to count during a suspend?
Huw.
More information about the wine-devel
mailing list