From: Jacek Caban Subject: [PATCH 2/5] ntdll: Factor out server_select. Message-Id: <9780187b-f2ae-2aed-b6c1-1a695c7f1066@codeweavers.com> Date: Wed, 8 Apr 2020 20:27:07 +0200 Signed-off-by: Jacek Caban --- dlls/ntdll/critsection.c | 2 +- dlls/ntdll/exception.c | 4 +-- dlls/ntdll/ntdll_misc.h | 4 +-- dlls/ntdll/server.c | 55 +++++++++++++++++++++++++++------------- dlls/ntdll/sync.c | 10 ++++---- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c index e8ffc1ceed..1892d3abcb 100644 --- a/dlls/ntdll/critsection.c +++ b/dlls/ntdll/critsection.c @@ -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; } diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index c35312fd1d..7bd7baa135 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -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 ) { diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index a5fe98c8d8..46473beaaf 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -105,8 +105,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, diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index dc9e5ea165..1e7fcb30cb 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -606,15 +606,13 @@ 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; - timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE; sigset_t old_set; memset( &result, 0, sizeof(result) ); @@ -639,29 +637,52 @@ 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; + + 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 diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 2b5b6ce44a..d5fb3c3411 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1084,7 +1084,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 ); } @@ -1123,7 +1123,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 ); } @@ -1148,7 +1148,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 */ { @@ -1247,7 +1247,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 ); } /****************************************************************************** @@ -1265,7 +1265,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 ); } /******************************************************************