[RFC PATCH 07/11] ntdll: Make server_select and server_wait accept extra "inline_apc" argument.
Jinoh Kang
jinoh.kang.kr at gmail.com
Sat Jan 22 07:00:11 CST 2022
If the "inline_apc" argument is specified, the function will first
invoke the APC specified by "inline_apc" and return the result to the
wineserver. This is done as a single server call along with the actual
wait, saving a round trip to the server.
Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
Notes:
The alternative approach (adding a select_op) is less intrusive since we
don't have to modify all callers of server_wait() and server_select().
dlls/ntdll/unix/server.c | 16 +++++++++++-----
dlls/ntdll/unix/sync.c | 10 +++++-----
dlls/ntdll/unix/thread.c | 4 ++--
dlls/ntdll/unix/unix_private.h | 5 +++--
4 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 9d0594d3374..5960559c976 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -585,7 +585,8 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
* server_select
*/
unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
- timeout_t abs_timeout, context_t *context, user_apc_t *user_apc )
+ timeout_t abs_timeout, context_t *context, user_apc_t *user_apc,
+ const inline_apc_t *inline_apc )
{
unsigned int ret;
int cookie;
@@ -601,6 +602,11 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
do
{
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
+ if (inline_apc && (apc_handle = inline_apc->apc_handle))
+ {
+ invoke_system_apc( &inline_apc->call, &result, FALSE );
+ inline_apc = NULL;
+ }
for (;;)
{
SERVER_START_REQ( select )
@@ -649,7 +655,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
* server_wait
*/
unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags,
- const LARGE_INTEGER *timeout )
+ const LARGE_INTEGER *timeout, const inline_apc_t *inline_apc )
{
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
unsigned int ret;
@@ -663,7 +669,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
abs_timeout -= now.QuadPart;
}
- ret = server_select( select_op, size, flags, abs_timeout, NULL, &apc );
+ ret = server_select( select_op, size, flags, abs_timeout, NULL, &apc, inline_apc );
if (ret == STATUS_USER_APC) return invoke_user_apc( NULL, &apc, ret );
/* A test on Windows 2000 shows that Windows always yields during
@@ -684,7 +690,7 @@ NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
if (alertable)
{
- status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc );
+ status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc, NULL );
if (status == STATUS_USER_APC) return invoke_user_apc( context, &apc, status );
}
return signal_set_full_context( context );
@@ -699,7 +705,7 @@ NTSTATUS WINAPI NtTestAlert(void)
user_apc_t apc;
NTSTATUS status;
- status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc );
+ status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc, NULL );
if (status == STATUS_USER_APC) invoke_user_apc( NULL, &apc, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 442243d8bcf..8fe1e1145e7 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -1406,7 +1406,7 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
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_wait( &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, NULL );
}
@@ -1434,7 +1434,7 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait,
select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT;
select_op.signal_and_wait.wait = wine_server_obj_handle( wait );
select_op.signal_and_wait.signal = wine_server_obj_handle( signal );
- return server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout );
+ return server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout, NULL );
}
@@ -1458,7 +1458,7 @@ NTSTATUS WINAPI NtYieldExecution(void)
NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout )
{
/* if alertable, we need to query the server */
- if (alertable) return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout );
+ if (alertable) return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout, NULL );
if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */
{
@@ -1703,7 +1703,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_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
+ return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout, NULL );
}
@@ -1722,7 +1722,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_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
+ return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout, NULL );
}
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
index 618ebb82bfb..5571085c2e2 100644
--- a/dlls/ntdll/unix/thread.c
+++ b/dlls/ntdll/unix/thread.c
@@ -1434,7 +1434,7 @@ void wait_suspend( CONTEXT *context )
contexts_to_server( server_contexts, context );
/* wait with 0 timeout, will only return once the thread is no longer suspended */
- server_select( NULL, 0, SELECT_INTERRUPTIBLE, 0, server_contexts, NULL );
+ server_select( NULL, 0, SELECT_INTERRUPTIBLE, 0, server_contexts, NULL, NULL );
contexts_from_server( context, server_contexts );
errno = saved_errno;
}
@@ -1483,7 +1483,7 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c
contexts_to_server( server_contexts, context );
server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE,
- TIMEOUT_INFINITE, server_contexts, NULL );
+ TIMEOUT_INFINITE, server_contexts, NULL, NULL );
SERVER_START_REQ( get_exception_status )
{
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index a79edabc37c..fc7ae671314 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -161,9 +161,10 @@ extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ) DECLSPEC_HIDDEN;
extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, 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, context_t *context, user_apc_t *user_apc ) DECLSPEC_HIDDEN;
+ timeout_t abs_timeout, context_t *context, user_apc_t *user_apc,
+ const inline_apc_t *inline_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;
+ const LARGE_INTEGER *timeout, const inline_apc_t *inline_apc ) 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_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
--
2.31.1
More information about the wine-devel
mailing list