From b05774ee7e92143fb6b763247c3ed5e2a1b521d2 Mon Sep 17 00:00:00 2001 From: Mike Kaplinskiy Date: Sun, 9 Aug 2009 00:08:27 -0400 Subject: [PATCH] server: Change cancel_async to take an optional iosb and only_thread. --- include/wine/server_protocol.h | 5 ++++- server/async.c | 22 ++++++++++++++++++++++ server/fd.c | 15 ++++++++++----- server/file.h | 6 ++++-- server/protocol.def | 2 ++ server/request.h | 4 +++- server/sock.c | 11 +++++++---- server/trace.c | 4 +++- 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index c7566ead0db..c926f6d8744 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2859,6 +2859,9 @@ struct cancel_async_request { struct request_header __header; obj_handle_t handle; + client_ptr_t iosb; + int only_thread; + char __pad_28[4]; }; struct cancel_async_reply { @@ -5312,6 +5315,6 @@ union generic_reply struct set_window_layered_info_reply set_window_layered_info_reply; }; -#define SERVER_PROTOCOL_VERSION 387 +#define SERVER_PROTOCOL_VERSION 388 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/async.c b/server/async.c index 91f0c44403e..73cd76de3e1 100644 --- a/server/async.c +++ b/server/async.c @@ -288,6 +288,28 @@ 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 ) +{ + struct list *ptr, *next; + int woken = 0; + + if (!queue || (!process && !thread && !iosb)) return 0; + + LIST_FOR_EACH_SAFE( ptr, next, &queue->queue ) + { + 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) ) + { + async_terminate( async, status ); + woken++; + } + } + return woken; +} + /* wake up async operations on the queue */ void async_wake_up( struct async_queue *queue, unsigned int status ) { diff --git a/server/fd.c b/server/fd.c index a57001a04c6..d2da6247ad7 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1856,11 +1856,15 @@ void default_fd_reselect_async( struct fd *fd, struct async_queue *queue ) } /* default cancel_async() fd routine */ -void default_fd_cancel_async( struct fd *fd ) +void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb ) { - async_wake_up( fd->read_q, STATUS_CANCELLED ); - async_wake_up( fd->write_q, STATUS_CANCELLED ); - async_wake_up( fd->wait_q, STATUS_CANCELLED ); + 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 ); + if (!n && iosb) + set_error( STATUS_NOT_FOUND ); } /* default flush() routine */ @@ -2064,10 +2068,11 @@ DECL_HANDLER(register_async) 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) { - if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd ); + if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd, current->process, thread, req->iosb ); release_object( fd ); } } diff --git a/server/file.h b/server/file.h index 77de546fe9d..f59ec9e4175 100644 --- a/server/file.h +++ b/server/file.h @@ -46,7 +46,7 @@ struct fd_ops /* selected events for async i/o need an update */ void (*reselect_async)( struct fd *, struct async_queue *queue ); /* cancel an async operation */ - void (*cancel_async)(struct fd *); + void (*cancel_async)(struct fd *, struct process *process, struct thread *thread, client_ptr_t iosb); }; /* file descriptor functions */ @@ -83,7 +83,7 @@ extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const as int blocking, const void *data, data_size_t size ); extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count ); extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue ); -extern void default_fd_cancel_async( struct fd *fd ); +extern void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb ); extern void no_flush( struct fd *fd, struct event **event ); extern void main_loop(void); extern void remove_process_locks( struct process *process ); @@ -143,6 +143,8 @@ extern void async_set_result( struct object *obj, unsigned int status, unsigned int total, client_ptr_t apc ); 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 ); diff --git a/server/protocol.def b/server/protocol.def index e871736f75f..1dcc04248d0 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2072,6 +2072,8 @@ enum message_type /* Cancel all async op on a fd */ @REQ(cancel_async) obj_handle_t handle; /* handle to comm port, socket or file */ + client_ptr_t iosb; /* I/O status block (NULL=all) */ + int only_thread; /* cancel matching this thread */ @END diff --git a/server/request.h b/server/request.h index 4fc3bd6a3c2..a0efd2d0b0e 100644 --- a/server/request.h +++ b/server/request.h @@ -1351,7 +1351,9 @@ C_ASSERT( FIELD_OFFSET(struct register_async_request, async) == 16 ); C_ASSERT( FIELD_OFFSET(struct register_async_request, count) == 56 ); C_ASSERT( sizeof(struct register_async_request) == 64 ); C_ASSERT( FIELD_OFFSET(struct cancel_async_request, handle) == 12 ); -C_ASSERT( sizeof(struct cancel_async_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct cancel_async_request, iosb) == 16 ); +C_ASSERT( FIELD_OFFSET(struct cancel_async_request, only_thread) == 24 ); +C_ASSERT( sizeof(struct cancel_async_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct ioctl_request, code) == 12 ); C_ASSERT( FIELD_OFFSET(struct ioctl_request, async) == 16 ); C_ASSERT( FIELD_OFFSET(struct ioctl_request, blocking) == 56 ); diff --git a/server/sock.c b/server/sock.c index baaa9df220a..71d8ccb42c8 100644 --- a/server/sock.c +++ b/server/sock.c @@ -97,7 +97,7 @@ static void sock_poll_event( struct fd *fd, int event ); static enum server_fd_type sock_get_fd_type( struct fd *fd ); 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 void sock_cancel_async( struct fd *fd ); +static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb ); static int sock_get_error( int err ); static void sock_set_error(void); @@ -538,13 +538,16 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue ) if (events) sock_try_event( sock, events ); } -static void sock_cancel_async( struct fd *fd ) +static void 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 ); - async_wake_up( sock->read_q, STATUS_CANCELLED ); - async_wake_up( sock->write_q, STATUS_CANCELLED ); + 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 ); + if (!n && iosb) + set_error( STATUS_NOT_FOUND ); } static struct fd *sock_get_fd( struct object *obj ) diff --git a/server/trace.c b/server/trace.c index d24f653251b..be3f1c68f23 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2568,6 +2568,8 @@ static void dump_register_async_request( const struct register_async_request *re static void dump_cancel_async_request( const struct cancel_async_request *req ) { fprintf( stderr, " handle=%04x", req->handle ); + dump_uint64( ", iosb=", &req->iosb ); + fprintf( stderr, ", only_thread=%d", req->only_thread ); } static void dump_ioctl_request( const struct ioctl_request *req ) @@ -4583,12 +4585,12 @@ static const struct { "IO_TIMEOUT", STATUS_IO_TIMEOUT }, { "KEY_DELETED", STATUS_KEY_DELETED }, { "MAPPED_FILE_SIZE_ZERO", STATUS_MAPPED_FILE_SIZE_ZERO }, - { "MEDIA_WRITE_PROTECTED", STATUS_MEDIA_WRITE_PROTECTED }, { "MUTANT_NOT_OWNED", STATUS_MUTANT_NOT_OWNED }, { "NAME_TOO_LONG", STATUS_NAME_TOO_LONG }, { "NOTIFY_ENUM_DIR", STATUS_NOTIFY_ENUM_DIR }, { "NOT_ALL_ASSIGNED", STATUS_NOT_ALL_ASSIGNED }, { "NOT_A_DIRECTORY", STATUS_NOT_A_DIRECTORY }, + { "NOT_FOUND", STATUS_NOT_FOUND }, { "NOT_IMPLEMENTED", STATUS_NOT_IMPLEMENTED }, { "NOT_REGISTRY_FILE", STATUS_NOT_REGISTRY_FILE }, { "NOT_SUPPORTED", STATUS_NOT_SUPPORTED }, -- 2.11.4.GIT