[RFC PATCH 2/6] server: Allow setting async result directly from Unix side.

Jinoh Kang jinoh.kang.kr at gmail.com
Sun Jan 23 11:29:55 CST 2022


Some I/O operations need a way to "queue" the async to the target object
first, even if the operation itself is to be completed synchronously.
After synchronous completion, it needs a way to notify the
IO_STATUS_BLOCK values back to the server.

Add a new wineserver request, "notify_async_direct_result", which
notifies direct (i.e. synchronous) completion of async from the same
thread.

Wrap the "notify_async_direct_result" request in a function named
"notify_async", which is no-op if the supplied wait handle is NULL.

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
 server/async.c      | 48 ++++++++++++++++++++++++++++++++++-----------
 server/protocol.def |  8 ++++++++
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/server/async.c b/server/async.c
index 2a67892dbe2..9b08c139929 100644
--- a/server/async.c
+++ b/server/async.c
@@ -135,11 +135,8 @@ static int async_signaled( struct object *obj, struct wait_queue_entry *entry )
     return async->signaled;
 }
 
-static void async_satisfied( struct object *obj, struct wait_queue_entry *entry )
+static void async_set_direct_result( struct async *async )
 {
-    struct async *async = (struct async *)obj;
-    assert( obj->ops == &async_ops );
-
     /* we only return an async handle for asyncs created via create_request_async() */
     assert( async->iosb );
 
@@ -149,18 +146,26 @@ static void async_satisfied( struct object *obj, struct wait_queue_entry *entry
         async->direct_result = 0;
     }
 
+    /* close wait handle here to avoid extra server round trip */
+    if (async->wait_handle)
+    {
+        close_handle( async->thread->process, async->wait_handle );
+        async->wait_handle = 0;
+    }
+}
+
+static void async_satisfied( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct async *async = (struct async *)obj;
+    assert( obj->ops == &async_ops );
+
+    async_set_direct_result( async );
+
     if ((async->initial_status == STATUS_PENDING && async->blocking) ||
         async->initial_status == STATUS_ALERTED)
         set_wait_status( entry, async->iosb->status );
     else
         set_wait_status( entry, async->initial_status );
-
-    /* close wait handle here to avoid extra server round trip */
-    if (async->wait_handle)
-    {
-        close_handle( async->thread->process, async->wait_handle );
-        async->wait_handle = 0;
-    }
 }
 
 static void async_destroy( struct object *obj )
@@ -752,3 +757,24 @@ DECL_HANDLER(get_async_result)
     }
     set_error( iosb->status );
 }
+
+/* Notify direct completion of async and close the wait handle */
+DECL_HANDLER(notify_async_direct_result)
+{
+    struct async *async = (struct async *)get_handle_obj( current->process, req->handle, 0, &async_ops );
+    unsigned int status;
+
+    if (!async) return;
+
+    if (async->iosb)
+    {
+        async->iosb->status = req->status;
+        async->iosb->result = req->information;
+        async_set_direct_result( async );
+        status = req->status;
+    }
+    else status = STATUS_ACCESS_DENIED;
+
+    release_object( &async->obj );
+    set_error( status );
+}
diff --git a/server/protocol.def b/server/protocol.def
index db73f0418a9..c4596e0bd58 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2147,6 +2147,14 @@ enum message_type
 @END
 
 
+/* Notify direct completion of async and close the wait handle */
+ at REQ(notify_async_direct_result)
+    obj_handle_t   handle;        /* wait handle */
+    unsigned int   status;        /* completion status */
+    apc_param_t    information;   /* IO_STATUS_BLOCK Information */
+ at END
+
+
 /* Perform a read on a file object */
 @REQ(read)
     async_data_t   async;         /* async I/O parameters */
-- 
2.31.1




More information about the wine-devel mailing list