From: Jacek Caban Subject: [PATCH 02/12] server: Preallocate wait handle in create_request_async and return it in read request. Message-Id: <64883bb5-a6cf-a6b8-1b46-fa3a482bc557@codeweavers.com> Date: Tue, 13 Jun 2017 16:47:25 +0200 device.c changes are ugly, but cleaned up later in the series. Signed-off-by: Jacek Caban --- server/async.c | 35 ++++++++++++++++++++++++++++++++++- server/device.c | 19 ++++++++++--------- server/fd.c | 4 ++-- server/file.h | 5 +++-- server/named_pipe.c | 20 +++----------------- 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/server/async.c b/server/async.c index d1cea9a607..4c6c6a9586 100644 --- a/server/async.c +++ b/server/async.c @@ -48,6 +48,7 @@ struct async struct event *event; async_data_t data; /* data for async I/O call */ struct iosb *iosb; /* I/O status block */ + obj_handle_t wait_handle; /* pre-allocated wait handle */ }; static void async_dump( struct object *obj, int verbose ); @@ -262,6 +263,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str async->timeout = NULL; async->queue = NULL; async->signaled = 0; + async->wait_handle = 0; if (iosb) async->iosb = (struct iosb *)grab_object( iosb ); else async->iosb = NULL; @@ -272,7 +274,8 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str return async; } -/* create an async associated with iosb for async-based requests */ +/* 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 *async; @@ -283,9 +286,39 @@ struct async *create_request_async( struct thread *thread, const async_data_t *d async = create_async( current, data, iosb ); release_object( iosb ); + if (async) + { + if (!(async->wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) + { + release_object( async ); + return NULL; + } + } return async; } +/* return async object status and wait handle to client */ +obj_handle_t async_handoff( struct async *async, int success ) +{ + obj_handle_t handle; + if (!success) + { + close_handle( async->thread->process, async->wait_handle ); + async->wait_handle = 0; + return 0; + } + + if (async->iosb->status == STATUS_PENDING && !async_is_blocking( async )) + { + close_handle( async->thread->process, async->wait_handle); + async->wait_handle = 0; + } + handle = async->wait_handle; + async->wait_handle = 0; + set_error( STATUS_PENDING ); + return handle; +} + /* set the timeout of an async operation */ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ) { diff --git a/server/device.c b/server/device.c index 1fe3de7d36..4aa605bdea 100644 --- a/server/device.c +++ b/server/device.c @@ -174,7 +174,7 @@ static struct fd *device_file_get_fd( struct object *obj ); static int device_file_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void device_file_destroy( struct object *obj ); static enum server_fd_type device_file_get_fd_type( struct fd *fd ); -static obj_handle_t device_file_read( struct fd *fd, struct async *async, file_pos_t pos ); +static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos ); static obj_handle_t device_file_write( struct fd *fd, struct async *async, file_pos_t pos ); static obj_handle_t device_file_flush( struct fd *fd, struct async *async ); static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); @@ -462,15 +462,16 @@ static void set_file_user_ptr( struct device_file *file, client_ptr_t ptr ) } /* queue an irp to the device */ -static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, struct async *async ) +static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, struct async *async, int need_handle ) { obj_handle_t handle = 0; - if (async_is_blocking( async ) && !(handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) return 0; + if (!need_handle) handle = 1; + else if (async_is_blocking( async ) && !(handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) return 0; if (!fd_queue_async( file->fd, async, ASYNC_TYPE_WAIT )) { - if (handle) close_handle( current->process, handle ); + if (need_handle && handle) close_handle( current->process, handle ); return 0; } irp->async = (struct async *)grab_object( async ); @@ -484,7 +485,7 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd ) return FD_TYPE_DEVICE; } -static obj_handle_t device_file_read( struct fd *fd, struct async *async, file_pos_t pos ) +static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp; @@ -500,7 +501,7 @@ static obj_handle_t device_file_read( struct fd *fd, struct async *async, file_p irp = create_irp( file, ¶ms, async ); if (!irp) return 0; - handle = queue_irp( file, irp, async ); + handle = queue_irp( file, irp, async, 0 ); release_object( irp ); return handle; } @@ -521,7 +522,7 @@ static obj_handle_t device_file_write( struct fd *fd, struct async *async, file_ irp = create_irp( file, ¶ms, async ); if (!irp) return 0; - handle = queue_irp( file, irp, async ); + handle = queue_irp( file, irp, async, 1 ); release_object( irp ); return handle; } @@ -540,7 +541,7 @@ static obj_handle_t device_file_flush( struct fd *fd, struct async *async ) irp = create_irp( file, ¶ms, NULL ); if (!irp) return 0; - handle = queue_irp( file, irp, async ); + handle = queue_irp( file, irp, async, 1 ); release_object( irp ); return handle; } @@ -560,7 +561,7 @@ static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct irp = create_irp( file, ¶ms, async ); if (!irp) return 0; - handle = queue_irp( file, irp, async ); + handle = queue_irp( file, irp, async, 1 ); release_object( irp ); return handle; } diff --git a/server/fd.c b/server/fd.c index f05556a133..f6eb57d1fd 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2158,7 +2158,7 @@ static void unmount_device( struct fd *device_fd ) } /* default read() routine */ -obj_handle_t no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ) +int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); return 0; @@ -2451,7 +2451,7 @@ DECL_HANDLER(read) if ((async = create_request_async( current, &req->async ))) { - reply->wait = fd->fd_ops->read( fd, async, req->pos ); + reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ) ); reply->options = fd->options; release_object( async ); } diff --git a/server/file.h b/server/file.h index 30db87e3ac..8cc4d3beab 100644 --- a/server/file.h +++ b/server/file.h @@ -52,7 +52,7 @@ struct fd_ops /* get file information */ enum server_fd_type (*get_fd_type)(struct fd *fd); /* perform a read on the file */ - obj_handle_t (*read)(struct fd *, struct async *, file_pos_t ); + int (*read)(struct fd *, struct async *, file_pos_t ); /* perform a write on the file */ obj_handle_t (*write)(struct fd *, struct async *, file_pos_t ); /* flush the object buffers */ @@ -100,7 +100,7 @@ extern void default_poll_event( struct fd *fd, int event ); extern int fd_queue_async( struct fd *fd, struct async *async, int type ); extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status ); extern void fd_reselect_async( struct fd *fd, struct async_queue *queue ); -extern obj_handle_t no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ); +extern int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ); extern obj_handle_t no_fd_write( struct fd *fd, struct async *async, file_pos_t pos ); extern obj_handle_t no_fd_flush( struct fd *fd, struct async *async ); extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); @@ -177,6 +177,7 @@ 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 obj_handle_t async_handoff( struct async *async, int success ); 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 ); diff --git a/server/named_pipe.c b/server/named_pipe.c index 0c314bd2e1..07ec006b79 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -154,7 +154,7 @@ static const struct object_ops named_pipe_ops = /* common server and client pipe end functions */ static enum server_fd_type pipe_end_get_fd_type( struct fd *fd ); -static obj_handle_t pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos ); +static int pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos ); static obj_handle_t pipe_end_write( struct fd *fd, struct async *async_data, file_pos_t pos ); static void pipe_end_queue_async( struct fd *fd, struct async *async, int type, int count ); static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue ); @@ -810,10 +810,9 @@ static void reselect_write_queue( struct pipe_end *pipe_end ) reselect_read_queue( reader ); } -static obj_handle_t pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos ) +static int pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos ) { struct pipe_end *pipe_end = get_fd_user( fd ); - obj_handle_t handle = 0; if (!use_server_io( pipe_end )) return no_fd_read( fd, async, pos ); @@ -824,24 +823,11 @@ static obj_handle_t pipe_end_read( struct fd *fd, struct async *async, file_pos_ } if (!pipe_end->read_q && !(pipe_end->read_q = create_async_queue( fd ))) return 0; - if (!(handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) return 0; queue_async( pipe_end->read_q, async ); reselect_read_queue( pipe_end ); set_error( STATUS_PENDING ); - - if (!async_is_blocking( async )) - { - struct iosb *iosb; - iosb = async_get_iosb( async ); - if (iosb->status == STATUS_PENDING) - { - close_handle( current->process, handle ); - handle = 0; - } - release_object( iosb ); - } - return handle; + return 1; } static obj_handle_t pipe_end_write( struct fd *fd, struct async *async, file_pos_t pos )