[RFC PATCH v2 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 08:36:48 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