[RFC PATCH v5 1/5] server: Allow calling async_handoff() with status code STATUS_ALERTED.

Jinoh Kang jinoh.kang.kr at gmail.com
Fri Feb 4 14:51:52 CST 2022


If the server detects that an I/O request could be completed immediately
(e.g. the socket to read from already has incoming data), it can now
return STATUS_ALERTED to allow opportunistic synchronous I/O.  The Unix
side will then attempt to perform I/O in nonblocking mode and report
back the I/O status to the server.  If the operation returns e.g. EAGAIN
or EWOULDBLOCK, the client can opt to either abandon the request (by
specifying an error status) or poll for it in the server as usual (by
waiting on the wait handle).

Without such mechanism in place, the client cannot safely perform
immediately satiable I/O operations synchronously, since it can
potentially conflict with other pending I/O operations that have already
been queued.

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---

Notes:
    REVIEWERS: The mention of the set_async_direct_result request comes in
    the next patch where it is introduced.
    
    v2 -> v3: set async->alerted = 1
    v3 -> v4: unchanged
    v4 -> v5:
    - edit comments
    - remove irrelevant word in commit message (signal_wait_async)
    - async_handoff(): don't check for async->pending in new code path
    - async_handoff(): use async_terminate() directly in new code path

 server/async.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/server/async.c b/server/async.c
index 7aef28355f0..97b3b9fc10a 100644
--- a/server/async.c
+++ b/server/async.c
@@ -338,6 +338,30 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_
         return async->wait_handle;
     }
 
+    if (get_error() == STATUS_ALERTED)
+    {
+        /* give the client opportunity to complete synchronously.  after the
+         * client performs the I/O, it reports the result back to the server.
+         * if it turns out that the I/O request is not actually immediately
+         * satiable, the client may then choose to re-queue the async by
+         * reporting STATUS_PENDING instead.
+         *
+         * since we're deferring the initial I/O (to the client), we mark the
+         * async as having unknown initial status (unknown_status = 1).  Note
+         * that we don't reuse async_set_unknown_status() here.  This is because
+         * the one responsible for performing the I/O is not the device driver,
+         * but instead the client that requested the I/O in the first place.
+         *
+         * also, async_set_unknown_status() would set direct_result to zero
+         * forcing APC_ASYNC_IO to fire in async_terminate(), which is not
+         * useful due to subtle semantic differences between synchronous and
+         * asynchronous completion.
+         */
+        async->unknown_status = 1;
+        async_terminate( async, STATUS_ALERTED );
+        return async->wait_handle;
+    }
+
     async->initial_status = get_error();
 
     if (!async->pending && NT_ERROR( get_error() ))
-- 
2.34.1




More information about the wine-devel mailing list