Andrey Turkin : server: Store I/O completion information in async structure .

Alexandre Julliard julliard at winehq.org
Tue Dec 18 07:34:56 CST 2007


Module: wine
Branch: master
Commit: 3afbee521845443e1a757a1b0afbd6d0abccbd63
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3afbee521845443e1a757a1b0afbd6d0abccbd63

Author: Andrey Turkin <andrey.turkin at gmail.com>
Date:   Mon Dec 17 22:06:17 2007 +0300

server: Store I/O completion information in async structure.

This is to allow completions to be sent on handle close. Also this can
be helpful for AcceptEx/TransmitFile implementation.

---

 dlls/ntdll/tests/file.c |   14 +++++++++++++-
 server/async.c          |   12 ++++++------
 server/fd.c             |   10 +++++-----
 server/file.h           |    2 +-
 4 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 4e1833c..8d2ffc3 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -566,9 +566,21 @@ static void test_iocp_fileio(HANDLE h)
             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
         }
+
+        ReadFile( hPipeSrv, buf, sizeof(buf), &read, &o);
+        CloseHandle( hPipeSrv );
+        count = get_pending_msgs(h);
+        ok( count == 1, "Unexpected msg count: %ld\n", count );
+        if (get_msg(h))
+        {
+            ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
+            ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
+            /* wine sends wrong status here */
+            todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
+            ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
+        }
     }
 
-    CloseHandle( hPipeSrv );
     CloseHandle( hPipeClt );
 }
 
diff --git a/server/async.c b/server/async.c
index ae58636..ff5f7a6 100644
--- a/server/async.c
+++ b/server/async.c
@@ -42,6 +42,8 @@ struct async
     struct timeout_user *timeout;
     unsigned int         timeout_status;  /* status to report upon timeout */
     struct event        *event;
+    struct completion   *completion;
+    unsigned long        comp_key;
     async_data_t         data;            /* data for async I/O call */
 };
 
@@ -121,6 +123,7 @@ static void async_destroy( struct object *obj )
 
     if (async->timeout) remove_timeout_user( async->timeout );
     if (async->event) release_object( async->event );
+    if (async->completion) release_object( async->completion );
     release_object( async->queue );
     release_object( async->thread );
 }
@@ -146,10 +149,6 @@ void async_terminate( struct async *async, unsigned int status )
         return;
     }
 
-    /* send error completion event */
-    if (status != STATUS_ALERTED && async->data.cvalue && async->queue->fd)
-        fd_add_completion( async->queue->fd, async->data.cvalue, status, 0 );
-
     memset( &data, 0, sizeof(data) );
     data.type            = APC_ASYNC_IO;
     data.async_io.func   = async->data.callback;
@@ -214,6 +213,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
     async->data    = *data;
     async->timeout = NULL;
     async->queue   = (struct async_queue *)grab_object( queue );
+    fd_assign_completion( queue->fd, &async->completion, &async->comp_key );
 
     list_add_tail( &queue->queue, &async->queue_entry );
     grab_object( async );
@@ -257,8 +257,8 @@ void async_set_result( struct object *obj, unsigned int status, unsigned long to
         if (async->timeout) remove_timeout_user( async->timeout );
         async->timeout = NULL;
         async->status = status;
-        if (async->data.cvalue && async->queue->fd)
-            fd_add_completion( async->queue->fd, async->data.cvalue, status, total );
+        if (async->completion && async->data.cvalue)
+            add_completion( async->completion, async->comp_key, async->data.cvalue, status, total );
         if (async->data.apc)
         {
             apc_call_t data;
diff --git a/server/fd.c b/server/fd.c
index 95a0520..c7f20d5 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1922,11 +1922,10 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
     return fd;
 }
 
-/* add a completion result to a completion queue attached to the fd */
-void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information )
+void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key )
 {
-    if (fd->completion)
-        add_completion( fd->completion, fd->comp_key, cvalue, status, information );
+    *p_key = fd->comp_key;
+    *p_port = fd->completion ? (struct completion *)grab_object( fd->completion ) : NULL;
 }
 
 /* flush a file buffers */
@@ -2066,7 +2065,8 @@ DECL_HANDLER(add_fd_completion)
     struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
     if (fd)
     {
-        fd_add_completion( fd, req->cvalue, req->status, req->information );
+        if (fd->completion)
+            add_completion( fd->completion, fd->comp_key, req->cvalue, req->status, req->information );
         release_object( fd );
     }
 }
diff --git a/server/file.h b/server/file.h
index e444007..26d1702 100644
--- a/server/file.h
+++ b/server/file.h
@@ -139,7 +139,7 @@ extern void async_set_result( struct object *obj, unsigned int status, unsigned
 extern int async_waiting( struct async_queue *queue );
 extern void async_terminate( struct async *async, unsigned int status );
 extern void async_wake_up( struct async_queue *queue, unsigned int status );
-extern void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information );
+extern void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key );
 
 /* access rights that require Unix read permission */
 #define FILE_UNIX_READ_ACCESS (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)




More information about the wine-cvs mailing list