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

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-06-26 12:19:28 +02:00 committed by Alexandre Julliard
parent 2bd828b13c
commit fa0dfe5967
4 changed files with 31 additions and 20 deletions

View File

@ -41,6 +41,7 @@ struct async
struct list queue_entry; /* entry in async queue list */
struct list process_entry; /* entry in process list */
struct async_queue *queue; /* queue containing this async */
struct fd *fd; /* fd associated with an unqueued async */
unsigned int status; /* current status */
struct timeout_user *timeout;
unsigned int timeout_status; /* status to report upon timeout */
@ -167,6 +168,7 @@ static void async_destroy( struct object *obj )
release_object( async->queue );
}
if (async->fd) release_object( async->fd );
if (async->timeout) remove_timeout_user( async->timeout );
if (async->event) release_object( async->event );
if (async->iosb) release_object( async->iosb );
@ -257,8 +259,10 @@ void free_async_queue( struct async_queue *queue )
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 );
list_add_tail( &queue->queue, &async->queue_entry );
@ -266,7 +270,7 @@ void queue_async( struct async_queue *queue, struct async *async )
}
/* 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 async *async;
@ -286,6 +290,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
async->data = *data;
async->timeout = NULL;
async->queue = NULL;
async->fd = (struct fd *)grab_object( fd );
async->signaled = 0;
async->wait_handle = 0;
async->direct_result = 0;
@ -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
* 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 iosb *iosb;
@ -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() )))
return NULL;
async = create_async( current, data, iosb );
async = create_async( fd, current, data, iosb );
release_object( iosb );
if (async)
{
@ -365,13 +370,15 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta
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 )
{
if (queue->fd)
struct fd *fd = async->queue ? async->queue->fd : async->fd;
if (fd)
{
apc_param_t ckey;
struct completion *completion = fd_get_completion( queue->fd, &ckey );
struct completion *completion = fd_get_completion( fd, &ckey );
if (completion)
{
@ -379,8 +386,8 @@ static void add_async_completion( struct async_queue *queue, apc_param_t cvalue,
release_object( completion );
}
}
else if (queue->completion) add_completion( queue->completion, queue->comp_key,
cvalue, status, information );
else if (async->queue && async->queue->completion)
add_completion( async->queue->completion, async->queue->comp_key, cvalue, status, information );
}
/* 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
async->status = status;
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)
{
apc_call_t data;
@ -423,7 +428,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
data.user.args[2] = 0;
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 );
else if (async->fd) set_fd_signaled( async->fd, 1 );
else if (async->queue && async->queue->fd) set_fd_signaled( async->queue->fd, 1 );
if (!async->signaled)
{
@ -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 )
{
struct async *async;
struct fd *fd;
int woken = 0;
restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{
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) &&
(!iosb || async->data.iosb == iosb))
{

View File

@ -1246,7 +1246,7 @@ DECL_HANDLER(read_directory_changes)
return;
/* 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;
/* assign it once */

View File

@ -2373,7 +2373,7 @@ DECL_HANDLER(flush)
if (!fd) return;
async = create_async( current, &req->async, NULL );
async = create_async( fd, current, &req->async, NULL );
if (async)
{
reply->event = fd->fd_ops->flush( fd, async );
@ -2449,7 +2449,7 @@ DECL_HANDLER(read)
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->options = fd->options;
@ -2466,7 +2466,7 @@ DECL_HANDLER(write)
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->options = fd->options;
@ -2487,7 +2487,7 @@ DECL_HANDLER(ioctl)
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->options = fd->options;
@ -2520,7 +2520,7 @@ DECL_HANDLER(register_async)
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 );
release_object( async );

View File

@ -175,8 +175,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, 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_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb );
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 void queue_async( struct async_queue *queue, struct async *async );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );