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