From: Marc-Aurel Zent <mzent@codeweavers.com> --- server/fd.c | 15 ++++++++++++++- server/request.c | 18 +++++++++++------- server/request.h | 4 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/server/fd.c b/server/fd.c index f70bec354a3..905f11efb7c 100644 --- a/server/fd.c +++ b/server/fd.c @@ -351,6 +351,7 @@ static struct list abs_timeout_list = LIST_INIT(abs_timeout_list); /* sorted abs static struct list rel_timeout_list = LIST_INIT(rel_timeout_list); /* sorted relative timeouts list */ timeout_t current_time; timeout_t monotonic_time; +static timeout_t current_suspend_bias; struct _KUSER_SHARED_DATA *user_shared_data = NULL; static const timeout_t user_shared_data_timeout = 16 * 10000; @@ -377,6 +378,15 @@ static void atomic_store_long(volatile LONG *ptr, LONG value) #endif } +static void atomic_store_ulonglong(volatile ULONGLONG *ptr, ULONGLONG value) +{ +#if defined(__i386__) || defined(__x86_64__) + *ptr = value; +#else + __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST); +#endif +} + static void set_user_shared_data_time(void) { timeout_t tick_count = monotonic_time / 10000; @@ -409,6 +419,9 @@ static void set_user_shared_data_time(void) atomic_store_ulong(&user_shared_data->InterruptTime.LowPart, monotonic_time); atomic_store_long(&user_shared_data->InterruptTime.High1Time, monotonic_time >> 32); + if (current_suspend_bias > user_shared_data->InterruptTimeBias + 10000) + atomic_store_ulonglong(&user_shared_data->InterruptTimeBias, current_suspend_bias); + atomic_store_long(&user_shared_data->TickCount.High2Time, tick_count >> 32); atomic_store_ulong(&user_shared_data->TickCount.LowPart, tick_count); atomic_store_long(&user_shared_data->TickCount.High1Time, tick_count >> 32); @@ -421,7 +434,7 @@ void set_current_time(void) struct timeval now; gettimeofday( &now, NULL ); current_time = (timeout_t)now.tv_sec * TICKS_PER_SEC + now.tv_usec * 10 + ticks_1601_to_1970; - monotonic_time = monotonic_counter(); + monotonic_time = monotonic_counter( ¤t_suspend_bias ); if (user_shared_data) set_user_shared_data_time(); } diff --git a/server/request.c b/server/request.c index 432a5918892..239e93ebf60 100644 --- a/server/request.c +++ b/server/request.c @@ -505,24 +505,28 @@ int send_client_fd( struct process *process, int fd, obj_handle_t handle ) return -1; } -/* return a monotonic time counter */ -timeout_t monotonic_counter(void) +/* return a monotonic time counter and optional suspend bias */ +timeout_t monotonic_counter( timeout_t *bias ) { + timeout_t counter, unbiased_counter = 0; #ifdef __APPLE__ static mach_timebase_info_data_t timebase; if (!timebase.denom) mach_timebase_info( &timebase ); - return mach_continuous_time() * timebase.numer / timebase.denom / 100; + unbiased_counter = mach_absolute_time() * timebase.numer / timebase.denom / 100; + counter = mach_continuous_time() * timebase.numer / timebase.denom / 100; #elif defined(HAVE_CLOCK_GETTIME) struct timespec ts; + if (!clock_gettime( CLOCK_MONOTONIC, &ts )) + counter = unbiased_counter = (timeout_t)ts.tv_sec * TICKS_PER_SEC + ts.tv_nsec / 100; #ifdef CLOCK_BOOTTIME if (!clock_gettime( CLOCK_BOOTTIME, &ts )) - return (timeout_t)ts.tv_sec * TICKS_PER_SEC + ts.tv_nsec / 100; + counter = (timeout_t)ts.tv_sec * TICKS_PER_SEC + ts.tv_nsec / 100; #endif - if (!clock_gettime( CLOCK_MONOTONIC, &ts )) - return (timeout_t)ts.tv_sec * TICKS_PER_SEC + ts.tv_nsec / 100; #endif - return current_time - server_start_time; + if (!unbiased_counter) counter = unbiased_counter = current_time - server_start_time; + if (bias) *bias = counter - unbiased_counter; + return counter; } static void master_socket_dump( struct object *obj, int verbose ) diff --git a/server/request.h b/server/request.h index 13254d967ed..2a082c874b6 100644 --- a/server/request.h +++ b/server/request.h @@ -54,7 +54,7 @@ extern int receive_fd( struct process *process ); extern int send_client_fd( struct process *process, int fd, obj_handle_t handle ); extern void read_request( struct thread *thread ); extern void write_reply( struct thread *thread ); -extern timeout_t monotonic_counter(void); +extern timeout_t monotonic_counter( timeout_t *bias ); extern void open_master_socket(void); extern void close_master_socket( timeout_t timeout ); extern void shutdown_master_socket(void); @@ -69,7 +69,7 @@ extern void trace_reply( enum request req, const union generic_reply *reply ); /* get current tick count to return to client */ static inline unsigned int get_tick_count(void) { - return monotonic_counter() / 10000; + return monotonic_counter( NULL ) / 10000; } /* get the request vararg data */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9875