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.
This commit is contained in:
parent
cc365bd822
commit
462172a3d6
|
@ -23,12 +23,13 @@
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
#include "wine/server.h"
|
||||||
|
|
||||||
/* debug helper */
|
/* debug helper */
|
||||||
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
|
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
|
||||||
extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
|
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 */
|
/* module handling */
|
||||||
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
|
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
|
||||||
|
|
|
@ -412,20 +412,16 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles,
|
||||||
PLARGE_INTEGER timeout )
|
PLARGE_INTEGER timeout )
|
||||||
{
|
{
|
||||||
int ret, cookie;
|
int ret, cookie;
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
if (count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
|
if (count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
|
||||||
|
|
||||||
NTDLL_get_server_timeout( &tv, timeout );
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
SERVER_START_REQ( select )
|
SERVER_START_REQ( select )
|
||||||
{
|
{
|
||||||
req->flags = SELECT_INTERRUPTIBLE;
|
req->flags = SELECT_INTERRUPTIBLE;
|
||||||
req->cookie = &cookie;
|
req->cookie = &cookie;
|
||||||
req->sec = tv.tv_sec;
|
NTDLL_get_server_timeout( &req->timeout, timeout );
|
||||||
req->usec = tv.tv_usec;
|
|
||||||
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
|
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
|
||||||
|
|
||||||
if (wait_all) req->flags |= SELECT_ALL;
|
if (wait_all) req->flags |= SELECT_ALL;
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "ntdll_misc.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
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.
|
* 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;
|
UINT remainder;
|
||||||
|
|
||||||
if (!timeout) /* infinite timeout */
|
if (!timeout) /* infinite timeout */
|
||||||
{
|
{
|
||||||
when->tv_sec = when->tv_usec = 0;
|
when->sec = when->usec = 0;
|
||||||
}
|
}
|
||||||
else if (timeout->QuadPart <= 0) /* relative timeout */
|
else if (timeout->QuadPart <= 0) /* relative timeout */
|
||||||
{
|
{
|
||||||
|
struct timeval tv;
|
||||||
ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder );
|
ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder );
|
||||||
gettimeofday( when, 0 );
|
gettimeofday( &tv, 0 );
|
||||||
if ((when->tv_usec += remainder / 10) >= 1000000)
|
when->sec = tv.tv_sec + sec;
|
||||||
|
if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000)
|
||||||
{
|
{
|
||||||
when->tv_usec -= 1000000;
|
when->usec -= 1000000;
|
||||||
when->tv_sec++;
|
when->sec++;
|
||||||
}
|
}
|
||||||
when->tv_sec += sec;
|
|
||||||
}
|
}
|
||||||
else /* absolute time */
|
else /* absolute time */
|
||||||
{
|
{
|
||||||
when->tv_sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970,
|
when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970,
|
||||||
TICKSPERSEC, &remainder );
|
TICKSPERSEC, &remainder );
|
||||||
when->tv_usec = remainder / 10;
|
when->usec = remainder / 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,13 @@ typedef struct
|
||||||
} startup_info_t;
|
} startup_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int sec;
|
||||||
|
int usec;
|
||||||
|
} abs_time_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
atom_t atom;
|
atom_t atom;
|
||||||
|
@ -608,8 +615,7 @@ struct select_request
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
int flags;
|
int flags;
|
||||||
void* cookie;
|
void* cookie;
|
||||||
int sec;
|
abs_time_t timeout;
|
||||||
int usec;
|
|
||||||
/* VARARG(handles,handles); */
|
/* VARARG(handles,handles); */
|
||||||
};
|
};
|
||||||
struct select_reply
|
struct select_reply
|
||||||
|
@ -1994,8 +2000,7 @@ struct set_timer_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
obj_handle_t handle;
|
obj_handle_t handle;
|
||||||
int sec;
|
abs_time_t expire;
|
||||||
int usec;
|
|
||||||
int period;
|
int period;
|
||||||
void* callback;
|
void* callback;
|
||||||
void* arg;
|
void* arg;
|
||||||
|
@ -3572,6 +3577,6 @@ union generic_reply
|
||||||
struct get_next_hook_reply get_next_hook_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 */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -130,21 +130,18 @@ BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG per
|
||||||
PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
|
PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
|
||||||
{
|
{
|
||||||
BOOL ret;
|
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 )
|
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->handle = handle;
|
||||||
req->sec = tv.tv_sec;
|
|
||||||
req->usec = tv.tv_usec;
|
|
||||||
req->period = period;
|
req->period = period;
|
||||||
req->callback = callback;
|
req->callback = callback;
|
||||||
req->arg = arg;
|
req->arg = arg;
|
||||||
|
|
|
@ -167,6 +167,13 @@ typedef struct
|
||||||
/* char title[...]; */
|
/* char title[...]; */
|
||||||
} startup_info_t;
|
} 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 */
|
/* structure returned in the list of window properties */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -486,8 +493,7 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC, APC_ASYNC_IO };
|
||||||
@REQ(select)
|
@REQ(select)
|
||||||
int flags; /* wait flags (see below) */
|
int flags; /* wait flags (see below) */
|
||||||
void* cookie; /* magic cookie to return to client */
|
void* cookie; /* magic cookie to return to client */
|
||||||
int sec; /* absolute timeout */
|
abs_time_t timeout; /* absolute timeout */
|
||||||
int usec; /* absolute timeout */
|
|
||||||
VARARG(handles,handles); /* handles to select on */
|
VARARG(handles,handles); /* handles to select on */
|
||||||
@END
|
@END
|
||||||
#define SELECT_ALL 1
|
#define SELECT_ALL 1
|
||||||
|
@ -1426,8 +1432,7 @@ enum char_info_mode
|
||||||
/* Set a waitable timer */
|
/* Set a waitable timer */
|
||||||
@REQ(set_timer)
|
@REQ(set_timer)
|
||||||
obj_handle_t handle; /* handle to the timer */
|
obj_handle_t handle; /* handle to the timer */
|
||||||
int sec; /* next expiration absolute time */
|
abs_time_t expire; /* next expiration absolute time */
|
||||||
int usec; /* next expiration absolute time */
|
|
||||||
int period; /* timer period in ms */
|
int period; /* timer period in ms */
|
||||||
void* callback; /* callback function */
|
void* callback; /* callback function */
|
||||||
void* arg; /* callback argument */
|
void* arg; /* callback argument */
|
||||||
|
|
|
@ -373,7 +373,7 @@ static void end_wait( struct thread *thread )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build the thread wait structure */
|
/* 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 thread_wait *wait;
|
||||||
struct wait_queue_entry *entry;
|
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;
|
current->wait = wait;
|
||||||
if (flags & SELECT_TIMEOUT)
|
if (flags & SELECT_TIMEOUT)
|
||||||
{
|
{
|
||||||
wait->timeout.tv_sec = sec;
|
wait->timeout.tv_sec = timeout->sec;
|
||||||
wait->timeout.tv_usec = usec;
|
wait->timeout.tv_usec = timeout->usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, entry = wait->queues; i < count; i++, entry++)
|
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 */
|
/* select on a list of handles */
|
||||||
static void select_on( int count, void *cookie, const obj_handle_t *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;
|
int ret, i;
|
||||||
struct object *objects[MAXIMUM_WAIT_OBJECTS];
|
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 (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)
|
if ((ret = check_wait( current )) != -1)
|
||||||
{
|
{
|
||||||
|
@ -963,7 +963,7 @@ DECL_HANDLER(resume_thread)
|
||||||
DECL_HANDLER(select)
|
DECL_HANDLER(select)
|
||||||
{
|
{
|
||||||
int count = get_req_data_size() / sizeof(int);
|
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 */
|
/* queue an APC for a thread */
|
||||||
|
|
|
@ -131,7 +131,7 @@ static void cancel_timer( struct timer *timer )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the timer expiration and period */
|
/* 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 )
|
void *callback, void *arg )
|
||||||
{
|
{
|
||||||
cancel_timer( timer );
|
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 */
|
period = 0; /* period doesn't make any sense for a manual timer */
|
||||||
timer->signaled = 0;
|
timer->signaled = 0;
|
||||||
}
|
}
|
||||||
if (!sec && !usec)
|
if (!expire->sec && !expire->usec)
|
||||||
{
|
{
|
||||||
/* special case: use now + period as first expiration */
|
/* special case: use now + period as first expiration */
|
||||||
gettimeofday( &timer->when, 0 );
|
gettimeofday( &timer->when, 0 );
|
||||||
|
@ -148,8 +148,8 @@ static void set_timer( struct timer *timer, int sec, int usec, int period,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timer->when.tv_sec = sec;
|
timer->when.tv_sec = expire->sec;
|
||||||
timer->when.tv_usec = usec;
|
timer->when.tv_usec = expire->usec;
|
||||||
}
|
}
|
||||||
timer->period = period;
|
timer->period = period;
|
||||||
timer->callback = callback;
|
timer->callback = callback;
|
||||||
|
@ -220,7 +220,7 @@ DECL_HANDLER(set_timer)
|
||||||
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
|
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
|
||||||
TIMER_MODIFY_STATE, &timer_ops )))
|
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 );
|
release_object( timer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,29 @@ static void dump_uints( const int *ptr, int len )
|
||||||
fputc( '}', stderr );
|
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 )
|
static void dump_rectangle( const rectangle_t *rect )
|
||||||
{
|
{
|
||||||
fprintf( stderr, "{%d,%d;%d,%d}",
|
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, " flags=%d,", req->flags );
|
||||||
fprintf( stderr, " cookie=%p,", req->cookie );
|
fprintf( stderr, " cookie=%p,", req->cookie );
|
||||||
fprintf( stderr, " sec=%d,", req->sec );
|
fprintf( stderr, " timeout=" );
|
||||||
fprintf( stderr, " usec=%d,", req->usec );
|
dump_abs_time( &req->timeout );
|
||||||
|
fprintf( stderr, "," );
|
||||||
fprintf( stderr, " handles=" );
|
fprintf( stderr, " handles=" );
|
||||||
dump_varargs_handles( cur_size );
|
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 )
|
static void dump_set_timer_request( const struct set_timer_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%p,", req->handle );
|
fprintf( stderr, " handle=%p,", req->handle );
|
||||||
fprintf( stderr, " sec=%d,", req->sec );
|
fprintf( stderr, " expire=" );
|
||||||
fprintf( stderr, " usec=%d,", req->usec );
|
dump_abs_time( &req->expire );
|
||||||
|
fprintf( stderr, "," );
|
||||||
fprintf( stderr, " period=%d,", req->period );
|
fprintf( stderr, " period=%d,", req->period );
|
||||||
fprintf( stderr, " callback=%p,", req->callback );
|
fprintf( stderr, " callback=%p,", req->callback );
|
||||||
fprintf( stderr, " arg=%p", req->arg );
|
fprintf( stderr, " arg=%p", req->arg );
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"user_handle_t" => "%p",
|
"user_handle_t" => "%p",
|
||||||
"process_id_t" => "%04x",
|
"process_id_t" => "%04x",
|
||||||
"thread_id_t" => "%04x",
|
"thread_id_t" => "%04x",
|
||||||
|
"abs_time_t" => "&dump_abs_time",
|
||||||
"rectangle_t" => "&dump_rectangle",
|
"rectangle_t" => "&dump_rectangle",
|
||||||
"char_info_t" => "&dump_char_info",
|
"char_info_t" => "&dump_char_info",
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue