Chip Davis : ntdll: Fix tick count calculation on Mac.

Alexandre Julliard julliard at winehq.org
Thu Nov 28 16:02:21 CST 2019


Module: wine
Branch: master
Commit: 289d456dd617c164047b6562b993a7c1a7955232
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=289d456dd617c164047b6562b993a7c1a7955232

Author: Chip Davis <cdavis at codeweavers.com>
Date:   Wed Nov 27 09:54:09 2019 -0600

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 at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 configure            | 1 +
 configure.ac         | 1 +
 dlls/kernel32/time.c | 4 ++++
 dlls/ntdll/time.c    | 4 ++++
 include/config.h.in  | 3 +++
 server/request.c     | 4 ++++
 6 files changed, 17 insertions(+)

diff --git a/configure b/configure
index dc23826900..90ff22fc7e 100755
--- a/configure
+++ b/configure
@@ -17696,6 +17696,7 @@ for ac_func in \
 	getopt_long_only \
 	kqueue \
 	lstat \
+	mach_continuous_time \
 	pipe2 \
 	poll \
 	port_create \
diff --git a/configure.ac b/configure.ac
index fe2816ca7b..7f2c3cda23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2171,6 +2171,7 @@ AC_CHECK_FUNCS(\
 	getopt_long_only \
 	kqueue \
 	lstat \
+	mach_continuous_time \
 	pipe2 \
 	poll \
 	port_create \
diff --git a/dlls/kernel32/time.c b/dlls/kernel32/time.c
index 817a830518..716230aa7a 100644
--- a/dlls/kernel32/time.c
+++ b/dlls/kernel32/time.c
@@ -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;
diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c
index 91e5887b87..4e3d5583c7 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;
diff --git a/include/config.h.in b/include/config.h.in
index 41a7cde553..63396e9250 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -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
 
diff --git a/server/request.c b/server/request.c
index d2adb08a18..5610d392cf 100644
--- a/server/request.c
+++ b/server/request.c
@@ -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;




More information about the wine-cvs mailing list