From: Jacek Caban Subject: [PATCH 2/7] server: Allow creating async object not associated with a queue. Message-Id: <263e1775-c441-7b55-d883-9e7714c2338a@codeweavers.com> Date: Wed, 15 Feb 2017 22:12:28 +0100 Signed-off-by: Jacek Caban --- 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 );