Paul Gofman : ntdll: Only queue IO callback if IO is pending in ioqueue_thread_proc().

Alexandre Julliard julliard at winehq.org
Wed Jul 28 15:37:41 CDT 2021


Module: wine
Branch: master
Commit: fa9bbe8a226e3b4cad078155887f25be280a87f5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=fa9bbe8a226e3b4cad078155887f25be280a87f5

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Wed Jul 28 01:07:00 2021 +0300

ntdll: Only queue IO callback if IO is pending in ioqueue_thread_proc().

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/tests/threadpool.c | 18 ++++++++++++++++++
 dlls/ntdll/threadpool.c       | 29 +++++++++++++++++------------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index 6b301eafcbd..986cbbcf8f1 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -2139,6 +2139,24 @@ static void test_tp_io(void)
     ok(!userdata.length, "got length %lu\n", userdata.length);
     ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
 
+    userdata.count = 0;
+    pTpStartAsyncIoOperation(io);
+    pTpCancelAsyncIoOperation(io);
+    ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+    ok(!ret, "wrong ret %d\n", ret);
+    ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+    ok(ret, "WriteFile() failed, error %u\n", GetLastError());
+    ok(GetLastError() == ERROR_IO_PENDING, "wrong error %u\n", GetLastError());
+
+    pTpWaitForIoCompletion(io, FALSE);
+    if (0)
+    {
+        /* Add a sleep to check that callback is not called later. Commented out to
+         * save the test time. */
+        Sleep(200);
+    }
+    ok(userdata.count == 0, "callback ran %u times\n", userdata.count);
+
     CloseHandle(ovl.hEvent);
     CloseHandle(client);
     CloseHandle(server);
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index b82d06e5e42..c27f6d4a145 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -1536,22 +1536,25 @@ static void CALLBACK ioqueue_thread_proc( void *param )
         {
             RtlEnterCriticalSection( &io->pool->cs );
 
-            --io->u.io.pending_count;
+            TRACE( "pending_count %u.\n", io->u.io.pending_count );
 
-            if (!array_reserve((void **)&io->u.io.completions, &io->u.io.completion_max,
-                    io->u.io.completion_count + 1, sizeof(*io->u.io.completions)))
+            if (io->u.io.pending_count)
             {
-                ERR("Failed to allocate memory.\n");
-                RtlLeaveCriticalSection( &io->pool->cs );
-                continue;
-            }
-
-            completion = &io->u.io.completions[io->u.io.completion_count++];
-            completion->iosb = iosb;
-            completion->cvalue = value;
+                --io->u.io.pending_count;
+                if (!array_reserve((void **)&io->u.io.completions, &io->u.io.completion_max,
+                        io->u.io.completion_count + 1, sizeof(*io->u.io.completions)))
+                {
+                    ERR( "Failed to allocate memory.\n" );
+                    RtlLeaveCriticalSection( &io->pool->cs );
+                    continue;
+                }
 
-            tp_object_submit( io, FALSE );
+                completion = &io->u.io.completions[io->u.io.completion_count++];
+                completion->iosb = iosb;
+                completion->cvalue = value;
 
+                tp_object_submit( io, FALSE );
+            }
             RtlLeaveCriticalSection( &io->pool->cs );
         }
 
@@ -2525,6 +2528,8 @@ void WINAPI TpCancelAsyncIoOperation( TP_IO *io )
 
     RtlEnterCriticalSection( &this->pool->cs );
 
+    TRACE("pending_count %u.\n", this->u.io.pending_count);
+
     this->u.io.pending_count--;
     if (object_is_finished( this, TRUE ))
         RtlWakeAllConditionVariable( &this->group_finished_event );




More information about the wine-cvs mailing list