wine-staging/patches/kernel32-SetFileCompletionNotificationModes/0006-server-Skip-async-completion-when-possible.patch
2017-07-03 04:22:05 +02:00

122 lines
4.8 KiB
Diff

From 9fc1b0617a1bf5136389984b9931ab92a42e56dc 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 | 12 +++++++++++-
server/fd.c | 4 ++++
server/file.h | 1 +
4 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
index 6846b514dc2..a6f8135624a 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 f50cdc5a45a..d222287c30b 100644
--- a/server/async.c
+++ b/server/async.c
@@ -45,6 +45,7 @@ struct async
struct timeout_user *timeout;
unsigned int timeout_status; /* status to report upon timeout */
int signaled;
+ int skip_completion; /* skip completion */
struct event *event;
async_data_t data; /* data for async I/O call */
struct iosb *iosb; /* I/O status block */
@@ -180,6 +181,14 @@ static void async_queue_destroy( struct object *obj )
if (async_queue->completion) release_object( async_queue->completion );
}
+void async_skip_completion( struct async *async, int comp_flags )
+{
+ if (!async->data.user) return;
+ if (!(comp_flags & COMPLETION_SKIP_ON_SUCCESS)) return;
+ async->skip_completion = (async->status == STATUS_SUCCESS ||
+ async->status == STATUS_ALERTED);
+}
+
/* notifies client thread of new status of its async request */
void async_terminate( struct async *async, unsigned int status )
{
@@ -278,6 +287,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
async->queue = NULL;
async->signaled = 0;
async->wait_handle = 0;
+ async->skip_completion = 0;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
else async->iosb = NULL;
@@ -384,7 +394,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
async->status = status;
if (status == STATUS_MORE_PROCESSING_REQUIRED) return; /* don't report the completion */
- if (async->queue && !async->data.apc && async->data.apc_context)
+ if (async->queue && !async->data.apc && async->data.apc_context && !async->skip_completion)
add_async_completion( async->queue, async->data.apc_context, status, total );
if (async->data.apc)
{
diff --git a/server/fd.c b/server/fd.c
index a2640468644..75cb9bff945 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2381,6 +2381,7 @@ DECL_HANDLER(flush)
if (async)
{
reply->event = fd->fd_ops->flush( fd, async );
+ async_skip_completion( async, fd->comp_flags );
release_object( async );
}
release_object( fd );
@@ -2457,6 +2458,7 @@ DECL_HANDLER(read)
{
reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ) );
reply->options = fd->options;
+ async_skip_completion( async, fd->comp_flags );
release_object( async );
}
release_object( fd );
@@ -2478,6 +2480,7 @@ DECL_HANDLER(write)
{
reply->wait = fd->fd_ops->write( fd, async, req->pos );
reply->options = fd->options;
+ async_skip_completion( async, fd->comp_flags );
release_object( async );
}
release_object( iosb );
@@ -2501,6 +2504,7 @@ DECL_HANDLER(ioctl)
{
reply->wait = fd->fd_ops->ioctl( fd, req->code, async );
reply->options = fd->options;
+ async_skip_completion( async, fd->comp_flags );
release_object( async );
}
release_object( iosb );
diff --git a/server/file.h b/server/file.h
index 8cc4d3beab2..f4482982cfe 100644
--- a/server/file.h
+++ b/server/file.h
@@ -183,6 +183,7 @@ extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned
extern void async_set_result( struct object *obj, unsigned int status, apc_param_t total );
extern int async_queued( struct async_queue *queue );
extern int async_waiting( struct async_queue *queue );
+extern void async_skip_completion( struct async *async, int comp_flags );
extern void async_terminate( struct async *async, 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 );
--
2.13.1