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