Jacek Caban : server: Return async result directly instead of via APCs if it's available.
Alexandre Julliard
julliard at winehq.org
Wed Jun 28 15:10:25 CDT 2017
Module: wine
Branch: master
Commit: 879d46e45644147a14269bf46829b44c2a374ad3
URL: http://source.winehq.org/git/wine.git/?a=commit;h=879d46e45644147a14269bf46829b44c2a374ad3
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Jun 26 12:18:08 2017 +0200
server: Return async result directly instead of via APCs if it's available.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/file.c | 5 ++++
server/async.c | 76 +++++++++++++++++++++++++++++++++++++------------------
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 5329c79..3d9840f 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -580,6 +580,11 @@ static NTSTATUS server_read_file( HANDLE handle, HANDLE event, PIO_APC_ROUTINE a
status = wine_server_call( req );
wait_handle = wine_server_ptr_handle( reply->wait );
options = reply->options;
+ if (wait_handle && status != STATUS_PENDING)
+ {
+ io->u.Status = status;
+ io->Information = wine_server_reply_size( reply );
+ }
}
SERVER_END_REQ;
diff --git a/server/async.c b/server/async.c
index f50cdc5..7f2bcf5 100644
--- a/server/async.c
+++ b/server/async.c
@@ -49,6 +49,7 @@ struct async
async_data_t data; /* data for async I/O call */
struct iosb *iosb; /* I/O status block */
obj_handle_t wait_handle; /* pre-allocated wait handle */
+ int direct_result; /* a flag if we're passing result directly from request instead of APC */
};
static void async_dump( struct object *obj, int verbose );
@@ -138,6 +139,12 @@ static void async_satisfied( struct object *obj, struct wait_queue_entry *entry
struct async *async = (struct async *)obj;
assert( obj->ops == &async_ops );
+ if (async->direct_result)
+ {
+ async_set_result( &async->obj, async->iosb->status, async->iosb->result );
+ async->direct_result = 0;
+ }
+
/* close wait handle here to avoid extra server round trip */
if (async->wait_handle)
{
@@ -195,18 +202,21 @@ void async_terminate( struct async *async, unsigned int status )
async->status = status;
if (async->iosb && async->iosb->status == STATUS_PENDING) async->iosb->status = status;
- if (async->data.user)
+ if (!async->direct_result)
{
- apc_call_t data;
-
- memset( &data, 0, sizeof(data) );
- data.type = APC_ASYNC_IO;
- data.async_io.user = async->data.user;
- data.async_io.sb = async->data.iosb;
- data.async_io.status = status;
- thread_queue_apc( async->thread, &async->obj, &data );
+ if (async->data.user)
+ {
+ apc_call_t data;
+
+ memset( &data, 0, sizeof(data) );
+ data.type = APC_ASYNC_IO;
+ data.async_io.user = async->data.user;
+ data.async_io.sb = async->data.iosb;
+ data.async_io.status = status;
+ thread_queue_apc( async->thread, &async->obj, &data );
+ }
+ else async_set_result( &async->obj, STATUS_SUCCESS, 0 );
}
- else async_set_result( &async->obj, STATUS_SUCCESS, 0 );
async_reselect( async );
if (async->queue) release_object( async ); /* so that it gets destroyed when the async is done */
@@ -270,14 +280,15 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
return NULL;
}
- async->thread = (struct thread *)grab_object( thread );
- async->event = event;
- async->status = STATUS_PENDING;
- async->data = *data;
- async->timeout = NULL;
- async->queue = NULL;
- async->signaled = 0;
- async->wait_handle = 0;
+ async->thread = (struct thread *)grab_object( thread );
+ async->event = event;
+ async->status = STATUS_PENDING;
+ async->data = *data;
+ async->timeout = NULL;
+ async->queue = NULL;
+ async->signaled = 0;
+ async->wait_handle = 0;
+ async->direct_result = 0;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
else async->iosb = NULL;
@@ -307,6 +318,7 @@ struct async *create_request_async( struct thread *thread, const async_data_t *d
release_object( async );
return NULL;
}
+ async->direct_result = 1;
}
return async;
}
@@ -321,12 +333,25 @@ obj_handle_t async_handoff( struct async *async, int success )
return 0;
}
- if (async->iosb->status == STATUS_PENDING && !async_is_blocking( async ))
+ if (async->iosb->status != STATUS_PENDING)
{
- close_handle( async->thread->process, async->wait_handle);
- async->wait_handle = 0;
+ if (async->iosb->out_data)
+ {
+ set_reply_data_ptr( async->iosb->out_data, async->iosb->out_size );
+ async->iosb->out_data = NULL;
+ }
+ async->signaled = 1;
+ }
+ else
+ {
+ async->direct_result = 0;
+ if (!async_is_blocking( async ))
+ {
+ close_handle( async->thread->process, async->wait_handle);
+ async->wait_handle = 0;
+ }
}
- set_error( STATUS_PENDING );
+ set_error( async->iosb->status );
return async->wait_handle;
}
@@ -399,8 +424,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
}
if (async->event) set_event( async->event );
else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
- async->signaled = 1;
- wake_up( &async->obj, 0 );
+ if (!async->signaled)
+ {
+ async->signaled = 1;
+ wake_up( &async->obj, 0 );
+ }
}
}
More information about the wine-cvs
mailing list