Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/async.c | 15 +++++++++++++++ server/file.h | 4 ++++ server/sock.c | 23 +++++++++++------------ 3 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/server/async.c b/server/async.c index 6da61fd502c..1ac5117edb9 100644 --- a/server/async.c +++ b/server/async.c @@ -55,6 +55,8 @@ struct async struct completion *completion; /* completion associated with fd */ apc_param_t comp_key; /* completion key associated with fd */ unsigned int comp_flags; /* completion flags */ + async_completion_callback completion_callback; /* callback to be called on completion */ + void *completion_callback_private; /* argument to completion_callback */ };
static void async_dump( struct object *obj, int verbose ); @@ -247,6 +249,8 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->direct_result = 0; async->completion = fd_get_completion( fd, &async->comp_key ); async->comp_flags = 0; + async->completion_callback = NULL; + async->completion_callback_private = NULL;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb ); else async->iosb = NULL; @@ -362,6 +366,13 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta async->timeout_status = status; }
+/* set a callback to be notified when the async is completed */ +void async_set_completion_callback( struct async *async, async_completion_callback func, void *private ) +{ + async->completion_callback = func; + async->completion_callback_private = private; +} + static void add_async_completion( struct async *async, apc_param_t cvalue, unsigned int status, apc_param_t information ) { @@ -420,6 +431,10 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota async->signaled = 1; wake_up( &async->obj, 0 ); } + + if (async->completion_callback) + async->completion_callback( async->completion_callback_private ); + async->completion_callback = NULL; } }
diff --git a/server/file.h b/server/file.h index 686bae084c5..87b500f0b5f 100644 --- a/server/file.h +++ b/server/file.h @@ -209,6 +209,9 @@ extern int is_serial_fd( struct fd *fd ); extern struct object *create_serial( struct fd *fd );
/* async I/O functions */ + +typedef void (*async_completion_callback)( void *private ); + extern void free_async_queue( struct async_queue *queue ); 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, unsigned int comp_flags, const async_data_t *data ); @@ -216,6 +219,7 @@ extern obj_handle_t async_handoff( struct async *async, int success, data_size_t 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 ); +extern void async_set_completion_callback( struct async *async, async_completion_callback func, void *private ); extern void set_async_pending( struct async *async, int signal ); extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); diff --git a/server/sock.c b/server/sock.c index 78b1578113b..3aed5494612 100644 --- a/server/sock.c +++ b/server/sock.c @@ -449,8 +449,9 @@ static inline int sock_error( struct fd *fd ) return optval; }
-static void free_accept_req( struct accept_req *req ) +static void free_accept_req( void *private ) { + struct accept_req *req = private; list_remove( &req->entry ); if (req->acceptsock) { @@ -582,7 +583,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
LIST_FOR_EACH_ENTRY( req, &sock->accept_list, struct accept_req, entry ) { - if (!req->accepted) + if (req->iosb->status == STATUS_PENDING && !req->accepted) { complete_async_accept( sock, req ); if (get_error() != STATUS_PENDING) @@ -591,7 +592,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) } }
- if (sock->accept_recv_req) + if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING) { complete_async_accept_recv( sock->accept_recv_req ); if (get_error() != STATUS_PENDING) @@ -626,9 +627,12 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) async_wake_up( &sock->write_q, status );
LIST_FOR_EACH_ENTRY_SAFE( req, next, &sock->accept_list, struct accept_req, entry ) - async_terminate( req->async, status ); + { + if (req->iosb->status == STATUS_PENDING) + async_terminate( req->async, status ); + }
- if (sock->accept_recv_req) + if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING) async_terminate( sock->accept_recv_req->async, status ); }
@@ -872,13 +876,6 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int static void sock_reselect_async( struct fd *fd, struct async_queue *queue ) { struct sock *sock = get_fd_user( fd ); - struct accept_req *req, *next; - - LIST_FOR_EACH_ENTRY_SAFE( req, next, &sock->accept_list, struct accept_req, entry ) - { - if (req->iosb->status != STATUS_PENDING) - free_accept_req( req ); - }
/* ignore reselect on ifchange queue */ if (&sock->ifchange_q != queue) @@ -1434,6 +1431,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) if (!(req = alloc_accept_req( sock, NULL, async, NULL ))) return 0; list_add_tail( &sock->accept_list, &req->entry );
+ async_set_completion_callback( async, free_accept_req, req ); queue_async( &sock->accept_q, async ); sock_reselect( sock ); set_error( STATUS_PENDING ); @@ -1490,6 +1488,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) release_object( acceptsock );
acceptsock->wparam = params->accept_handle; + async_set_completion_callback( async, free_accept_req, req ); queue_async( &sock->accept_q, async ); sock_reselect( sock ); set_error( STATUS_PENDING );