]> git.proxmox.com Git - qemu.git/blobdiff - aio-win32.c
smc91c111: Fix receive starvation
[qemu.git] / aio-win32.c
index 78b2801c5112af0dd30b277a0b77f79c102f72f3..f9cfbb75aca8ad9af7b50fc0338065f286dc81f8 100644 (file)
@@ -95,6 +95,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
     bool progress;
     int count;
+    int timeout;
 
     progress = false;
 
@@ -108,6 +109,9 @@ bool aio_poll(AioContext *ctx, bool blocking)
         progress = true;
     }
 
+    /* Run timers */
+    progress |= timerlistgroup_run_timers(&ctx->tlg);
+
     /*
      * Then dispatch any pending callbacks from the GSource.
      *
@@ -125,7 +129,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
             node->io_notify(node->e);
 
             /* aio_notify() does not count as progress */
-            if (node->opaque != &ctx->notifier) {
+            if (node->e != &ctx->notifier) {
                 progress = true;
             }
         }
@@ -164,8 +168,11 @@ bool aio_poll(AioContext *ctx, bool blocking)
 
     /* wait until next event */
     while (count > 0) {
-        int timeout = blocking ? INFINITE : 0;
-        int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
+        int ret;
+
+        timeout = blocking ?
+            qemu_timeout_ns_to_ms(timerlistgroup_deadline_ns(&ctx->tlg)) : 0;
+        ret = WaitForMultipleObjects(count, events, FALSE, timeout);
 
         /* if we have any signaled events, dispatch event */
         if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
@@ -188,7 +195,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
                 node->io_notify(node->e);
 
                 /* aio_notify() does not count as progress */
-                if (node->opaque != &ctx->notifier) {
+                if (node->e != &ctx->notifier) {
                     progress = true;
                 }
             }
@@ -208,5 +215,14 @@ bool aio_poll(AioContext *ctx, bool blocking)
         events[ret - WAIT_OBJECT_0] = events[--count];
     }
 
+    if (blocking) {
+        /* Run the timers a second time. We do this because otherwise aio_wait
+         * will not note progress - and will stop a drain early - if we have
+         * a timer that was not ready to run entering g_poll but is ready
+         * after g_poll. This will only do anything if a timer has expired.
+         */
+        progress |= timerlistgroup_run_timers(&ctx->tlg);
+    }
+
     return progress;
 }