ntdll: Move Nt system time functions to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-11 10:07:09 +02:00
parent 613446d018
commit a4ce2f652d
6 changed files with 127 additions and 119 deletions

View File

@ -38,9 +38,6 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef __APPLE__
# include <mach/mach_time.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
@ -103,33 +100,6 @@ static inline BOOL IsLeapYear(int Year)
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
}
/* return a monotonic time counter, in Win32 ticks */
static inline ULONGLONG monotonic_counter(void)
{
struct timeval now;
#ifdef __APPLE__
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;
#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.@]
@ -471,38 +441,7 @@ void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS
*/
NTSTATUS WINAPI NtQuerySystemTime( LARGE_INTEGER *time )
{
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */
if (clock_id == CLOCK_MONOTONIC)
{
#ifdef CLOCK_REALTIME_COARSE
struct timespec res;
/* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */
if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000)
clock_id = CLOCK_REALTIME_COARSE;
else
#endif /* CLOCK_REALTIME_COARSE */
clock_id = CLOCK_REALTIME;
}
if (!clock_gettime( clock_id, &ts ))
{
time->QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
time->QuadPart += (ts.tv_nsec + 50) / 100;
}
else
#endif /* HAVE_CLOCK_GETTIME */
{
struct timeval now;
gettimeofday( &now, 0 );
time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
time->QuadPart += now.tv_usec * 10;
}
return STATUS_SUCCESS;
return unix_funcs->NtQuerySystemTime( time );
}
/***********************************************************************
@ -543,18 +482,18 @@ LONGLONG WINAPI RtlGetSystemTimePrecise( void )
*/
NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER *frequency )
{
NTSTATUS status;
__TRY
{
counter->QuadPart = monotonic_counter();
if (frequency) frequency->QuadPart = TICKSPERSEC;
status = unix_funcs->NtQueryPerformanceCounter( counter, frequency );
}
__EXCEPT_PAGE_FAULT
{
return STATUS_ACCESS_VIOLATION;
}
__ENDTRY
return STATUS_SUCCESS;
return status;
}
/******************************************************************************
@ -562,7 +501,7 @@ NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER
*/
BOOL WINAPI DECLSPEC_HOTPATCH RtlQueryPerformanceCounter( LARGE_INTEGER *counter )
{
counter->QuadPart = monotonic_counter();
unix_funcs->NtQueryPerformanceCounter( counter, NULL );
return TRUE;
}
@ -1070,58 +1009,10 @@ NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzin
/***********************************************************************
* NtSetSystemTime [NTDLL.@]
* ZwSetSystemTime [NTDLL.@]
*
* Set the system time.
*
* PARAMS
* NewTime [I] The time to set.
* OldTime [O] Optional destination for the previous system time.
*
* RETURNS
* Success: STATUS_SUCCESS.
* Failure: An NTSTATUS error code indicating the problem.
*/
NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime)
NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *new, LARGE_INTEGER *old )
{
struct timeval tv;
time_t tm_t;
DWORD sec, oldsec;
LARGE_INTEGER tm;
/* Return the old time if necessary */
if (!OldTime) OldTime = &tm;
NtQuerySystemTime( OldTime );
if (!RtlTimeToSecondsSince1970( OldTime, &oldsec )) return STATUS_INVALID_PARAMETER;
if (!RtlTimeToSecondsSince1970( NewTime, &sec )) return STATUS_INVALID_PARAMETER;
/* fake success if time didn't change */
if (oldsec == sec)
return STATUS_SUCCESS;
/* set the new time */
tv.tv_sec = sec;
tv.tv_usec = 0;
#ifdef HAVE_SETTIMEOFDAY
tm_t = sec;
if (!settimeofday(&tv, NULL)) /* 0 is OK, -1 is error */
{
TRACE("OS time changed to %s\n", ctime(&tm_t));
return STATUS_SUCCESS;
}
ERR("Cannot set time to %s, time adjustment %ld: %s\n",
ctime(&tm_t), (long)(sec-oldsec), strerror(errno));
if (errno == EPERM)
return STATUS_PRIVILEGE_NOT_HELD;
else
return STATUS_INVALID_PARAMETER;
#else
tm_t = sec;
FIXME("setting time to %s not implemented for missing settimeofday\n",
ctime(&tm_t));
return STATUS_NOT_IMPLEMENTED;
#endif
return unix_funcs->NtSetSystemTime( new, old );
}
/***********************************************************************

View File

@ -1018,8 +1018,10 @@ static struct unix_funcs unix_funcs =
NtPulseEvent,
NtQueryEvent,
NtQueryMutant,
NtQueryPerformanceCounter,
NtQuerySection,
NtQuerySemaphore,
NtQuerySystemTime,
NtQueryTimer,
NtQueryVirtualMemory,
NtQueueApcThread,
@ -1034,6 +1036,7 @@ static struct unix_funcs unix_funcs =
NtSetContextThread,
NtSetEvent,
NtSetLdtEntries,
NtSetSystemTime,
NtSetTimer,
NtSignalAndWaitForSingleObject,
NtSuspendThread,

View File

@ -59,6 +59,7 @@
# include <mach/mach.h>
# include <mach/task.h>
# include <mach/semaphore.h>
# include <mach/mach_time.h>
#endif
#include "ntstatus.h"
@ -66,6 +67,7 @@
#define NONAMELESSUNION
#include "windef.h"
#include "winternl.h"
#include "ddk/wdm.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
@ -73,6 +75,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(sync);
#define TICKSPERSEC 10000000
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400)
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
HANDLE keyed_event = 0;
@ -87,6 +91,34 @@ static RTL_CRITICAL_SECTION_DEBUG addr_section_debug =
};
static RTL_CRITICAL_SECTION addr_section = { &addr_section_debug, -1, 0, 0, 0, 0 };
/* return a monotonic time counter, in Win32 ticks */
static inline ULONGLONG monotonic_counter(void)
{
struct timeval now;
#ifdef __APPLE__
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;
#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;
}
#ifdef __linux__
#define FUTEX_WAIT 0
@ -906,6 +938,84 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou
}
/******************************************************************************
* NtQueryPerformanceCounter (NTDLL.@)
*/
NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER *frequency )
{
counter->QuadPart = monotonic_counter();
if (frequency) frequency->QuadPart = TICKSPERSEC;
return STATUS_SUCCESS;
}
/***********************************************************************
* NtQuerySystemTime (NTDLL.@)
*/
NTSTATUS WINAPI NtQuerySystemTime( LARGE_INTEGER *time )
{
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */
if (clock_id == CLOCK_MONOTONIC)
{
#ifdef CLOCK_REALTIME_COARSE
struct timespec res;
/* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */
if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000)
clock_id = CLOCK_REALTIME_COARSE;
else
#endif /* CLOCK_REALTIME_COARSE */
clock_id = CLOCK_REALTIME;
}
if (!clock_gettime( clock_id, &ts ))
{
time->QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
time->QuadPart += (ts.tv_nsec + 50) / 100;
}
else
#endif /* HAVE_CLOCK_GETTIME */
{
struct timeval now;
gettimeofday( &now, 0 );
time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
time->QuadPart += now.tv_usec * 10;
}
return STATUS_SUCCESS;
}
/***********************************************************************
* NtSetSystemTime (NTDLL.@)
*/
NTSTATUS WINAPI NtSetSystemTime( const LARGE_INTEGER *new, LARGE_INTEGER *old )
{
LARGE_INTEGER now;
LONGLONG diff;
NtQuerySystemTime( &now );
if (old) *old = now;
diff = new->QuadPart - now.QuadPart;
if (diff > -TICKSPERSEC / 2 && diff < TICKSPERSEC / 2) return STATUS_SUCCESS;
ERR( "not allowed: difference %d ms\n", (int)(diff / 10000) );
return STATUS_PRIVILEGE_NOT_HELD;
}
/******************************************************************************
* NtGetTickCount (NTDLL.@)
*/
ULONG WINAPI NtGetTickCount(void)
{
/* note: we ignore TickCountMultiplier */
return user_shared_data->u.TickCount.LowPart;
}
/******************************************************************************
* NtCreateKeyedEvent (NTDLL.@)
*/

