From: Jacek Caban Subject: [PATCH 3/5] ntdll: Use server_select in RtlWaitOnAddress. Message-Id: <8ee06ad2-5eca-7772-af74-203c36f1f930@codeweavers.com> Date: Wed, 8 Apr 2020 20:27:56 +0200 Signed-off-by: Jacek Caban --- dlls/ntdll/ntdll_misc.h | 4 ++- dlls/ntdll/server.c | 14 ++++------ dlls/ntdll/sync.c | 58 ++++++++--------------------------------- 3 files changed, 19 insertions(+), 57 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 46473beaaf..cdfc22d3b5 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -105,6 +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, + timeout_t abs_timeout, user_apc_t *user_apc ) 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; @@ -116,7 +118,7 @@ extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct o data_size_t *ret_len ) DECLSPEC_HIDDEN; extern NTSTATUS validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; extern int wait_select_reply( void *cookie ) DECLSPEC_HIDDEN; -extern void invoke_apc( const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN; +extern void invoke_apc( const user_apc_t *apc ) DECLSPEC_HIDDEN; /* module handling */ extern LIST_ENTRY tls_links DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 1e7fcb30cb..28977c4892 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -381,7 +381,7 @@ int wait_select_reply( void *cookie ) } -static void invoke_user_apc( const user_apc_t *apc ) +void invoke_apc( const user_apc_t *apc ) { switch( apc->type ) { @@ -410,7 +410,7 @@ static void invoke_user_apc( const user_apc_t *apc ) * Invoke a single APC. * */ -void invoke_apc( const apc_call_t *call, apc_result_t *result ) +static void invoke_system_apc( const apc_call_t *call, apc_result_t *result ) { SIZE_T size; void *addr; @@ -422,10 +422,6 @@ void invoke_apc( const apc_call_t *call, apc_result_t *result ) { case APC_NONE: break; - case APC_USER: - case APC_TIMER: - invoke_user_apc( &call->user ); - break; case APC_ASYNC_IO: { IO_STATUS_BLOCK *iosb = wine_server_get_ptr( call->async_io.sb ); @@ -638,7 +634,7 @@ 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 ); + invoke_system_apc( &call, &result ); /* don't signal multiple times */ if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT) @@ -671,7 +667,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f { ret = server_select( select_op, size, flags, abs_timeout, &apc ); if (ret != STATUS_USER_APC) break; - invoke_user_apc( &apc ); + invoke_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 */ @@ -720,7 +716,7 @@ unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, a if (self) { - invoke_apc( call, result ); + invoke_system_apc( call, result ); } else { diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index d5fb3c3411..ee2c818507 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -2451,13 +2451,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size { select_op_t select_op; NTSTATUS 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; + user_apc_t apc; if (size != 1 && size != 2 && size != 4 && size != 8) return STATUS_INVALID_PARAMETER; @@ -2469,57 +2465,25 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size select_op.keyed_event.handle = wine_server_obj_handle( keyed_event ); select_op.keyed_event.key = wine_server_client_ptr( addr ); - memset( &result, 0, sizeof(result) ); - - do + for (;;) { RtlEnterCriticalSection( &addr_section ); if (!compare_addr( addr, cmp, size )) - { - RtlLeaveCriticalSection( &addr_section ); - return STATUS_SUCCESS; - } - - pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set ); - for (;;) - { - SERVER_START_REQ( select ) - { - req->flags = SELECT_INTERRUPTIBLE; - req->cookie = wine_server_client_ptr( &cookie ); - req->prev_apc = apc_handle; - req->timeout = abs_timeout; - wine_server_add_data( req, &result, sizeof(result) ); - wine_server_add_data( req, &select_op, sizeof(select_op.keyed_event) ); - ret = server_call_unlocked( req ); - abs_timeout = reply->timeout; - apc_handle = reply->apc_handle; - call = reply->call; - } - SERVER_END_REQ; - - if (ret != STATUS_KERNEL_APC) break; - invoke_apc( &call, &result ); - } - pthread_sigmask( SIG_SETMASK, &old_set, NULL ); - + ret = STATUS_SUCCESS; + else + ret = server_select( &select_op, sizeof(select_op.keyed_event), SELECT_INTERRUPTIBLE, abs_timeout, &apc ); RtlLeaveCriticalSection( &addr_section ); - 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; - } + if (ret != STATUS_USER_APC) break; - if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie ); + invoke_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; } - while (ret == STATUS_USER_APC || ret == STATUS_KERNEL_APC); if (ret == STATUS_TIMEOUT && user_apc) ret = STATUS_USER_APC; - return ret; }