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