Jacek Caban : server: Allow creating async object not associated with a queue.

Alexandre Julliard julliard at winehq.org
Tue Feb 21 16:56:13 CST 2017


Module: wine
Branch: master
Commit: 91bd81441f3b5ab4760ff225e7d88c6b35ca3f2c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=91bd81441f3b5ab4760ff225e7d88c6b35ca3f2c

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Feb 15 22:12:28 2017 +0100

server: Allow creating async object not associated with a queue.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 server/async.c      | 41 ++++++++++++++++++++++++++---------------
 server/fd.c         | 14 +++++++++-----
 server/file.h       |  4 ++--
 server/named_pipe.c |  6 ++++--
 server/sock.c       |  6 ++++--
 5 files changed, 45 insertions(+), 26 deletions(-)

diff --git a/server/async.c b/server/async.c
index ef548d1..3de60b6 100644
--- a/server/async.c
+++ b/server/async.c
@@ -114,7 +114,7 @@ static const struct object_ops async_queue_ops =
 
 static inline void async_reselect( struct async *async )
 {
-    if (async->queue->fd) fd_reselect_async( async->queue->fd, async->queue );
+    if (async->queue && async->queue->fd) fd_reselect_async( async->queue->fd, async->queue );
 }
 
 static void async_dump( struct object *obj, int verbose )
@@ -137,13 +137,17 @@ static void async_destroy( struct object *obj )
     assert( obj->ops == &async_ops );
 
     list_remove( &async->process_entry );
-    list_remove( &async->queue_entry );
-    async_reselect( async );
+
+    if (async->queue)
+    {
+        list_remove( &async->queue_entry );
+        async_reselect( async );
+        release_object( async->queue );
+    }
 
     if (async->timeout) remove_timeout_user( async->timeout );
     if (async->event) release_object( async->event );
     if (async->iosb) release_object( async->iosb );
-    release_object( async->queue );
     release_object( async->thread );
 }
 
@@ -191,7 +195,7 @@ void async_terminate( struct async *async, unsigned int status )
     else async_set_result( &async->obj, STATUS_SUCCESS, 0, 0, 0 );
 
     async_reselect( async );
-    release_object( async );  /* so that it gets destroyed when the async is done */
+    if (async->queue) release_object( async );  /* so that it gets destroyed when the async is done */
 }
 
 /* callback for timeout on an async request */
@@ -227,9 +231,18 @@ void free_async_queue( struct async_queue *queue )
     release_object( queue );
 }
 
+void queue_async( struct async_queue *queue, struct async *async )
+{
+    async->queue = (struct async_queue *)grab_object( queue );
+
+    grab_object( async );
+    list_add_tail( &queue->queue, &async->queue_entry );
+
+    if (queue->fd) set_fd_signaled( queue->fd, 0 );
+}
+
 /* create an async on a given queue of a fd */
-struct async *create_async( struct thread *thread, struct async_queue *queue, const async_data_t *data,
-                            struct iosb *iosb )
+struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb )
 {
     struct event *event = NULL;
     struct async *async;
@@ -248,18 +261,15 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
     async->status  = STATUS_PENDING;
     async->data    = *data;
     async->timeout = NULL;
-    async->queue   = (struct async_queue *)grab_object( queue );
+    async->queue   = NULL;
     async->signaled = 0;
 
     if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
     else async->iosb = NULL;
 
-    list_add_tail( &queue->queue, &async->queue_entry );
     list_add_head( &thread->process->asyncs, &async->process_entry );
-    grab_object( async );
-
-    if (queue->fd) set_fd_signaled( queue->fd, 0 );
     if (event) reset_event( event );
+
     return async;
 }
 
@@ -318,7 +328,8 @@ 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->data.cvalue) add_async_completion( async->queue, async->data.cvalue, status, total );
+        if (async->queue && async->data.cvalue)
+            add_async_completion( async->queue, async->data.cvalue, status, total );
         if (apc)
         {
             apc_call_t data;
@@ -331,7 +342,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
             thread_queue_apc( async->thread, NULL, &data );
         }
         if (async->event) set_event( async->event );
-        else if (async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
+        else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
         async->signaled = 1;
         wake_up( &async->obj, 0 );
     }
@@ -364,7 +375,7 @@ restart:
     LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
     {
         if (async->status == STATUS_CANCELLED) continue;
-        if ((!obj || (async->queue->fd && get_fd_user( async->queue->fd ) == obj)) &&
+        if ((!obj || (async->queue && async->queue->fd && get_fd_user( async->queue->fd ) == obj)) &&
             (!thread || async->thread == thread) &&
             (!iosb || async->data.iosb == iosb))
         {
diff --git a/server/fd.c b/server/fd.c
index 732a5b7..31d0f4a 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2054,12 +2054,16 @@ struct async *fd_queue_async( struct fd *fd, const async_data_t *data, struct io
         assert(0);
     }
 
-    if ((async = create_async( current, queue, data, iosb )) && type != ASYNC_TYPE_WAIT)
+    if ((async = create_async( current, data, iosb )))
     {
-        if (!fd->inode)
-            set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
-        else  /* regular files are always ready for read and write */
-            async_wake_up( queue, STATUS_ALERTED );
+        queue_async( queue, async );
+        if (type != ASYNC_TYPE_WAIT)
+        {
+            if (!fd->inode)
+                set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
+            else  /* regular files are always ready for read and write */
+                async_wake_up( queue, STATUS_ALERTED );
+        }
     }
     return async;
 }
diff --git a/server/file.h b/server/file.h
index c5867a6..af497da 100644
--- a/server/file.h
+++ b/server/file.h
@@ -177,8 +177,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, struct async_queue *queue,
-                                   const async_data_t *data, struct iosb *iosb );
+extern struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb );
+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 );
 extern void async_set_result( struct object *obj, unsigned int status,
                               apc_param_t total, client_ptr_t apc, client_ptr_t apc_arg );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 3245688..4eee875 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -838,6 +838,7 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code,
             struct named_pipe *pipe;
             struct pipe_server *server;
             struct unicode_str name;
+            timeout_t when;
 
             if (size < sizeof(*buffer) ||
                 size < FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[buffer->NameLength/sizeof(WCHAR)]))
@@ -855,9 +856,10 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code,
 
                 if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL ))) goto done;
 
-                if ((async = create_async( current, pipe->waiters, async_data, NULL )))
+                if ((async = create_async( current, async_data, NULL )))
                 {
-                    timeout_t when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout;
+                    queue_async( pipe->waiters, async );
+                    when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout;
                     async_set_timeout( async, when, STATUS_IO_TIMEOUT );
                     if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
                     release_object( async );
diff --git a/server/sock.c b/server/sock.c
index f70a85d..e9369e5 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -552,7 +552,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
             return 0;
         }
         if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0;
-        if (!(async = create_async( current, ifchange_q, async_data, NULL ))) return 0;
+        if (!(async = create_async( current, async_data, NULL ))) return 0;
+        queue_async( ifchange_q, async );
         if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
         release_object( async );
         set_error( STATUS_PENDING );
@@ -593,7 +594,8 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
         return;
     }
 
-    if (!(async = create_async( current, queue, data, NULL ))) return;
+    if (!(async = create_async( current, data, NULL ))) return;
+    queue_async( queue, async );
     release_object( async );
 
     sock_reselect( sock );




More information about the wine-cvs mailing list