Commit fa0dfe59 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

server: Store fd reference in async object for unqueued asyncs.

parent 2bd828b1
...@@ -41,6 +41,7 @@ struct async ...@@ -41,6 +41,7 @@ struct async
struct list queue_entry; /* entry in async queue list */ struct list queue_entry; /* entry in async queue list */
struct list process_entry; /* entry in process list */ struct list process_entry; /* entry in process list */
struct async_queue *queue; /* queue containing this async */ struct async_queue *queue; /* queue containing this async */
struct fd *fd; /* fd associated with an unqueued async */
unsigned int status; /* current status */ unsigned int status; /* current status */
struct timeout_user *timeout; struct timeout_user *timeout;
unsigned int timeout_status; /* status to report upon timeout */ unsigned int timeout_status; /* status to report upon timeout */
...@@ -167,6 +168,7 @@ static void async_destroy( struct object *obj ) ...@@ -167,6 +168,7 @@ static void async_destroy( struct object *obj )
release_object( async->queue ); release_object( async->queue );
} }
if (async->fd) release_object( async->fd );
if (async->timeout) remove_timeout_user( async->timeout ); if (async->timeout) remove_timeout_user( async->timeout );
if (async->event) release_object( async->event ); if (async->event) release_object( async->event );
if (async->iosb) release_object( async->iosb ); if (async->iosb) release_object( async->iosb );
...@@ -257,8 +259,10 @@ void free_async_queue( struct async_queue *queue ) ...@@ -257,8 +259,10 @@ void free_async_queue( struct async_queue *queue )
void queue_async( struct async_queue *queue, struct async *async ) void queue_async( struct async_queue *queue, struct async *async )
{ {
async->queue = (struct async_queue *)grab_object( queue ); release_object( async->fd );
async->fd = NULL;
async->queue = (struct async_queue *)grab_object( queue );
grab_object( async ); grab_object( async );
list_add_tail( &queue->queue, &async->queue_entry ); list_add_tail( &queue->queue, &async->queue_entry );
...@@ -266,7 +270,7 @@ void queue_async( struct async_queue *queue, struct async *async ) ...@@ -266,7 +270,7 @@ void queue_async( struct async_queue *queue, struct async *async )
} }
/* create an async on a given queue of a fd */ /* create an async on a given queue of a fd */
struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb ) struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb )
{ {
struct event *event = NULL; struct event *event = NULL;
struct async *async; struct async *async;
...@@ -286,6 +290,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str ...@@ -286,6 +290,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
async->data = *data; async->data = *data;
async->timeout = NULL; async->timeout = NULL;
async->queue = NULL; async->queue = NULL;
async->fd = (struct fd *)grab_object( fd );
async->signaled = 0; async->signaled = 0;
async->wait_handle = 0; async->wait_handle = 0;
async->direct_result = 0; async->direct_result = 0;
...@@ -301,7 +306,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str ...@@ -301,7 +306,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
/* 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 */ * returned async must be passed to async_handoff */
struct async *create_request_async( struct thread *thread, const async_data_t *data ) struct async *create_request_async( struct fd *fd, const async_data_t *data )
{ {
struct async *async; struct async *async;
struct iosb *iosb; struct iosb *iosb;
...@@ -309,7 +314,7 @@ struct async *create_request_async( struct thread *thread, const async_data_t *d ...@@ -309,7 +314,7 @@ struct async *create_request_async( struct thread *thread, const async_data_t *d
if (!(iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() ))) if (!(iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() )))
return NULL; return NULL;
async = create_async( current, data, iosb ); async = create_async( fd, current, data, iosb );
release_object( iosb ); release_object( iosb );
if (async) if (async)
{ {
...@@ -365,13 +370,15 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta ...@@ -365,13 +370,15 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta
async->timeout_status = status; async->timeout_status = status;
} }
static void add_async_completion( struct async_queue *queue, apc_param_t cvalue, unsigned int status, static void add_async_completion( struct async *async, apc_param_t cvalue, unsigned int status,
apc_param_t information ) apc_param_t information )
{ {
if (queue->fd) struct fd *fd = async->queue ? async->queue->fd : async->fd;
if (fd)
{ {
apc_param_t ckey; apc_param_t ckey;
struct completion *completion = fd_get_completion( queue->fd, &ckey ); struct completion *completion = fd_get_completion( fd, &ckey );
if (completion) if (completion)
{ {
...@@ -379,8 +386,8 @@ static void add_async_completion( struct async_queue *queue, apc_param_t cvalue, ...@@ -379,8 +386,8 @@ static void add_async_completion( struct async_queue *queue, apc_param_t cvalue,
release_object( completion ); release_object( completion );
} }
} }
else if (queue->completion) add_completion( queue->completion, queue->comp_key, else if (async->queue && async->queue->completion)
cvalue, status, information ); add_completion( async->queue->completion, async->queue->comp_key, cvalue, status, information );
} }
/* store the result of the client-side async callback */ /* store the result of the client-side async callback */
...@@ -410,8 +417,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota ...@@ -410,8 +417,6 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
async->status = status; async->status = status;
if (status == STATUS_MORE_PROCESSING_REQUIRED) return; /* don't report the completion */ if (status == STATUS_MORE_PROCESSING_REQUIRED) return; /* don't report the completion */
if (async->queue && !async->data.apc && async->data.apc_context)
add_async_completion( async->queue, async->data.apc_context, status, total );
if (async->data.apc) if (async->data.apc)
{ {
apc_call_t data; apc_call_t data;
...@@ -423,7 +428,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota ...@@ -423,7 +428,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
data.user.args[2] = 0; data.user.args[2] = 0;
thread_queue_apc( async->thread, NULL, &data ); thread_queue_apc( async->thread, NULL, &data );
} }
else if (async->data.apc_context)
add_async_completion( async, async->data.apc_context, status, total );
if (async->event) set_event( async->event ); if (async->event) set_event( async->event );
else if (async->fd) set_fd_signaled( async->fd, 1 );
else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 ); else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
if (!async->signaled) if (!async->signaled)
{ {
...@@ -454,13 +463,15 @@ int async_waiting( struct async_queue *queue ) ...@@ -454,13 +463,15 @@ int async_waiting( struct async_queue *queue )
static int cancel_async( struct process *process, struct object *obj, struct thread *thread, client_ptr_t iosb ) static int cancel_async( struct process *process, struct object *obj, struct thread *thread, client_ptr_t iosb )
{ {
struct async *async; struct async *async;
struct fd *fd;
int woken = 0; int woken = 0;
restart: restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry ) LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{ {
if (async->status == STATUS_CANCELLED) continue; if (async->status == STATUS_CANCELLED) continue;
if ((!obj || (async->queue && async->queue->fd && get_fd_user( async->queue->fd ) == obj)) && fd = async->queue ? async->queue->fd : async->fd;
if ((!obj || (fd && get_fd_user( fd ) == obj)) &&
(!thread || async->thread == thread) && (!thread || async->thread == thread) &&
(!iosb || async->data.iosb == iosb)) (!iosb || async->data.iosb == iosb))
{ {
......
...@@ -1246,7 +1246,7 @@ DECL_HANDLER(read_directory_changes) ...@@ -1246,7 +1246,7 @@ DECL_HANDLER(read_directory_changes)
return; return;
/* requests don't timeout */ /* requests don't timeout */
if (!(async = create_async( current, &req->async, NULL ))) goto end; if (!(async = create_async( dir->fd, current, &req->async, NULL ))) goto end;
if (!fd_queue_async( dir->fd, async, ASYNC_TYPE_WAIT )) goto end; if (!fd_queue_async( dir->fd, async, ASYNC_TYPE_WAIT )) goto end;
/* assign it once */ /* assign it once */
......
...@@ -2373,7 +2373,7 @@ DECL_HANDLER(flush) ...@@ -2373,7 +2373,7 @@ DECL_HANDLER(flush)
if (!fd) return; if (!fd) return;
async = create_async( current, &req->async, NULL ); async = create_async( fd, current, &req->async, NULL );
if (async) if (async)
{ {
reply->event = fd->fd_ops->flush( fd, async ); reply->event = fd->fd_ops->flush( fd, async );
...@@ -2449,7 +2449,7 @@ DECL_HANDLER(read) ...@@ -2449,7 +2449,7 @@ DECL_HANDLER(read)
if (!fd) return; if (!fd) return;
if ((async = create_request_async( current, &req->async ))) if ((async = create_request_async( fd, &req->async )))
{ {
reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ), NULL ); reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ), NULL );
reply->options = fd->options; reply->options = fd->options;
...@@ -2466,7 +2466,7 @@ DECL_HANDLER(write) ...@@ -2466,7 +2466,7 @@ DECL_HANDLER(write)
if (!fd) return; if (!fd) return;
if ((async = create_request_async( current, &req->async ))) if ((async = create_request_async( fd, &req->async )))
{ {
reply->wait = async_handoff( async, fd->fd_ops->write( fd, async, req->pos ), &reply->size ); reply->wait = async_handoff( async, fd->fd_ops->write( fd, async, req->pos ), &reply->size );
reply->options = fd->options; reply->options = fd->options;
...@@ -2487,7 +2487,7 @@ DECL_HANDLER(ioctl) ...@@ -2487,7 +2487,7 @@ DECL_HANDLER(ioctl)
if ((iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() ))) if ((iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() )))
{ {
if ((async = create_async( current, &req->async, iosb ))) if ((async = create_async( fd, current, &req->async, iosb )))
{ {
reply->wait = fd->fd_ops->ioctl( fd, req->code, async ); reply->wait = fd->fd_ops->ioctl( fd, req->code, async );
reply->options = fd->options; reply->options = fd->options;
...@@ -2520,7 +2520,7 @@ DECL_HANDLER(register_async) ...@@ -2520,7 +2520,7 @@ DECL_HANDLER(register_async)
if ((fd = get_handle_fd_obj( current->process, req->async.handle, access ))) if ((fd = get_handle_fd_obj( current->process, req->async.handle, access )))
{ {
if (get_unix_fd( fd ) != -1 && (async = create_async( current, &req->async, NULL ))) if (get_unix_fd( fd ) != -1 && (async = create_async( fd, current, &req->async, NULL )))
{ {
fd->fd_ops->queue_async( fd, async, req->type, req->count ); fd->fd_ops->queue_async( fd, async, req->type, req->count );
release_object( async ); release_object( async );
......
...@@ -175,8 +175,8 @@ extern struct object *create_serial( struct fd *fd ); ...@@ -175,8 +175,8 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */ /* async I/O functions */
extern struct async_queue *create_async_queue( struct fd *fd ); extern struct async_queue *create_async_queue( struct fd *fd );
extern void free_async_queue( struct async_queue *queue ); 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_async( struct fd *fd, 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 struct async *create_request_async( struct fd *fd, const async_data_t *data );
extern obj_handle_t async_handoff( struct async *async, int success, data_size_t *result ); extern obj_handle_t async_handoff( struct async *async, int success, data_size_t *result );
extern void queue_async( struct async_queue *queue, struct async *async ); 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_timeout( struct async *async, timeout_t timeout, unsigned int status );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment