Commit 321d26cb authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

server: Use correct clock in select.

parent 6d2d3595
...@@ -600,11 +600,19 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT ...@@ -600,11 +600,19 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
obj_handle_t apc_handle = 0; obj_handle_t apc_handle = 0;
apc_call_t call; apc_call_t call;
apc_result_t result; apc_result_t result;
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE; abstime_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
sigset_t old_set; sigset_t old_set;
memset( &result, 0, sizeof(result) ); memset( &result, 0, sizeof(result) );
if (abs_timeout < 0)
{
LARGE_INTEGER now;
RtlQueryPerformanceCounter(&now);
abs_timeout -= now.QuadPart;
}
do do
{ {
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set ); pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
...@@ -619,7 +627,6 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT ...@@ -619,7 +627,6 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
wine_server_add_data( req, &result, sizeof(result) ); wine_server_add_data( req, &result, sizeof(result) );
wine_server_add_data( req, select_op, size ); wine_server_add_data( req, select_op, size );
ret = server_call_unlocked( req ); ret = server_call_unlocked( req );
abs_timeout = reply->timeout;
apc_handle = reply->apc_handle; apc_handle = reply->apc_handle;
call = reply->call; call = reply->call;
} }
......
...@@ -2463,7 +2463,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size ...@@ -2463,7 +2463,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
obj_handle_t apc_handle = 0; obj_handle_t apc_handle = 0;
apc_call_t call; apc_call_t call;
apc_result_t result; apc_result_t result;
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE; abstime_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
sigset_t old_set; sigset_t old_set;
if (size != 1 && size != 2 && size != 4 && size != 8) if (size != 1 && size != 2 && size != 4 && size != 8)
...@@ -2478,6 +2478,14 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size ...@@ -2478,6 +2478,14 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
memset( &result, 0, sizeof(result) ); memset( &result, 0, sizeof(result) );
if (abs_timeout < 0)
{
LARGE_INTEGER now;
RtlQueryPerformanceCounter(&now);
abs_timeout -= now.QuadPart;
}
do do
{ {
RtlEnterCriticalSection( &addr_section ); RtlEnterCriticalSection( &addr_section );
...@@ -2499,7 +2507,6 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size ...@@ -2499,7 +2507,6 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
wine_server_add_data( req, &result, sizeof(result) ); wine_server_add_data( req, &result, sizeof(result) );
wine_server_add_data( req, &select_op, sizeof(select_op.keyed_event) ); wine_server_add_data( req, &select_op, sizeof(select_op.keyed_event) );
ret = server_call_unlocked( req ); ret = server_call_unlocked( req );
abs_timeout = reply->timeout;
apc_handle = reply->apc_handle; apc_handle = reply->apc_handle;
call = reply->call; call = reply->call;
} }
......
...@@ -1250,7 +1250,7 @@ struct select_request ...@@ -1250,7 +1250,7 @@ struct select_request
struct request_header __header; struct request_header __header;
int flags; int flags;
client_ptr_t cookie; client_ptr_t cookie;
timeout_t timeout; abstime_t timeout;
obj_handle_t prev_apc; obj_handle_t prev_apc;
/* VARARG(result,apc_result); */ /* VARARG(result,apc_result); */
/* VARARG(data,select_op); */ /* VARARG(data,select_op); */
...@@ -1259,10 +1259,9 @@ struct select_request ...@@ -1259,10 +1259,9 @@ struct select_request
struct select_reply struct select_reply
{ {
struct reply_header __header; struct reply_header __header;
timeout_t timeout;
apc_call_t call; apc_call_t call;
obj_handle_t apc_handle; obj_handle_t apc_handle;
char __pad_60[4]; char __pad_52[4];
}; };
#define SELECT_ALERTABLE 1 #define SELECT_ALERTABLE 1
#define SELECT_INTERRUPTIBLE 2 #define SELECT_INTERRUPTIBLE 2
...@@ -6711,7 +6710,7 @@ union generic_reply ...@@ -6711,7 +6710,7 @@ union generic_reply
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 596 #define SERVER_PROTOCOL_VERSION 597
/* ### protocol_version end ### */ /* ### protocol_version end ### */
......
...@@ -1099,12 +1099,11 @@ struct rawinput_device ...@@ -1099,12 +1099,11 @@ struct rawinput_device
@REQ(select) @REQ(select)
int flags; /* wait flags (see below) */ int flags; /* wait flags (see below) */
client_ptr_t cookie; /* magic cookie to return to client */ client_ptr_t cookie; /* magic cookie to return to client */
timeout_t timeout; /* timeout */ abstime_t timeout; /* timeout */
obj_handle_t prev_apc; /* handle to previous APC */ obj_handle_t prev_apc; /* handle to previous APC */
VARARG(result,apc_result); /* result of previous APC */ VARARG(result,apc_result); /* result of previous APC */
VARARG(data,select_op); /* operation-specific data */ VARARG(data,select_op); /* operation-specific data */
@REPLY @REPLY
timeout_t timeout; /* timeout converted to absolute */
apc_call_t call; /* APC call arguments */ apc_call_t call; /* APC call arguments */
obj_handle_t apc_handle; /* handle to next APC */ obj_handle_t apc_handle; /* handle to next APC */
@END @END
......
...@@ -721,6 +721,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -721,6 +721,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_resume_process, (req_handler)req_resume_process,
}; };
C_ASSERT( sizeof(abstime_t) == 8 );
C_ASSERT( sizeof(affinity_t) == 8 ); C_ASSERT( sizeof(affinity_t) == 8 );
C_ASSERT( sizeof(apc_call_t) == 40 ); C_ASSERT( sizeof(apc_call_t) == 40 );
C_ASSERT( sizeof(apc_param_t) == 8 ); C_ASSERT( sizeof(apc_param_t) == 8 );
...@@ -939,10 +940,9 @@ C_ASSERT( FIELD_OFFSET(struct select_request, cookie) == 16 ); ...@@ -939,10 +940,9 @@ C_ASSERT( FIELD_OFFSET(struct select_request, cookie) == 16 );
C_ASSERT( FIELD_OFFSET(struct select_request, timeout) == 24 ); C_ASSERT( FIELD_OFFSET(struct select_request, timeout) == 24 );
C_ASSERT( FIELD_OFFSET(struct select_request, prev_apc) == 32 ); C_ASSERT( FIELD_OFFSET(struct select_request, prev_apc) == 32 );
C_ASSERT( sizeof(struct select_request) == 40 ); C_ASSERT( sizeof(struct select_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct select_reply, timeout) == 8 ); C_ASSERT( FIELD_OFFSET(struct select_reply, call) == 8 );
C_ASSERT( FIELD_OFFSET(struct select_reply, call) == 16 ); C_ASSERT( FIELD_OFFSET(struct select_reply, apc_handle) == 48 );
C_ASSERT( FIELD_OFFSET(struct select_reply, apc_handle) == 56 ); C_ASSERT( sizeof(struct select_reply) == 56 );
C_ASSERT( sizeof(struct select_reply) == 64 );
C_ASSERT( FIELD_OFFSET(struct create_event_request, access) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_event_request, access) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_event_request, manual_reset) == 16 ); C_ASSERT( FIELD_OFFSET(struct create_event_request, manual_reset) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_event_request, initial_state) == 20 ); C_ASSERT( FIELD_OFFSET(struct create_event_request, initial_state) == 20 );
......
...@@ -79,7 +79,7 @@ struct thread_wait ...@@ -79,7 +79,7 @@ struct thread_wait
enum select_op select; enum select_op select;
client_ptr_t key; /* wait key for keyed events */ client_ptr_t key; /* wait key for keyed events */
client_ptr_t cookie; /* magic cookie to return to client */ client_ptr_t cookie; /* magic cookie to return to client */
timeout_t timeout; abstime_t when;
struct timeout_user *user; struct timeout_user *user;
struct wait_queue_entry queues[1]; struct wait_queue_entry queues[1];
}; };
...@@ -687,7 +687,7 @@ static unsigned int end_wait( struct thread *thread, unsigned int status ) ...@@ -687,7 +687,7 @@ static unsigned int end_wait( struct thread *thread, unsigned int status )
/* build the thread wait structure */ /* build the thread wait structure */
static int wait_on( const select_op_t *select_op, unsigned int count, struct object *objects[], static int wait_on( const select_op_t *select_op, unsigned int count, struct object *objects[],
int flags, timeout_t timeout ) int flags, abstime_t when )
{ {
struct thread_wait *wait; struct thread_wait *wait;
struct wait_queue_entry *entry; struct wait_queue_entry *entry;
...@@ -701,7 +701,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj ...@@ -701,7 +701,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj
wait->select = select_op->op; wait->select = select_op->op;
wait->cookie = 0; wait->cookie = 0;
wait->user = NULL; wait->user = NULL;
wait->timeout = timeout; wait->when = when;
wait->abandoned = 0; wait->abandoned = 0;
current->wait = wait; current->wait = wait;
...@@ -720,7 +720,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj ...@@ -720,7 +720,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj
} }
static int wait_on_handles( const select_op_t *select_op, unsigned int count, const obj_handle_t *handles, static int wait_on_handles( const select_op_t *select_op, unsigned int count, const obj_handle_t *handles,
int flags, timeout_t timeout ) int flags, abstime_t when )
{ {
struct object *objects[MAXIMUM_WAIT_OBJECTS]; struct object *objects[MAXIMUM_WAIT_OBJECTS];
unsigned int i; unsigned int i;
...@@ -732,7 +732,7 @@ static int wait_on_handles( const select_op_t *select_op, unsigned int count, co ...@@ -732,7 +732,7 @@ static int wait_on_handles( const select_op_t *select_op, unsigned int count, co
if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL ))) if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
break; break;
if (i == count) ret = wait_on( select_op, count, objects, flags, timeout ); if (i == count) ret = wait_on( select_op, count, objects, flags, when );
while (i > 0) release_object( objects[--i] ); while (i > 0) release_object( objects[--i] );
return ret; return ret;
...@@ -769,7 +769,8 @@ static int check_wait( struct thread *thread ) ...@@ -769,7 +769,8 @@ static int check_wait( struct thread *thread )
} }
if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC; if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
if (wait->timeout <= current_time) return STATUS_TIMEOUT; if (wait->when >= 0 && wait->when <= current_time) return STATUS_TIMEOUT;
if (wait->when < 0 && -wait->when <= monotonic_time) return STATUS_TIMEOUT;
return -1; return -1;
} }
...@@ -875,19 +876,17 @@ static int signal_object( obj_handle_t handle ) ...@@ -875,19 +876,17 @@ static int signal_object( obj_handle_t handle )
} }
/* select on a list of handles */ /* select on a list of handles */
static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, client_ptr_t cookie, static void select_on( const select_op_t *select_op, data_size_t op_size, client_ptr_t cookie,
int flags, timeout_t timeout ) int flags, abstime_t when )
{ {
int ret; int ret;
unsigned int count; unsigned int count;
struct object *object; struct object *object;
if (timeout <= 0) timeout = current_time - timeout;
switch (select_op->op) switch (select_op->op)
{ {
case SELECT_NONE: case SELECT_NONE:
if (!wait_on( select_op, 0, NULL, flags, timeout )) return timeout; if (!wait_on( select_op, 0, NULL, flags, when )) return;
break; break;
case SELECT_WAIT: case SELECT_WAIT:
...@@ -896,24 +895,24 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c ...@@ -896,24 +895,24 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
if (op_size < offsetof( select_op_t, wait.handles ) || count > MAXIMUM_WAIT_OBJECTS) if (op_size < offsetof( select_op_t, wait.handles ) || count > MAXIMUM_WAIT_OBJECTS)
{ {
set_error( STATUS_INVALID_PARAMETER ); set_error( STATUS_INVALID_PARAMETER );
return 0; return;
} }
if (!wait_on_handles( select_op, count, select_op->wait.handles, flags, timeout )) if (!wait_on_handles( select_op, count, select_op->wait.handles, flags, when ))
return timeout; return;
break; break;
case SELECT_SIGNAL_AND_WAIT: case SELECT_SIGNAL_AND_WAIT:
if (!wait_on_handles( select_op, 1, &select_op->signal_and_wait.wait, flags, timeout )) if (!wait_on_handles( select_op, 1, &select_op->signal_and_wait.wait, flags, when ))
return timeout; return;
if (select_op->signal_and_wait.signal) if (select_op->signal_and_wait.signal)
{ {
if (!signal_object( select_op->signal_and_wait.signal )) if (!signal_object( select_op->signal_and_wait.signal ))
{ {
end_wait( current, get_error() ); end_wait( current, get_error() );
return timeout; return;
} }
/* check if we woke ourselves up */ /* check if we woke ourselves up */
if (!current->wait) return timeout; if (!current->wait) return;
} }
break; break;
...@@ -921,38 +920,38 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c ...@@ -921,38 +920,38 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
case SELECT_KEYED_EVENT_RELEASE: case SELECT_KEYED_EVENT_RELEASE:
object = (struct object *)get_keyed_event_obj( current->process, select_op->keyed_event.handle, object = (struct object *)get_keyed_event_obj( current->process, select_op->keyed_event.handle,
select_op->op == SELECT_KEYED_EVENT_WAIT ? KEYEDEVENT_WAIT : KEYEDEVENT_WAKE ); select_op->op == SELECT_KEYED_EVENT_WAIT ? KEYEDEVENT_WAIT : KEYEDEVENT_WAKE );
if (!object) return timeout; if (!object) return;
ret = wait_on( select_op, 1, &object, flags, timeout ); ret = wait_on( select_op, 1, &object, flags, when );
release_object( object ); release_object( object );
if (!ret) return timeout; if (!ret) return;
current->wait->key = select_op->keyed_event.key; current->wait->key = select_op->keyed_event.key;
break; break;
default: default:
set_error( STATUS_INVALID_PARAMETER ); set_error( STATUS_INVALID_PARAMETER );
return 0; return;
} }
if ((ret = check_wait( current )) != -1) if ((ret = check_wait( current )) != -1)
{ {
/* condition is already satisfied */ /* condition is already satisfied */
set_error( end_wait( current, ret )); set_error( end_wait( current, ret ));
return timeout; return;
} }
/* now we need to wait */ /* now we need to wait */
if (current->wait->timeout != TIMEOUT_INFINITE) if (current->wait->when != TIMEOUT_INFINITE)
{ {
if (!(current->wait->user = add_timeout_user( current->wait->timeout, if (!(current->wait->user = add_timeout_user( abstime_to_timeout(current->wait->when),
thread_timeout, current->wait ))) thread_timeout, current->wait )))
{ {
end_wait( current, get_error() ); end_wait( current, get_error() );
return timeout; return;
} }
} }
current->wait->cookie = cookie; current->wait->cookie = cookie;
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return timeout; return;
} }
/* attempt to wake threads sleeping on the object wait queue */ /* attempt to wake threads sleeping on the object wait queue */
...@@ -1577,7 +1576,7 @@ DECL_HANDLER(select) ...@@ -1577,7 +1576,7 @@ DECL_HANDLER(select)
release_object( apc ); release_object( apc );
} }
reply->timeout = select_on( &select_op, op_size, req->cookie, req->flags, req->timeout ); select_on( &select_op, op_size, req->cookie, req->flags, req->timeout );
while (get_error() == STATUS_USER_APC) while (get_error() == STATUS_USER_APC)
{ {
......
...@@ -88,6 +88,12 @@ static void dump_timeout( const char *prefix, const timeout_t *time ) ...@@ -88,6 +88,12 @@ static void dump_timeout( const char *prefix, const timeout_t *time )
fprintf( stderr, "%s%s", prefix, get_timeout_str(*time) ); fprintf( stderr, "%s%s", prefix, get_timeout_str(*time) );
} }
static void dump_abstime( const char *prefix, const abstime_t *when )
{
timeout_t timeout = abstime_to_timeout( *when );
dump_timeout( prefix, &timeout );
}
static void dump_uint64( const char *prefix, const unsigned __int64 *val ) static void dump_uint64( const char *prefix, const unsigned __int64 *val )
{ {
if ((unsigned int)*val != *val) if ((unsigned int)*val != *val)
...@@ -1581,7 +1587,7 @@ static void dump_select_request( const struct select_request *req ) ...@@ -1581,7 +1587,7 @@ static void dump_select_request( const struct select_request *req )
{ {
fprintf( stderr, " flags=%d", req->flags ); fprintf( stderr, " flags=%d", req->flags );
dump_uint64( ", cookie=", &req->cookie ); dump_uint64( ", cookie=", &req->cookie );
dump_timeout( ", timeout=", &req->timeout ); dump_abstime( ", timeout=", &req->timeout );
fprintf( stderr, ", prev_apc=%04x", req->prev_apc ); fprintf( stderr, ", prev_apc=%04x", req->prev_apc );
dump_varargs_apc_result( ", result=", cur_size ); dump_varargs_apc_result( ", result=", cur_size );
dump_varargs_select_op( ", data=", cur_size ); dump_varargs_select_op( ", data=", cur_size );
...@@ -1589,8 +1595,7 @@ static void dump_select_request( const struct select_request *req ) ...@@ -1589,8 +1595,7 @@ static void dump_select_request( const struct select_request *req )
static void dump_select_reply( const struct select_reply *req ) static void dump_select_reply( const struct select_reply *req )
{ {
dump_timeout( " timeout=", &req->timeout ); dump_apc_call( " call=", &req->call );
dump_apc_call( ", call=", &req->call );
fprintf( stderr, ", apc_handle=%04x", req->apc_handle ); fprintf( stderr, ", apc_handle=%04x", req->apc_handle );
} }
......
...@@ -43,6 +43,7 @@ my %formats = ...@@ -43,6 +43,7 @@ my %formats =
"mem_size_t" => [ 8, 8, "&dump_uint64" ], "mem_size_t" => [ 8, 8, "&dump_uint64" ],
"affinity_t" => [ 8, 8, "&dump_uint64" ], "affinity_t" => [ 8, 8, "&dump_uint64" ],
"timeout_t" => [ 8, 8, "&dump_timeout" ], "timeout_t" => [ 8, 8, "&dump_timeout" ],
"abstime_t" => [ 8, 8, "&dump_abstime" ],
"rectangle_t" => [ 16, 4, "&dump_rectangle" ], "rectangle_t" => [ 16, 4, "&dump_rectangle" ],
"char_info_t" => [ 4, 2, "&dump_char_info" ], "char_info_t" => [ 4, 2, "&dump_char_info" ],
"apc_call_t" => [ 40, 8, "&dump_apc_call" ], "apc_call_t" => [ 40, 8, "&dump_apc_call" ],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment