Alexandre Julliard : server: Make async objects waitable.

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 8 05:21:28 CDT 2015


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri May  8 17:32:06 2015 +0900

server: Make async objects waitable.

---

 server/async.c      | 20 ++++++++++++++++----
 server/event.c      | 13 -------------
 server/named_pipe.c | 32 ++++----------------------------
 server/object.h     |  1 -
 server/sock.c       | 46 ++++++++--------------------------------------
 5 files changed, 28 insertions(+), 84 deletions(-)

diff --git a/server/async.c b/server/async.c
index e1650fe..d2da976 100644
--- a/server/async.c
+++ b/server/async.c
@@ -41,11 +41,13 @@ struct async
     unsigned int         status;          /* current status */
     struct timeout_user *timeout;
     unsigned int         timeout_status;  /* status to report upon timeout */
+    int                  signaled;
     struct event        *event;
     async_data_t         data;            /* data for async I/O call */
 };
 
 static void async_dump( struct object *obj, int verbose );
+static int async_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void async_destroy( struct object *obj );
 
 static const struct object_ops async_ops =
@@ -53,10 +55,10 @@ static const struct object_ops async_ops =
     sizeof(struct async),      /* size */
     async_dump,                /* dump */
     no_get_type,               /* get_type */
-    no_add_queue,              /* add_queue */
-    NULL,                      /* remove_queue */
-    NULL,                      /* signaled */
-    NULL,                      /* satisfied */
+    add_queue,                 /* add_queue */
+    remove_queue,              /* remove_queue */
+    async_signaled,            /* signaled */
+    no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
     no_map_access,             /* map_access */
@@ -114,6 +116,13 @@ static void async_dump( struct object *obj, int verbose )
     fprintf( stderr, "Async thread=%p\n", async->thread );
 }
 
+static int async_signaled( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct async *async = (struct async *)obj;
+    assert( obj->ops == &async_ops );
+    return async->signaled;
+}
+
 static void async_destroy( struct object *obj )
 {
     struct async *async = (struct async *)obj;
@@ -228,6 +237,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
     async->data    = *data;
     async->timeout = NULL;
     async->queue   = (struct async_queue *)grab_object( queue );
+    async->signaled = 0;
 
     list_add_tail( &queue->queue, &async->queue_entry );
     grab_object( async );
@@ -306,6 +316,8 @@ 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->fd) set_fd_signaled( async->queue->fd, 1 );
+        async->signaled = 1;
+        wake_up( &async->obj, 0 );
     }
 }
 
diff --git a/server/event.c b/server/event.c
index 0daa5b2..4d3c562 100644
--- a/server/event.c
+++ b/server/event.c
@@ -124,19 +124,6 @@ struct event *create_event( struct directory *root, const struct unicode_str *na
     return event;
 }
 
-obj_handle_t alloc_wait_event( struct process *process )
-{
-    obj_handle_t handle = 0;
-    struct event *event = create_event( NULL, NULL, 0, 1, 0, NULL );
-
-    if (event)
-    {
-        handle = alloc_handle( process, event, EVENT_ALL_ACCESS, 0 );
-        release_object( event );
-    }
-    return handle;
-}
-
 struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access )
 {
     return (struct event *)get_handle_obj( process, handle, access, &event_ops );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 154eeb9..83e2dae 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -614,21 +614,9 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const a
         {
         case ps_idle_server:
         case ps_wait_connect:
-            if (blocking)
-            {
-                async_data_t new_data = *async_data;
-                if (!(wait_handle = alloc_wait_event( current->process ))) break;
-                new_data.event = wait_handle;
-                if (!(async = fd_queue_async( server->ioctl_fd, &new_data, ASYNC_TYPE_WAIT )))
-                {
-                    close_handle( current->process, wait_handle );
-                    break;
-                }
-            }
-            else async = fd_queue_async( server->ioctl_fd, async_data, ASYNC_TYPE_WAIT );
-
-            if (async)
+            if ((async = fd_queue_async( server->ioctl_fd, async_data, ASYNC_TYPE_WAIT )))
             {
+                if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
                 set_server_state( server, ps_wait_open );
                 if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS );
                 release_object( async );
@@ -913,23 +901,11 @@ 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 (blocking)
-                {
-                    async_data_t new_data = *async_data;
-                    if (!(wait_handle = alloc_wait_event( current->process ))) goto done;
-                    new_data.event = wait_handle;
-                    if (!(async = create_async( current, pipe->waiters, &new_data )))
-                    {
-                        close_handle( current->process, wait_handle );
-                        wait_handle = 0;
-                    }
-                }
-                else async = create_async( current, pipe->waiters, async_data );
-
-                if (async)
+                if ((async = create_async( current, pipe->waiters, async_data )))
                 {
                     timeout_t 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 );
                     set_error( STATUS_PENDING );
                 }
diff --git a/server/object.h b/server/object.h
index 72b52ee..00bef38 100644
--- a/server/object.h
+++ b/server/object.h
@@ -162,7 +162,6 @@ extern struct event *create_event( struct directory *root, const struct unicode_
                                    const struct security_descriptor *sd );
 extern struct keyed_event *create_keyed_event( struct directory *root, const struct unicode_str *name,
                                                unsigned int attr, const struct security_descriptor *sd );
-extern obj_handle_t alloc_wait_event( struct process *process );
 extern struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
 extern struct keyed_event *get_keyed_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
 extern void pulse_event( struct event *event );
diff --git a/server/sock.c b/server/sock.c
index c4dcf6f..67d6416 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -120,7 +120,6 @@ struct sock
 };
 
 static void sock_dump( struct object *obj, int verbose );
-static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
 static int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *sock_get_fd( struct object *obj );
 static void sock_destroy( struct object *obj );
@@ -539,25 +538,19 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
 {
     struct sock *sock = get_fd_user( fd );
     obj_handle_t wait_handle = 0;
-    async_data_t new_data;
+    struct async_queue *ifchange_q;
+    struct async *async;
 
     assert( sock->obj.ops == &sock_ops );
 
     switch(code)
     {
     case WS_SIO_ADDRESS_LIST_CHANGE:
-        if (blocking)
-        {
-            if (!(wait_handle = alloc_wait_event( current->process ))) return 0;
-            new_data = *async_data;
-            new_data.event = wait_handle;
-            async_data = &new_data;
-        }
-        if (!sock_add_ifchange( sock, async_data ) && wait_handle)
-        {
-            close_handle( current->process, wait_handle );
-            return 0;
-        }
+        if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0;
+        if (!(async = create_async( current, ifchange_q, async_data ))) return 0;
+        if (blocking) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
+        release_object( async );
+        set_error( STATUS_PENDING );
         return wait_handle;
     default:
         set_error( STATUS_NOT_SUPPORTED );
@@ -962,29 +955,6 @@ static void sock_set_error(void)
     set_error( sock_get_ntstatus( errno ) );
 }
 
-/* add interface change notification to a socket */
-static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
-{
-    struct async_queue *ifchange_q;
-    struct async *async;
-
-    if (!(ifchange_q = sock_get_ifchange_q( sock )))
-        return 0;
-
-    if (!(async = create_async( current, ifchange_q, async_data )))
-    {
-        if (!async_queued( ifchange_q ))
-            sock_destroy_ifchange_q( sock );
-
-        set_error( STATUS_NO_MEMORY );
-        return 0;
-    }
-
-    release_object( async );
-    set_error( STATUS_PENDING );
-    return 1;
-}
-
 #ifdef HAVE_LINUX_RTNETLINK_H
 
 /* only keep one ifchange object around, all sockets waiting for wakeups will look to it */
@@ -1204,7 +1174,7 @@ static struct async_queue *sock_get_ifchange_q( struct sock *sock )
         return NULL;
 
     /* create the ifchange notification queue */
-    fd = ifchange->ops->get_fd( ifchange );
+    fd = get_obj_fd( ifchange );
     sock->ifchange_q = create_async_queue( fd );
     release_object( fd );
     if (!sock->ifchange_q)




More information about the wine-cvs mailing list