From: Anton Baskanov baskanov@gmail.com
Fixes long uptimes causing Parkan: Iron Strategy to hang shortly after starting a mission and laggy arrows in GTA San Andreas lowrider challenge. The games seem to not like low values either so add a 5 minute offset to the counter. --- dlls/ntdll/unix/server.c | 2 ++ dlls/ntdll/unix/sync.c | 10 ++++++++-- dlls/ntdll/unix/unix_private.h | 1 + include/wine/server_protocol.h | 3 ++- server/main.c | 1 + server/object.h | 2 ++ server/protocol.def | 25 +++++++++++++------------ server/request.c | 16 ++++++++++++++-- server/request.h | 1 + server/request_handlers.h | 7 ++++--- server/request_trace.h | 1 + server/thread.c | 1 + 12 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index b40e7c2a1d7..bdf9bed6f40 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -98,6 +98,7 @@ USHORT native_machine = 0; BOOL process_exiting = FALSE;
timeout_t server_start_time = 0; /* time of server startup */ +timeout_t monotonic_start_time = 0; /* monotonic time of server startup */
sigset_t server_block_set; /* signals to block during server calls */ static int fd_socket = -1; /* socket to exchange file descriptors with the server */ @@ -1624,6 +1625,7 @@ size_t server_init_process(void) peb->SessionId = reply->session_id; info_size = reply->info_size; server_start_time = reply->server_start; + monotonic_start_time = reply->monotonic_start; supported_machines_count = wine_server_reply_size( reply ) / sizeof(*supported_machines); } SERVER_END_REQ; diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 2b01aaf83b8..e70bd0613ae 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -77,8 +77,7 @@ static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) return wine_dbgstr_longlong( timeout->QuadPart ); }
-/* return a monotonic time counter, in Win32 ticks */ -static inline ULONGLONG monotonic_counter(void) +static inline ULONGLONG absoulute_monotonic_counter(void) { struct timeval now; #ifdef __APPLE__ @@ -99,6 +98,13 @@ static inline ULONGLONG monotonic_counter(void) return ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10 - server_start_time; }
+/* return a monotonic time counter, in Win32 ticks */ +static inline ULONGLONG monotonic_counter(void) +{ + timeout_t time_offset = 5LL * 60 * TICKSPERSEC; + return absoulute_monotonic_counter() - monotonic_start_time + time_offset; +} + #ifdef __linux__
#define USE_FUTEX diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index f840045f841..bf1978d2ea5 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -180,6 +180,7 @@ extern USHORT supported_machines[8]; extern BOOL process_exiting; extern HANDLE keyed_event; extern timeout_t server_start_time; +extern timeout_t monotonic_start_time; extern sigset_t server_block_set; extern struct _KUSER_SHARED_DATA *user_shared_data; extern SYSTEM_CPU_INFORMATION cpu_info; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index a39ab123970..42ab73e87ab 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1129,6 +1129,7 @@ struct init_first_thread_reply process_id_t pid; thread_id_t tid; timeout_t server_start; + timeout_t monotonic_start; unsigned int session_id; data_size_t info_size; /* VARARG(machines,ushorts); */ @@ -6775,6 +6776,6 @@ union generic_reply struct set_keyboard_repeat_reply set_keyboard_repeat_reply; };
-#define SERVER_PROTOCOL_VERSION 855 +#define SERVER_PROTOCOL_VERSION 856
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/main.c b/server/main.c index 1248b92f24d..2c0b690c7a5 100644 --- a/server/main.c +++ b/server/main.c @@ -230,6 +230,7 @@ int main( int argc, char *argv[] ) open_master_socket();
if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() ); + init_monotonic_counter(); set_current_time(); init_signals(); init_memory(); diff --git a/server/object.h b/server/object.h index 7555f564a08..bc71df4e5f3 100644 --- a/server/object.h +++ b/server/object.h @@ -308,6 +308,8 @@ extern const char *server_argv0;
/* server start time used for GetTickCount() */ extern timeout_t server_start_time; + /* server start time used for monotonic_counter() */ +extern timeout_t monotonic_start_time;
/* object types */ extern struct type_descr no_type; diff --git a/server/protocol.def b/server/protocol.def index 292303c385f..0b63dd40deb 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1098,18 +1098,19 @@ struct obj_locator
/* Initialize the first thread of a new process */ @REQ(init_first_thread) - int unix_pid; /* Unix pid of new process */ - int unix_tid; /* Unix tid of new thread */ - int debug_level; /* new debug level */ - int reply_fd; /* fd for reply pipe */ - int wait_fd; /* fd for blocking calls pipe */ -@REPLY - process_id_t pid; /* process id of the new thread's process */ - thread_id_t tid; /* thread id of the new thread */ - timeout_t server_start; /* server start time */ - unsigned int session_id; /* process session id */ - data_size_t info_size; /* total size of startup info */ - VARARG(machines,ushorts); /* array of supported machines */ + int unix_pid; /* Unix pid of new process */ + int unix_tid; /* Unix tid of new thread */ + int debug_level; /* new debug level */ + int reply_fd; /* fd for reply pipe */ + int wait_fd; /* fd for blocking calls pipe */ +@REPLY + process_id_t pid; /* process id of the new thread's process */ + thread_id_t tid; /* thread id of the new thread */ + timeout_t server_start; /* server start time */ + timeout_t monotonic_start; /* server monotonic start time */ + unsigned int session_id; /* process session id */ + data_size_t info_size; /* total size of startup info */ + VARARG(machines,ushorts); /* array of supported machines */ @END
diff --git a/server/request.c b/server/request.c index 2254315b79e..6b859a97761 100644 --- a/server/request.c +++ b/server/request.c @@ -120,6 +120,7 @@ static const struct fd_ops master_socket_fd_ops = struct thread *current = NULL; /* thread handling the current request */ unsigned int global_error = 0; /* global error code for when no thread is current */ timeout_t server_start_time = 0; /* server startup time */ +timeout_t monotonic_start_time = 0; /* server monotonic startup time */ char *server_dir = NULL; /* server directory */ int server_dir_fd = -1; /* file descriptor for the server dir */ int config_dir_fd = -1; /* file descriptor for the config dir */ @@ -504,8 +505,7 @@ 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) +static timeout_t absolute_monotonic_counter(void) { #ifdef __APPLE__ static mach_timebase_info_data_t timebase; @@ -524,6 +524,18 @@ timeout_t monotonic_counter(void) return current_time - server_start_time; }
+void init_monotonic_counter(void) +{ + monotonic_start_time = absolute_monotonic_counter(); +} + +/* return a monotonic time counter */ +timeout_t monotonic_counter(void) +{ + timeout_t time_offset = 5LL * 60 * TICKS_PER_SEC; + return absolute_monotonic_counter() - monotonic_start_time + time_offset; +} + static void master_socket_dump( struct object *obj, int verbose ) { struct master_socket *sock = (struct master_socket *)obj; diff --git a/server/request.h b/server/request.h index 13254d967ed..cbef98e744b 100644 --- a/server/request.h +++ b/server/request.h @@ -54,6 +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 void init_monotonic_counter(void); extern timeout_t monotonic_counter(void); extern void open_master_socket(void); extern void close_master_socket( timeout_t timeout ); diff --git a/server/request_handlers.h b/server/request_handlers.h index fd39842df56..f7025a901ee 100644 --- a/server/request_handlers.h +++ b/server/request_handlers.h @@ -696,9 +696,10 @@ C_ASSERT( sizeof(struct init_first_thread_request) == 32 ); C_ASSERT( offsetof(struct init_first_thread_reply, pid) == 8 ); C_ASSERT( offsetof(struct init_first_thread_reply, tid) == 12 ); C_ASSERT( offsetof(struct init_first_thread_reply, server_start) == 16 ); -C_ASSERT( offsetof(struct init_first_thread_reply, session_id) == 24 ); -C_ASSERT( offsetof(struct init_first_thread_reply, info_size) == 28 ); -C_ASSERT( sizeof(struct init_first_thread_reply) == 32 ); +C_ASSERT( offsetof(struct init_first_thread_reply, monotonic_start) == 24 ); +C_ASSERT( offsetof(struct init_first_thread_reply, session_id) == 32 ); +C_ASSERT( offsetof(struct init_first_thread_reply, info_size) == 36 ); +C_ASSERT( sizeof(struct init_first_thread_reply) == 40 ); C_ASSERT( offsetof(struct init_thread_request, unix_tid) == 12 ); C_ASSERT( offsetof(struct init_thread_request, reply_fd) == 16 ); C_ASSERT( offsetof(struct init_thread_request, wait_fd) == 20 ); diff --git a/server/request_trace.h b/server/request_trace.h index 6e38f2a8379..75ab2ed45fc 100644 --- a/server/request_trace.h +++ b/server/request_trace.h @@ -147,6 +147,7 @@ static void dump_init_first_thread_reply( const struct init_first_thread_reply * fprintf( stderr, " pid=%04x", req->pid ); fprintf( stderr, ", tid=%04x", req->tid ); dump_timeout( ", server_start=", &req->server_start ); + dump_timeout( ", monotonic_start=", &req->monotonic_start ); fprintf( stderr, ", session_id=%08x", req->session_id ); fprintf( stderr, ", info_size=%u", req->info_size ); dump_varargs_ushorts( ", machines=", cur_size ); diff --git a/server/thread.c b/server/thread.c index b3ce5d9ac95..324064070dc 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1429,6 +1429,7 @@ DECL_HANDLER(init_first_thread) reply->session_id = process->session_id; reply->info_size = get_process_startup_info_size( process ); reply->server_start = server_start_time; + reply->monotonic_start = monotonic_start_time; set_reply_data( supported_machines, min( supported_machines_count * sizeof(unsigned short), get_reply_max_size() )); }