Alexandre Julliard : ntdll: Use a monotonic time counter to implement NtQueryPerformanceCounter.

Alexandre Julliard julliard at winehq.org
Mon Jan 28 13:43:20 CST 2013


Module: wine
Branch: master
Commit: 25598513dc98fd27d91c0f7c4460b733155c6bf1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=25598513dc98fd27d91c0f7c4460b733155c6bf1

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Jan 25 17:27:52 2013 +0100

ntdll: Use a monotonic time counter to implement NtQueryPerformanceCounter.

---

 configure              |   64 ++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac           |    7 +++++
 dlls/ntdll/Makefile.in |    2 +-
 dlls/ntdll/time.c      |   40 +++++++++++++++++------------
 include/config.h.in    |    3 ++
 5 files changed, 98 insertions(+), 18 deletions(-)

diff --git a/configure b/configure
index ccd0283..2e7c008 100755
--- a/configure
+++ b/configure
@@ -628,6 +628,7 @@ PORCFLAGS
 LINGUAS
 ALL_TEST_RESOURCES
 LDAPLIBS
+LIBRT
 LIBPOLL
 LIBDL
 EXTRA_BINARIES
@@ -13524,6 +13525,69 @@ fi
 done
 
 
+ac_save_LIBS=$LIBS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_clock_gettime+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+  ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+                test "$ac_res" = "none required" || LIBRT="$ac_res"
+
+fi
+
+LIBS=$ac_save_LIBS
+
 LDAPLIBS=""
 
 if test "$ac_cv_header_ldap_h" = "yes" -a "$ac_cv_header_lber_h" = "yes"
diff --git a/configure.ac b/configure.ac
index dde896f..c93cd08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2080,6 +2080,13 @@ AC_CHECK_FUNCS(\
 	socketpair \
 )
 
+dnl Check for clock_gettime which may be in -lrt
+ac_save_LIBS=$LIBS
+AC_SEARCH_LIBS(clock_gettime, rt,
+               [AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define to 1 if you have the `clock_gettime' function.])
+                test "$ac_res" = "none required" || AC_SUBST(LIBRT,"$ac_res")])
+LIBS=$ac_save_LIBS
+
 dnl **** Check for OpenLDAP ***
 AC_SUBST(LDAPLIBS,"")
 if test "$ac_cv_header_ldap_h" = "yes" -a "$ac_cv_header_lber_h" = "yes"
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index cd4fe0a..c961f70 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -D_NTSYSTEM_
 MODULE    = ntdll.dll
 IMPORTLIB = ntdll
 IMPORTS   = winecrt0
-EXTRALIBS = @IOKITLIB@ @LIBPTHREAD@
+EXTRALIBS = @IOKITLIB@ @LIBRT@ @LIBPTHREAD@
 EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x7bc00000
 
 C_SRCS = \
diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c
index a8b1376..b9d3f03 100644
--- a/dlls/ntdll/time.c
+++ b/dlls/ntdll/time.c
@@ -85,8 +85,6 @@ static RTL_CRITICAL_SECTION TIME_tz_section = { &critsect_debug, -1, 0, 0, 0, 0
 /* 1601 to 1980 is 379 years plus 91 leap days */
 #define SECS_1601_TO_1980  ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY)
 #define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC)
-/* max ticks that can be represented as Unix time */
-#define TICKS_1601_TO_UNIX_MAX ((SECS_1601_TO_1970 + INT_MAX) * TICKSPERSEC)
 
 
 static const int MonthLengths[2][MONSPERYEAR] =
@@ -100,6 +98,25 @@ static inline int IsLeapYear(int Year)
 	return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
 }
 
+/* return a monotonic time counter, in Win32 ticks */
+static ULONGLONG monotonic_counter(void)
+{
+    struct timeval now;
+
+#ifdef HAVE_CLOCK_GETTIME
+    struct timespec ts;
+#ifdef CLOCK_MONOTONIC_RAW
+    if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts ))
+        return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100;
+#endif
+    if (!clock_gettime( CLOCK_MONOTONIC, &ts ))
+        return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100;
+#endif
+
+    gettimeofday( &now, 0 );
+    return now.tv_sec * (ULONGLONG)TICKSPERSEC + now.tv_usec * 10 + TICKS_1601_TO_1970 - server_start_time;
+}
+
 /******************************************************************************
  *       RtlTimeToTimeFields [NTDLL.@]
  *
@@ -450,24 +467,13 @@ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
 
 /******************************************************************************
  *  NtQueryPerformanceCounter	[NTDLL.@]
- *
- *  Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a
- *  good number of applications that crash when the returned frequency is either
- *  lower or higher than what Windows gives. Also too high counter values are
- *  reported to give problems.
  */
-NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency )
+NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER *frequency )
 {
-    LARGE_INTEGER now;
-
-    if (!Counter) return STATUS_ACCESS_VIOLATION;
+    if (!counter) return STATUS_ACCESS_VIOLATION;
 
-    /* convert a counter that increments at a rate of 10 MHz
-     * to one of 1.193182 MHz, with some care for arithmetic
-     * overflow and good accuracy (21/176 = 0.11931818) */
-    NtQuerySystemTime( &now );
-    Counter->QuadPart = ((now.QuadPart - server_start_time) * 21) / 176;
-    if (Frequency) Frequency->QuadPart = 1193182;
+    counter->QuadPart = monotonic_counter();
+    if (frequency) frequency->QuadPart = TICKSPERSEC;
     return STATUS_SUCCESS;
 }
 
diff --git a/include/config.h.in b/include/config.h.in
index 9a7d109..1a5652c 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -55,6 +55,9 @@
 /* Define to 1 if you have the `chsize' function. */
 #undef HAVE_CHSIZE
 
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
 /* Define to 1 if you have the <CL/cl.h> header file. */
 #undef HAVE_CL_CL_H
 




More information about the wine-cvs mailing list