Mike Kaplinskiy : server: Change cancel_async to take an optional iosb and only_thread.
Alexandre Julliard
julliard at winehq.org
Tue Aug 18 10:01:20 CDT 2009
Module: wine
Branch: master
Commit: b05774ee7e92143fb6b763247c3ed5e2a1b521d2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b05774ee7e92143fb6b763247c3ed5e2a1b521d2
Author: Mike Kaplinskiy <mike.kaplinskiy at gmail.com>
Date: Sun Aug 9 00:08:27 2009 -0400
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 c7566ea..c926f6d 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 91f0c44..73cd76d 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 a57001a..d2da624 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 77de546..f59ec9e 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 e871736..1dcc042 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 4fc3bd6..a0efd2d 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 baaa9df..71d8ccb 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 d24f653..be3f1c6 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 },
More information about the wine-cvs
mailing list