From 462172a3d63e1a9e5488acd3841dd0f3c432c06a Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 2 Apr 2003 22:48:59 +0000 Subject: [PATCH] Added abs_time_t structure to the server protocol, and added a dump routine for it that displays the relative timeout to make timeout values easier to interpret. --- dlls/ntdll/ntdll_misc.h | 3 ++- dlls/ntdll/sync.c | 6 +----- dlls/ntdll/time.c | 20 +++++++++++--------- include/wine/server_protocol.h | 15 ++++++++++----- scheduler/timer.c | 19 ++++++++----------- server/protocol.def | 13 +++++++++---- server/thread.c | 12 ++++++------ server/timer.c | 10 +++++----- server/trace.c | 33 +++++++++++++++++++++++++++++---- tools/make_requests | 1 + 10 files changed, 82 insertions(+), 50 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 0809bee62ff..7d22ca87b8f 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -23,12 +23,13 @@ #include "winternl.h" #include "module.h" #include "thread.h" +#include "wine/server.h" /* debug helper */ extern LPCSTR debugstr_us( const UNICODE_STRING *str ); extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes); -extern void NTDLL_get_server_timeout( struct timeval *when, const LARGE_INTEGER *timeout ); +extern void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout ); /* module handling */ extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop ); diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 5e72d3e8aca..1662d738e72 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -412,20 +412,16 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, PLARGE_INTEGER timeout ) { int ret, cookie; - struct timeval tv; if (count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - NTDLL_get_server_timeout( &tv, timeout ); - for (;;) { SERVER_START_REQ( select ) { req->flags = SELECT_INTERRUPTIBLE; req->cookie = &cookie; - req->sec = tv.tv_sec; - req->usec = tv.tv_usec; + NTDLL_get_server_timeout( &req->timeout, timeout ); wine_server_add_data( req, handles, count * sizeof(HANDLE) ); if (wait_all) req->flags |= SELECT_ALL; diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c index 22805ddedf4..669ae9e9b4c 100644 --- a/dlls/ntdll/time.c +++ b/dlls/ntdll/time.c @@ -40,6 +40,7 @@ #include "winternl.h" #include "wine/unicode.h" #include "wine/debug.h" +#include "ntdll_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(ntdll); @@ -299,30 +300,31 @@ static inline void NormalizeTimeFields(CSHORT *FieldToNormalize, CSHORT *CarryFi * * Convert a NTDLL timeout into a timeval struct to send to the server. */ -void NTDLL_get_server_timeout( struct timeval *when, const LARGE_INTEGER *timeout ) +void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout ) { UINT remainder; if (!timeout) /* infinite timeout */ { - when->tv_sec = when->tv_usec = 0; + when->sec = when->usec = 0; } else if (timeout->QuadPart <= 0) /* relative timeout */ { + struct timeval tv; ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder ); - gettimeofday( when, 0 ); - if ((when->tv_usec += remainder / 10) >= 1000000) + gettimeofday( &tv, 0 ); + when->sec = tv.tv_sec + sec; + if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000) { - when->tv_usec -= 1000000; - when->tv_sec++; + when->usec -= 1000000; + when->sec++; } - when->tv_sec += sec; } else /* absolute time */ { - when->tv_sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970, + when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970, TICKSPERSEC, &remainder ); - when->tv_usec = remainder / 10; + when->usec = remainder / 10; } } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 07161312934..0a5ef3427c3 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -152,6 +152,13 @@ typedef struct } startup_info_t; +typedef struct +{ + int sec; + int usec; +} abs_time_t; + + typedef struct { atom_t atom; @@ -608,8 +615,7 @@ struct select_request struct request_header __header; int flags; void* cookie; - int sec; - int usec; + abs_time_t timeout; /* VARARG(handles,handles); */ }; struct select_reply @@ -1994,8 +2000,7 @@ struct set_timer_request { struct request_header __header; obj_handle_t handle; - int sec; - int usec; + abs_time_t expire; int period; void* callback; void* arg; @@ -3572,6 +3577,6 @@ union generic_reply struct get_next_hook_reply get_next_hook_reply; }; -#define SERVER_PROTOCOL_VERSION 103 +#define SERVER_PROTOCOL_VERSION 104 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/scheduler/timer.c b/scheduler/timer.c index ee6e9072165..6ed81a0c3ca 100644 --- a/scheduler/timer.c +++ b/scheduler/timer.c @@ -130,21 +130,18 @@ BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG per PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume ) { BOOL ret; - struct timeval tv; - - if (!when->s.LowPart && !when->s.HighPart) - { - /* special case to start timeout on now+period without too many calculations */ - tv.tv_sec = 0; - tv.tv_usec = 0; - } - else NTDLL_get_server_timeout( &tv, when ); SERVER_START_REQ( set_timer ) { + if (!when->s.LowPart && !when->s.HighPart) + { + /* special case to start timeout on now+period without too many calculations */ + req->expire.sec = 0; + req->expire.usec = 0; + } + else NTDLL_get_server_timeout( &req->expire, when ); + req->handle = handle; - req->sec = tv.tv_sec; - req->usec = tv.tv_usec; req->period = period; req->callback = callback; req->arg = arg; diff --git a/server/protocol.def b/server/protocol.def index a3db3858d48..b27788b4f43 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -167,6 +167,13 @@ typedef struct /* char title[...]; */ } startup_info_t; +/* structure for absolute timeouts */ +typedef struct +{ + int sec; /* seconds since Unix epoch */ + int usec; /* microseconds */ +} abs_time_t; + /* structure returned in the list of window properties */ typedef struct { @@ -486,8 +493,7 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC, APC_ASYNC_IO }; @REQ(select) int flags; /* wait flags (see below) */ void* cookie; /* magic cookie to return to client */ - int sec; /* absolute timeout */ - int usec; /* absolute timeout */ + abs_time_t timeout; /* absolute timeout */ VARARG(handles,handles); /* handles to select on */ @END #define SELECT_ALL 1 @@ -1426,8 +1432,7 @@ enum char_info_mode /* Set a waitable timer */ @REQ(set_timer) obj_handle_t handle; /* handle to the timer */ - int sec; /* next expiration absolute time */ - int usec; /* next expiration absolute time */ + abs_time_t expire; /* next expiration absolute time */ int period; /* timer period in ms */ void* callback; /* callback function */ void* arg; /* callback argument */ diff --git a/server/thread.c b/server/thread.c index 0db0ada80e3..ad310c9dc51 100644 --- a/server/thread.c +++ b/server/thread.c @@ -373,7 +373,7 @@ static void end_wait( struct thread *thread ) } /* build the thread wait structure */ -static int wait_on( int count, struct object *objects[], int flags, int sec, int usec ) +static int wait_on( int count, struct object *objects[], int flags, const abs_time_t *timeout ) { struct thread_wait *wait; struct wait_queue_entry *entry; @@ -388,8 +388,8 @@ static int wait_on( int count, struct object *objects[], int flags, int sec, int current->wait = wait; if (flags & SELECT_TIMEOUT) { - wait->timeout.tv_sec = sec; - wait->timeout.tv_usec = usec; + wait->timeout.tv_sec = timeout->sec; + wait->timeout.tv_usec = timeout->usec; } for (i = 0, entry = wait->queues; i < count; i++, entry++) @@ -518,7 +518,7 @@ static void thread_timeout( void *ptr ) /* select on a list of handles */ static void select_on( int count, void *cookie, const obj_handle_t *handles, - int flags, int sec, int usec ) + int flags, const abs_time_t *timeout ) { int ret, i; struct object *objects[MAXIMUM_WAIT_OBJECTS]; @@ -535,7 +535,7 @@ static void select_on( int count, void *cookie, const obj_handle_t *handles, } if (i < count) goto done; - if (!wait_on( count, objects, flags, sec, usec )) goto done; + if (!wait_on( count, objects, flags, timeout )) goto done; if ((ret = check_wait( current )) != -1) { @@ -963,7 +963,7 @@ DECL_HANDLER(resume_thread) DECL_HANDLER(select) { int count = get_req_data_size() / sizeof(int); - select_on( count, req->cookie, get_req_data(), req->flags, req->sec, req->usec ); + select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout ); } /* queue an APC for a thread */ diff --git a/server/timer.c b/server/timer.c index 4ca7793bb62..85cf0801d89 100644 --- a/server/timer.c +++ b/server/timer.c @@ -131,7 +131,7 @@ static void cancel_timer( struct timer *timer ) } /* set the timer expiration and period */ -static void set_timer( struct timer *timer, int sec, int usec, int period, +static void set_timer( struct timer *timer, const abs_time_t *expire, int period, void *callback, void *arg ) { cancel_timer( timer ); @@ -140,7 +140,7 @@ static void set_timer( struct timer *timer, int sec, int usec, int period, period = 0; /* period doesn't make any sense for a manual timer */ timer->signaled = 0; } - if (!sec && !usec) + if (!expire->sec && !expire->usec) { /* special case: use now + period as first expiration */ gettimeofday( &timer->when, 0 ); @@ -148,8 +148,8 @@ static void set_timer( struct timer *timer, int sec, int usec, int period, } else { - timer->when.tv_sec = sec; - timer->when.tv_usec = usec; + timer->when.tv_sec = expire->sec; + timer->when.tv_usec = expire->usec; } timer->period = period; timer->callback = callback; @@ -220,7 +220,7 @@ DECL_HANDLER(set_timer) if ((timer = (struct timer *)get_handle_obj( current->process, req->handle, TIMER_MODIFY_STATE, &timer_ops ))) { - set_timer( timer, req->sec, req->usec, req->period, req->callback, req->arg ); + set_timer( timer, &req->expire, req->period, req->callback, req->arg ); release_object( timer ); } } diff --git a/server/trace.c b/server/trace.c index 2110883410c..9f466158cc6 100644 --- a/server/trace.c +++ b/server/trace.c @@ -59,6 +59,29 @@ static void dump_uints( const int *ptr, int len ) fputc( '}', stderr ); } +static void dump_abs_time( const abs_time_t *time ) +{ + struct timeval tv; + int secs, usecs; + + if (!time->sec && !time->usec) + { + fprintf( stderr, "0" ); + return; + } + gettimeofday( &tv, NULL ); + secs = time->sec - tv.tv_sec; + if ((usecs = time->usec - tv.tv_usec) < 0) + { + usecs += 1000000; + secs--; + } + if (secs > 0 || (secs == 0 && usecs >= 0)) + fprintf( stderr, "%d.%06d (+%d.%06d)", time->sec, time->usec, secs, usecs ); + else + fprintf( stderr, "%d.%06d (-%d.%06d)", time->sec, time->usec, abs(secs+1), 1000000-usecs ); +} + static void dump_rectangle( const rectangle_t *rect ) { fprintf( stderr, "{%d,%d;%d,%d}", @@ -684,8 +707,9 @@ static void dump_select_request( const struct select_request *req ) { fprintf( stderr, " flags=%d,", req->flags ); fprintf( stderr, " cookie=%p,", req->cookie ); - fprintf( stderr, " sec=%d,", req->sec ); - fprintf( stderr, " usec=%d,", req->usec ); + fprintf( stderr, " timeout=" ); + dump_abs_time( &req->timeout ); + fprintf( stderr, "," ); fprintf( stderr, " handles=" ); dump_varargs_handles( cur_size ); } @@ -1662,8 +1686,9 @@ static void dump_open_timer_reply( const struct open_timer_reply *req ) static void dump_set_timer_request( const struct set_timer_request *req ) { fprintf( stderr, " handle=%p,", req->handle ); - fprintf( stderr, " sec=%d,", req->sec ); - fprintf( stderr, " usec=%d,", req->usec ); + fprintf( stderr, " expire=" ); + dump_abs_time( &req->expire ); + fprintf( stderr, "," ); fprintf( stderr, " period=%d,", req->period ); fprintf( stderr, " callback=%p,", req->callback ); fprintf( stderr, " arg=%p", req->arg ); diff --git a/tools/make_requests b/tools/make_requests index 86043e1373d..1d7d7b63c04 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -36,6 +36,7 @@ "user_handle_t" => "%p", "process_id_t" => "%04x", "thread_id_t" => "%04x", + "abs_time_t" => "&dump_abs_time", "rectangle_t" => "&dump_rectangle", "char_info_t" => "&dump_char_info", );