server: Store async list in process object and use that to find async in cansel_async request.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2016-12-01 12:10:23 +01:00 committed by Alexandre Julliard
parent d1064669f4
commit 055918c982
6 changed files with 34 additions and 48 deletions

View File

@ -31,12 +31,15 @@
#include "object.h"
#include "file.h"
#include "request.h"
#include "process.h"
#include "handle.h"
struct async
{
struct object obj; /* object header */
struct thread *thread; /* owning thread */
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 */
unsigned int status; /* current status */
struct timeout_user *timeout;
@ -132,6 +135,7 @@ static void async_destroy( struct object *obj )
struct async *async = (struct async *)obj;
assert( obj->ops == &async_ops );
list_remove( &async->process_entry );
list_remove( &async->queue_entry );
async_reselect( async );
@ -244,6 +248,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
async->signaled = 0;
list_add_tail( &queue->queue, &async->queue_entry );
list_add_tail( &thread->process->asyncs, &async->process_entry );
grab_object( async );
if (queue->fd) set_fd_signaled( queue->fd, 0 );
@ -343,23 +348,22 @@ int async_waiting( struct async_queue *queue )
return async->status == STATUS_PENDING;
}
int async_wake_up_by( struct async_queue *queue, struct process *process,
struct thread *thread, client_ptr_t iosb, unsigned int status )
static int cancel_async( struct process *process, struct object *obj, struct thread *thread, client_ptr_t iosb )
{
struct list *ptr, *next;
struct async *async;
int woken = 0;
if (!queue || (!process && !thread && !iosb)) return 0;
LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{
struct async *async = LIST_ENTRY( ptr, struct async, queue_entry );
if ( (!process || async->thread->process == process) &&
(!thread || async->thread == thread) &&
(!iosb || async->data.iosb == iosb) )
if (async->status == STATUS_CANCELLED) continue;
if ((!obj || (async->queue->fd && get_fd_user( async->queue->fd ) == obj)) &&
(!thread || async->thread == thread) &&
(!iosb || async->data.iosb == iosb))
{
async_terminate( async, status );
async_terminate( async, STATUS_CANCELLED );
woken++;
goto restart;
}
}
return woken;
@ -379,3 +383,17 @@ void async_wake_up( struct async_queue *queue, unsigned int status )
if (status == STATUS_ALERTED) break; /* only wake up the first one */
}
}
/* cancels all async I/O */
DECL_HANDLER(cancel_async)
{
struct object *obj = get_handle_obj( current->process, req->handle, 0, NULL );
struct thread *thread = req->only_thread ? current : NULL;
if (obj)
{
int count = cancel_async( current->process, obj, thread, req->iosb );
if (!count && req->iosb) set_error( STATUS_NOT_FOUND );
release_object( obj );
}
}

View File

@ -2118,12 +2118,7 @@ void default_fd_reselect_async( struct fd *fd, struct async_queue *queue )
/* default cancel_async() fd routine */
int default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
{
int n = 0;
n += async_wake_up_by( fd->read_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( fd->write_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( fd->wait_q, process, thread, iosb, STATUS_CANCELLED );
return n;
return 0;
}
static inline int is_valid_mounted_device( struct stat *st )
@ -2519,20 +2514,6 @@ DECL_HANDLER(register_async)
}
}
/* cancels all async I/O */
DECL_HANDLER(cancel_async)
{
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
struct thread *thread = req->only_thread ? current : NULL;
if (fd)
{
int count = fd->fd_ops->cancel_async( fd, current->process, thread, req->iosb );
if (!count && req->iosb) set_error( STATUS_NOT_FOUND );
release_object( fd );
}
}
/* attach completion object to a fd */
DECL_HANDLER(set_completion_info)
{

View File

@ -175,8 +175,6 @@ extern void async_set_result( struct object *obj, unsigned int status,
extern int async_queued( struct async_queue *queue );
extern int async_waiting( struct async_queue *queue );
extern void async_terminate( struct async *async, unsigned int status );
extern int async_wake_up_by( struct async_queue *queue, struct process *process,
struct thread *thread, client_ptr_t iosb, unsigned int status );
extern void async_wake_up( struct async_queue *queue, unsigned int status );
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
extern void fd_copy_completion( struct fd *src, struct fd *dst );

View File

@ -535,6 +535,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process->rawinput_kbd = NULL;
list_init( &process->thread_list );
list_init( &process->locks );
list_init( &process->asyncs );
list_init( &process->classes );
list_init( &process->dlls );
list_init( &process->rawinput_devices );
@ -614,6 +615,7 @@ static void process_destroy( struct object *obj )
/* we can't have a thread remaining */
assert( list_empty( &process->thread_list ));
assert( list_empty( &process->asyncs ));
assert( !process->sigkill_timeout ); /* timeout should hold a reference to the process */

View File

@ -78,6 +78,7 @@ struct process
unsigned int is_terminating:1;/* is process terminating? */
struct job *job; /* job object ascoicated with this process */
struct list job_entry; /* list entry for job object */
struct list asyncs; /* list of async object owned by the process */
struct list locks; /* list of file locks owned by the process */
struct list classes; /* window classes owned by the process */
struct console_input*console; /* console input */

View File

@ -132,7 +132,6 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd );
static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking );
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
static int sock_get_ntstatus( int err );
static int sock_get_error( int err );
@ -171,7 +170,7 @@ static const struct fd_ops sock_fd_ops =
sock_ioctl, /* ioctl */
sock_queue_async, /* queue_async */
sock_reselect_async, /* reselect_async */
sock_cancel_async /* cancel_async */
default_fd_cancel_async /* cancel_async */
};
@ -611,19 +610,6 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
sock_reselect( sock );
}
static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
{
struct sock *sock = get_fd_user( fd );
int n = 0;
assert( sock->obj.ops == &sock_ops );
n += async_wake_up_by( sock->read_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( sock->write_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( sock->ifchange_q, process, thread, iosb, STATUS_CANCELLED );
return n;
}
static struct fd *sock_get_fd( struct object *obj )
{
struct sock *sock = (struct sock *)obj;