ntdll: Factor out server_select.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2020-04-10 01:05:19 +02:00 committed by Alexandre Julliard
parent 4f9cc93108
commit 8701260768
5 changed files with 56 additions and 35 deletions

View File

@ -242,7 +242,7 @@ static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
time.QuadPart = timeout * (LONGLONG)-10000000;
select_op.wait.op = SELECT_WAIT;
select_op.wait.handles[0] = wine_server_obj_handle( sem );
ret = server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), 0, &time );
ret = server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), 0, &time );
}
return ret;
}

View File

@ -128,7 +128,7 @@ void wait_suspend( CONTEXT *context )
/* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout.QuadPart = 0;
server_select( NULL, 0, SELECT_INTERRUPTIBLE, &timeout );
server_wait( NULL, 0, SELECT_INTERRUPTIBLE, &timeout );
/* retrieve the new context */
SERVER_START_REQ( get_suspend_context )
@ -185,7 +185,7 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *con
select_op.wait.op = SELECT_WAIT;
select_op.wait.handles[0] = handle;
server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE, NULL );
server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE, NULL );
SERVER_START_REQ( get_exception_status )
{

View File

@ -116,8 +116,8 @@ extern sigset_t server_block_set DECLSPEC_HIDDEN;
extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
extern unsigned int server_select( const select_op_t *select_op, data_size_t size,
UINT flags, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size,
UINT flags, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
extern int server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN;
extern int server_get_unix_fd( HANDLE handle, unsigned int access, int *unix_fd,

View File

@ -606,27 +606,17 @@ void invoke_apc( const apc_call_t *call, apc_result_t *result )
* server_select
*/
unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
const LARGE_INTEGER *timeout )
timeout_t abs_timeout, user_apc_t *user_apc )
{
unsigned int ret;
int cookie;
BOOL user_apc = FALSE;
obj_handle_t apc_handle = 0;
apc_call_t call;
apc_result_t result;
abstime_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
sigset_t old_set;
memset( &result, 0, sizeof(result) );
if (abs_timeout < 0)
{
LARGE_INTEGER now;
RtlQueryPerformanceCounter(&now);
abs_timeout -= now.QuadPart;
}
do
{
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
@ -646,29 +636,60 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
}
SERVER_END_REQ;
if (ret != STATUS_KERNEL_APC) break;
invoke_apc( &call, &result );
/* don't signal multiple times */
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
size = offsetof( select_op_t, signal_and_wait.signal );
if (ret != STATUS_KERNEL_APC) break;
invoke_apc( &call, &result );
}
pthread_sigmask( SIG_SETMASK, &old_set, NULL );
if (ret != STATUS_PENDING) break;
if (ret == STATUS_USER_APC)
{
invoke_apc( &call, &result );
/* if we ran a user apc we have to check once more if additional apcs are queued,
* but we don't want to wait */
abs_timeout = 0;
user_apc = TRUE;
size = 0;
}
if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie );
ret = wait_select_reply( &cookie );
}
while (ret == STATUS_USER_APC || ret == STATUS_KERNEL_APC);
if (ret == STATUS_USER_APC) *user_apc = call.user;
return ret;
}
/***********************************************************************
* server_wait
*/
unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags,
const LARGE_INTEGER *timeout )
{
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
BOOL user_apc = FALSE;
unsigned int ret;
user_apc_t apc;
if (abs_timeout < 0)
{
LARGE_INTEGER now;
RtlQueryPerformanceCounter(&now);
abs_timeout -= now.QuadPart;
}
for (;;)
{
ret = server_select( select_op, size, flags, abs_timeout, &apc );
if (ret != STATUS_USER_APC) break;
invoke_user_apc( &apc );
/* if we ran a user apc we have to check once more if additional apcs are queued,
* but we don't want to wait */
abs_timeout = 0;
user_apc = TRUE;
size = 0;
/* don't signal multiple times */
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
size = offsetof( select_op_t, signal_and_wait.signal );
}
if (ret == STATUS_TIMEOUT && user_apc) ret = STATUS_USER_APC;
/* A test on Windows 2000 shows that Windows always yields during

View File

@ -1091,7 +1091,7 @@ static NTSTATUS wait_objects( DWORD count, const HANDLE *handles,
if (alertable) flags |= SELECT_ALERTABLE;
select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
return server_select( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout );
return server_wait( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout );
}
@ -1130,7 +1130,7 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWa
select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT;
select_op.signal_and_wait.wait = wine_server_obj_handle( hWaitObject );
select_op.signal_and_wait.signal = wine_server_obj_handle( hSignalObject );
return server_select( &select_op, sizeof(select_op.signal_and_wait), flags, timeout );
return server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout );
}
@ -1155,7 +1155,7 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou
{
/* if alertable, we need to query the server */
if (alertable)
return server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout );
return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout );
if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */
{
@ -1254,7 +1254,7 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key,
select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT;
select_op.keyed_event.handle = wine_server_obj_handle( handle );
select_op.keyed_event.key = wine_server_client_ptr( key );
return server_select( &select_op, sizeof(select_op.keyed_event), flags, timeout );
return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
}
/******************************************************************************
@ -1272,7 +1272,7 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key,
select_op.keyed_event.op = SELECT_KEYED_EVENT_RELEASE;
select_op.keyed_event.handle = wine_server_obj_handle( handle );
select_op.keyed_event.key = wine_server_client_ptr( key );
return server_select( &select_op, sizeof(select_op.keyed_event), flags, timeout );
return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
}
/******************************************************************