Zebediah Figura : ntdll: Call the select request directly in RtlWaitOnAddress().

Alexandre Julliard julliard at winehq.org
Tue Dec 4 16:33:55 CST 2018


Module: wine
Branch: master
Commit: 0ea963a4063395a7a4611b435eb74b5cf0830116
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=0ea963a4063395a7a4611b435eb74b5cf0830116

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Fri Nov 30 19:03:56 2018 -0600

ntdll: Call the select request directly in RtlWaitOnAddress().

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/ntdll_misc.h |  2 ++
 dlls/ntdll/server.c     |  4 +--
 dlls/ntdll/sync.c       | 86 +++++++++++++++++++++++++++++++++++++------------
 3 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index fdb443b..1630978 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -104,6 +104,8 @@ extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
 extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
                                          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 BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN;
 
 /* module handling */
 extern LIST_ENTRY tls_links DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index ec03445..38356f4 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -349,7 +349,7 @@ void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sig
  *
  * Wait for a reply on the waiting pipe of the current thread.
  */
-static int wait_select_reply( void *cookie )
+int wait_select_reply( void *cookie )
 {
     int signaled;
     struct wake_up_reply reply;
@@ -386,7 +386,7 @@ static int wait_select_reply( void *cookie )
  *
  * Invoke a single APC. Return TRUE if a user APC has been run.
  */
-static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
+BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
 {
     BOOL user_apc = FALSE;
     SIZE_T size;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 0c373a4..e1a48d7 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -1961,35 +1961,81 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
     return status;
 }
 
-/***********************************************************************
- *           RtlWaitOnAddress   (NTDLL.@)
- */
-NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
-                                  const LARGE_INTEGER *timeout )
+static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
 {
     switch (size)
     {
         case 1:
-            if (*(const UCHAR *)addr != *(const UCHAR *)cmp)
-                return STATUS_SUCCESS;
-            break;
+            return (*(const UCHAR *)addr == *(const UCHAR *)cmp);
         case 2:
-            if (*(const USHORT *)addr != *(const USHORT *)cmp)
-                return STATUS_SUCCESS;
-            break;
+            return (*(const USHORT *)addr == *(const USHORT *)cmp);
         case 4:
-            if (*(const ULONG *)addr != *(const ULONG *)cmp)
-                return STATUS_SUCCESS;
-            break;
+            return (*(const ULONG *)addr == *(const ULONG *)cmp);
         case 8:
-            if (*(const ULONG64 *)addr != *(const ULONG64 *)cmp)
-                return STATUS_SUCCESS;
-            break;
-        default:
-            return STATUS_INVALID_PARAMETER;
+            return (*(const ULONG64 *)addr == *(const ULONG64 *)cmp);
     }
 
-    return NtWaitForKeyedEvent( 0, addr, 0, timeout );
+    return FALSE;
+}
+
+/***********************************************************************
+ *           RtlWaitOnAddress   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
+                                  const LARGE_INTEGER *timeout )
+{
+    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;
+
+    if (size != 1 && size != 2 && size != 4 && size != 8)
+        return STATUS_INVALID_PARAMETER;
+
+    select_op.keyed_event.op     = SELECT_KEYED_EVENT_WAIT;
+    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) );
+
+    for (;;)
+    {
+        if (!compare_addr( addr, cmp, size ))
+            return STATUS_SUCCESS;
+
+        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 = wine_server_call( req );
+            abs_timeout = reply->timeout;
+            apc_handle  = reply->apc_handle;
+            call        = reply->call;
+        }
+        SERVER_END_REQ;
+        if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie );
+        if (ret != STATUS_USER_APC) break;
+        if (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_TIMEOUT && user_apc) ret = STATUS_USER_APC;
+
+    return ret;
 }
 
 /***********************************************************************




More information about the wine-cvs mailing list