Jacek Caban : server: Store fd reference in async object for unqueued asyncs.
Alexandre Julliard
julliard at winehq.org
Wed Jun 28 15:10:25 CDT 2017
Module: wine
Branch: master
Commit: fa0dfe5967087edf5e9f77975dc1ad5e0e01a963
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fa0dfe5967087edf5e9f77975dc1ad5e0e01a963
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Jun 26 12:19:28 2017 +0200
server: Store fd reference in async object for unqueued asyncs.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
server/async.c | 35 +++++++++++++++++++++++------------
server/change.c | 2 +-
server/fd.c | 10 +++++-----
server/file.h | 4 ++--
4 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/server/async.c b/server/async.c
index b693c28..409c9b5 100644
--- a/server/async.c
+++ b/server/async.c
@@ -41,6 +41,7 @@ struct async
struct list queue_entry; /* entry in async queue list */
struct list process_entry; /* entry in process list */
struct async_queue *queue; /* queue containing this async */
+ struct fd *fd; /* fd associated with an unqueued async */
unsigned int status; /* current status */
struct timeout_user *timeout;
unsigned int timeout_status; /* status to report upon timeout */
@@ -167,6 +168,7 @@ static void async_destroy( struct object *obj )
release_object( async->queue );
}
+ if (async->fd) release_object( async->fd );
if (async->timeout) remove_timeout_user( async->timeout );
if (async->event) release_object( async->event );
if (async->iosb) release_object( async->iosb );
@@ -257,8 +259,10 @@ void free_async_queue( struct async_queue *queue )
void queue_async( struct async_queue *queue, struct async *async )
{
- async->queue = (struct async_queue *)grab_object( queue );
+ release_object( async->fd );
+ async->fd = NULL;
+ async->queue = (struct async_queue *)grab_object( queue );
grab_object( async );
list_add_tail( &queue->queue, &async->queue_entry );
@@ -266,7 +270,7 @@ void queue_async( struct async_queue *queue, struct async *async )
}
/* create an async on a given queue of a fd */
-struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb )
+struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb )
{
struct event *event = NULL;
struct async *async;
@@ -286,6 +290,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
async->data = *data;
async->timeout = NULL;
async->queue = NULL;
+ async->fd = (struct fd *)grab_object( fd );
async->signaled = 0;
async->wait_handle = 0;
async->direct_result = 0;
@@ -301,7 +306,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
/* create an async associated with iosb for async-based requests
* returned async must be passed to async_handoff */
-struct async *create_request_async( struct thread *thread, const async_data_t *data )
+struct async *create_request_async( struct fd *fd, const async_data_t *data )
{
struct async *async;
struct iosb *iosb;
@@ -309,7 +314,7 @@ struct async *create_request_async( struct thread *thread, const async_data_t *d
if (!(iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() )))
return NULL;
- async = create_async( current, data, iosb );
+ async = create_async( fd, current, data, iosb );
release_object( iosb );
if (async)
{
@@ -365,13 +370,15 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta
async->timeout_status = status;
}
-static void add_async_completion( struct async_queue *queue, apc_param_t cvalue, unsigned int status,
+static void add_async_completion( struct async *async, apc_param_t cvalue, unsigned int status,
apc_param_t information )
{
- if (queue->fd)
+ struct fd *fd = async->queue ? async->queue->fd : async->fd;
+
+ if (fd)
{
apc_param_t ckey;
- struct completion *completion = fd_get_completion( queue->fd, &ckey );
+ struct completion *completion = fd_get_completion( fd, &ckey );
if (completion)
{
@@ -379,8 +386,8 @@ static void add_async_completion( struct async_queue *queue, apc_param_t cvalue,
release_object( completion );
}
}
- else if (queue->completion) add_completion( queue->completion, queue->comp_key,
- cvalue, status, information );
+ else if (async->queue && async->queue->completion)
+ add_completion( async->queue->completion, async->queue->comp_key, cvalue, status, information );
}
/* store the result of the client-side async callback */
@@ -410,8 +417,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
async->status = status;
if (status == STATUS_MORE_PROCESSING_REQUIRED) return; /* don't report the completion */
- if (async->queue && !async->data.apc && async->data.apc_context)
- add_async_completion( async->queue, async->data.apc_context, status, total );
if (async->data.apc)
{
apc_call_t data;
@@ -423,7 +428,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
data.user.args[2] = 0;
thread_queue_apc( async->thread, NULL, &data );
}
+ else if (async->data.apc_context)
+ add_async_completion( async, async->data.apc_context, status, total );
+
if (async->event) set_event( async->event );
+ else if (async->fd) set_fd_signaled( async->fd, 1 );
else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
if (!async->signaled)
{
@@ -454,13 +463,15 @@ int async_waiting( struct async_queue *queue )
static int cancel_async( struct process *process, struct object *obj, struct thread *thread, client_ptr_t iosb )
{
struct async *async;
+ struct fd *fd;
int woken = 0;
restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{
if (async->status == STATUS_CANCELLED) continue;
- if ((!obj || (async->queue && async->queue->fd && get_fd_user( async->queue->fd ) == obj)) &&
+ fd = async->queue ? async->queue->fd : async->fd;
+ if ((!obj || (fd && get_fd_user( fd ) == obj)) &&
(!thread || async->thread == thread) &&
(!iosb || async->data.iosb == iosb))
{
diff --git a/server/change.c b/server/change.c
index 14fb2f1..88423fe 100644
--- a/server/change.c
+++ b/server/change.c
@@ -1246,7 +1246,7 @@ DECL_HANDLER(read_directory_changes)
return;
/* requests don't timeout */
- if (!(async = create_async( current, &req->async, NULL ))) goto end;
+ if (!(async = create_async( dir->fd, current, &req->async, NULL ))) goto end;
if (!fd_queue_async( dir->fd, async, ASYNC_TYPE_WAIT )) goto end;
/* assign it once */
diff --git a/server/fd.c b/server/fd.c
index 0f1a15e..a073c54 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2373,7 +2373,7 @@ DECL_HANDLER(flush)
if (!fd) return;
- async = create_async( current, &req->async, NULL );
+ async = create_async( fd, current, &req->async, NULL );
if (async)
{
reply->event = fd->fd_ops->flush( fd, async );
@@ -2449,7 +2449,7 @@ DECL_HANDLER(read)
if (!fd) return;
- if ((async = create_request_async( current, &req->async )))
+ if ((async = create_request_async( fd, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ), NULL );
reply->options = fd->options;
@@ -2466,7 +2466,7 @@ DECL_HANDLER(write)
if (!fd) return;
- if ((async = create_request_async( current, &req->async )))
+ if ((async = create_request_async( fd, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->write( fd, async, req->pos ), &reply->size );
reply->options = fd->options;
@@ -2487,7 +2487,7 @@ DECL_HANDLER(ioctl)
if ((iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() )))
{
- if ((async = create_async( current, &req->async, iosb )))
+ if ((async = create_async( fd, current, &req->async, iosb )))
{
reply->wait = fd->fd_ops->ioctl( fd, req->code, async );
reply->options = fd->options;
@@ -2520,7 +2520,7 @@ DECL_HANDLER(register_async)
if ((fd = get_handle_fd_obj( current->process, req->async.handle, access )))
{
- if (get_unix_fd( fd ) != -1 && (async = create_async( current, &req->async, NULL )))
+ if (get_unix_fd( fd ) != -1 && (async = create_async( fd, current, &req->async, NULL )))
{
fd->fd_ops->queue_async( fd, async, req->type, req->count );
release_object( async );
diff --git a/server/file.h b/server/file.h
index 96c1d23..1e5ea7a 100644
--- a/server/file.h
+++ b/server/file.h
@@ -175,8 +175,8 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */
extern struct async_queue *create_async_queue( struct fd *fd );
extern void free_async_queue( struct async_queue *queue );
-extern struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb );
-extern struct async *create_request_async( struct thread *thread, const async_data_t *data );
+extern struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb );
+extern struct async *create_request_async( struct fd *fd, const async_data_t *data );
extern obj_handle_t async_handoff( struct async *async, int success, data_size_t *result );
extern void queue_async( struct async_queue *queue, struct async *async );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
More information about the wine-cvs
mailing list