View File

@ -121,6 +121,7 @@ extern timeout_t server_start_time DECLSPEC_HIDDEN;
extern sigset_t server_block_set DECLSPEC_HIDDEN;
extern SIZE_T signal_stack_size DECLSPEC_HIDDEN;
extern SIZE_T signal_stack_mask DECLSPEC_HIDDEN;
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN;
extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;

View File

@ -161,7 +161,7 @@ static void *user_space_limit = (void *)0x7fff0000;
static void *working_set_limit = (void *)0x7fff0000;
#endif
static struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
SIZE_T signal_stack_size = 0;
SIZE_T signal_stack_mask = 0;

View File

@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 37
#define NTDLL_UNIXLIB_VERSION 38
struct unix_funcs
{
@ -96,10 +96,12 @@ struct unix_funcs
void *info, ULONG len, ULONG *ret_len );
NTSTATUS (WINAPI *NtQueryMutant)( HANDLE handle, MUTANT_INFORMATION_CLASS class,
void *info, ULONG len, ULONG *ret_len );
NTSTATUS (WINAPI *NtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
NTSTATUS (WINAPI *NtQuerySection)( HANDLE handle, SECTION_INFORMATION_CLASS class,
void *ptr, SIZE_T size, SIZE_T *ret_size );
NTSTATUS (WINAPI *NtQuerySemaphore)( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class,
void *info, ULONG len, ULONG *ret_len );
NTSTATUS (WINAPI *NtQuerySystemTime)( LARGE_INTEGER *time );
NTSTATUS (WINAPI *NtQueryTimer)( HANDLE handle, TIMER_INFORMATION_CLASS class,
void *info, ULONG len, ULONG *ret_len );
NTSTATUS (WINAPI *NtQueryVirtualMemory)( HANDLE process, LPCVOID addr,
@ -120,6 +122,7 @@ struct unix_funcs
NTSTATUS (WINAPI *NtSetContextThread)( HANDLE handle, const CONTEXT *context );
NTSTATUS (WINAPI *NtSetEvent)( HANDLE handle, LONG *prev_state );
NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 );
NTSTATUS (WINAPI *NtSetSystemTime)( const LARGE_INTEGER *new, LARGE_INTEGER *old );
NTSTATUS (WINAPI *NtSetTimer)( HANDLE handle, const LARGE_INTEGER *when,
PTIMER_APC_ROUTINE callback, void *arg,
BOOLEAN resume, ULONG period, BOOLEAN *state );