diff --git a/configure b/configure index ccd02835d8a..2e7c0085f2d 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 dde896f7013..c93cd082087 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 cd4fe0a92bf..c961f705b30 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 a8b13768450..b9d3f03c72b 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 9a7d1090d1a..1a5652c65c3 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 header file. */ #undef HAVE_CL_CL_H