wine-staging/patches/kernel32-SetFileCompletionNotificationModes/0006-server-Skip-async-completion-when-possible.patch
2017-07-08 23:09:53 +02:00

133 lines
5.4 KiB
Diff

From fcc8dc4d71db746ccc4b974eae02edd222d23313 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 9 Apr 2017 03:13:25 +0200
Subject: server: Skip async completion when possible.
---
dlls/ntdll/tests/pipe.c | 2 --
server/async.c | 10 ++++++++--
server/fd.c | 8 ++++----
server/file.h | 2 +-
4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
index bda9a144ade..aa240edea21 100644
--- a/dlls/ntdll/tests/pipe.c
+++ b/dlls/ntdll/tests/pipe.c
@@ -389,9 +389,7 @@ static void test_completion(void)
pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
- todo_wine
ok(!ret, "GetQueuedCompletionStatus succeeded\n");
- todo_wine
ok(pov == NULL, "expected NULL, got %p\n", pov);
CloseHandle(ov.hEvent);
diff --git a/server/async.c b/server/async.c
index 020580728de..08daa9a2304 100644
--- a/server/async.c
+++ b/server/async.c
@@ -53,6 +53,7 @@ struct async
int direct_result; /* a flag if we're passing result directly from request instead of APC */
struct completion *completion; /* completion associated with fd */
apc_param_t comp_key; /* completion key associated with fd */
+ unsigned int comp_flags; /* completion flags */
};
static void async_dump( struct object *obj, int verbose );
@@ -237,6 +238,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da
async->wait_handle = 0;
async->direct_result = 0;
async->completion = NULL;
+ async->comp_flags = 0;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
else async->iosb = NULL;
@@ -249,7 +251,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da
/* create an async associated with iosb for async-based requests
* returned async must be passed to async_handoff */
-struct async *create_request_async( struct fd *fd, const async_data_t *data )
+struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data )
{
struct async *async;
struct iosb *iosb;
@@ -267,6 +269,7 @@ struct async *create_request_async( struct fd *fd, const async_data_t *data )
return NULL;
}
async->direct_result = 1;
+ async->comp_flags = comp_flags;
}
return async;
}
@@ -368,8 +371,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
data.user.args[2] = 0;
thread_queue_apc( async->thread, NULL, &data );
}
- else if (async->data.apc_context)
+ else if (async->data.apc_context && (!async->direct_result ||
+ !(async->comp_flags & COMPLETION_SKIP_ON_SUCCESS)))
+ {
add_async_completion( async, async->data.apc_context, status, total );
+ }
if (async->event) set_event( async->event );
else if (async->fd) set_fd_signaled( async->fd, 1 );
diff --git a/server/fd.c b/server/fd.c
index 18b1e04d448..d8f066c7219 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2374,7 +2374,7 @@ DECL_HANDLER(flush)
if (!fd) return;
- if ((async = create_request_async( fd, &req->async )))
+ if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->event = async_handoff( async, fd->fd_ops->flush( fd, async ), NULL );
release_object( async );
@@ -2449,7 +2449,7 @@ DECL_HANDLER(read)
if (!fd) return;
- if ((async = create_request_async( fd, &req->async )))
+ if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ), NULL );
reply->options = fd->options;
@@ -2466,7 +2466,7 @@ DECL_HANDLER(write)
if (!fd) return;
- if ((async = create_request_async( fd, &req->async )))
+ if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->write( fd, async, req->pos ), &reply->size );
reply->options = fd->options;
@@ -2484,7 +2484,7 @@ DECL_HANDLER(ioctl)
if (!fd) return;
- if ((async = create_request_async( fd, &req->async )))
+ if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->ioctl( fd, req->code, async ), NULL );
reply->options = fd->options;
diff --git a/server/file.h b/server/file.h
index fa41654e6b6..33b42554534 100644
--- a/server/file.h
+++ b/server/file.h
@@ -180,7 +180,7 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */
extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb );
-extern struct async *create_request_async( struct fd *fd, const async_data_t *data );
+extern struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data );
extern obj_handle_t async_handoff( struct async *async, int success, data_size_t *result );
extern void queue_async( struct async_queue *queue, struct async *async );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
--
2.13.1