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@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,