diff mbox

[5/6] main-loop: replace WaitForMultipleObjects with g_poll

Message ID 1332236961-22743-6-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini March 20, 2012, 9:49 a.m. UTC
On w32, glib implements g_poll using WaitForMultipleObjects
or MsgWaitForMultipleObjects.  This means that we can simplify
our code by switching to g_poll, and at the same time prepare for
adding back glib sources.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 main-loop.c |   40 +++++++++++++++++-----------------------
 1 files changed, 17 insertions(+), 23 deletions(-)

Comments

Blue Swirl April 4, 2012, 8:44 p.m. UTC | #1
On Tue, Mar 20, 2012 at 09:49, Paolo Bonzini <pbonzini@redhat.com> wrote:
> On w32, glib implements g_poll using WaitForMultipleObjects
> or MsgWaitForMultipleObjects.  This means that we can simplify
> our code by switching to g_poll, and at the same time prepare for
> adding back glib sources.

Unfortunately g_poll does not seem to be available in glib-2.0:
  CC    main-loop.o
/src/qemu/main-loop.c: In function 'os_host_main_loop_wait':
/src/qemu/main-loop.c:438: warning: implicit declaration of function 'g_poll'
/src/qemu/main-loop.c:438: warning: nested extern declaration of 'g_poll'
  LINK  qemu-img.exe
main-loop.o: In function `os_host_main_loop_wait':
/src/qemu/main-loop.c:438: undefined reference to `_g_poll'

>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  main-loop.c |   40 +++++++++++++++++-----------------------
>  1 files changed, 17 insertions(+), 23 deletions(-)
>
> diff --git a/main-loop.c b/main-loop.c
> index 7364074..4d02568 100644
> --- a/main-loop.c
> +++ b/main-loop.c
> @@ -220,9 +220,9 @@ int main_loop_init(void)
>
>  static fd_set rfds, wfds, xfds;
>  static int nfds;
> +static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
>
>  #ifndef _WIN32
> -static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
>  static int n_poll_fds;
>  static int max_priority;
>
> @@ -351,6 +351,7 @@ void qemu_del_polling_cb(PollingFunc *func, void *opaque)
>  /* Wait objects support */
>  typedef struct WaitObjects {
>     int num;
> +    int revents[MAXIMUM_WAIT_OBJECTS + 1];
>     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
>     WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
>     void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
> @@ -367,6 +368,7 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
>     w->events[w->num] = handle;
>     w->func[w->num] = func;
>     w->opaque[w->num] = opaque;
> +    w->revents[w->num] = 0;
>     w->num++;
>     return 0;
>  }
> @@ -385,6 +387,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
>             w->events[i] = w->events[i + 1];
>             w->func[i] = w->func[i + 1];
>             w->opaque[i] = w->opaque[i + 1];
> +            w->revents[i] = w->revents[i + 1];
>         }
>     }
>     if (found) {
> @@ -400,9 +403,8 @@ void qemu_fd_register(int fd)
>
>  static int os_host_main_loop_wait(int timeout)
>  {
> -    int ret, ret2, i;
> +    int ret, i;
>     PollingEntry *pe;
> -    int err;
>     WaitObjects *w = &wait_objects;
>     static struct timeval tv0;
>
> @@ -422,33 +424,25 @@ static int os_host_main_loop_wait(int timeout)
>         }
>     }
>
> +    for (i = 0; i < w->num; i++) {
> +        poll_fds[i].fd = (DWORD) w->events[i];
> +        poll_fds[i].events = G_IO_IN;
> +    }
> +
>     qemu_mutex_unlock_iothread();
> -    ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
> +    ret = g_poll(poll_fds, w->num, timeout);
>     qemu_mutex_lock_iothread();
> -    if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
> -        if (w->func[ret - WAIT_OBJECT_0]) {
> -            w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
> +    if (ret > 0) {
> +        for (i = 0; i < w->num; i++) {
> +            w->revents[i] = poll_fds[i].revents;
>         }
> -
> -        /* Check for additional signaled events */
> -        for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
> -            /* Check if event is signaled */
> -            ret2 = WaitForSingleObject(w->events[i], 0);
> -            if (ret2 == WAIT_OBJECT_0) {
> -                if (w->func[i]) {
> -                    w->func[i](w->opaque[i]);
> -                }
> -            } else if (ret2 != WAIT_TIMEOUT) {
> -                err = GetLastError();
> -                fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
> +        for (i = 0; i < w->num; i++) {
> +            if (w->revents[i] && w->func[i]) {
> +                w->func[i](w->opaque[i]);
>             }
>         }
> -    } else if (ret != WAIT_TIMEOUT) {
> -        err = GetLastError();
> -        fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
>     }
>
> -
>     /* If an edge-triggered socket event occurred, select will return a
>      * positive result on the next iteration.  We do not need to do anything
>      * here.
> --
> 1.7.7.6
>
>
>
Peter Maydell April 4, 2012, 9:07 p.m. UTC | #2
On 4 April 2012 21:44, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Tue, Mar 20, 2012 at 09:49, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> On w32, glib implements g_poll using WaitForMultipleObjects
>> or MsgWaitForMultipleObjects.  This means that we can simplify
>> our code by switching to g_poll, and at the same time prepare for
>> adding back glib sources.
>
> Unfortunately g_poll does not seem to be available in glib-2.0:

Looks like it appeared in glib 2.19. We could maybe use an
autobuilder configured for whatever the lowest glib version
we support is, given how high the API churn seems to be :-/

-- PMM
Paolo Bonzini April 5, 2012, 8:12 a.m. UTC | #3
----- Messaggio originale -----
> Da: "Blue Swirl" <blauwirbel@gmail.com>
> A: "Paolo Bonzini" <pbonzini@redhat.com>
> Cc: qemu-devel@nongnu.org, sw@weilnetz.de
> Inviato: Mercoledì, 4 aprile 2012 22:44:12
> Oggetto: Re: [Qemu-devel] [PATCH 5/6] main-loop: replace WaitForMultipleObjects with g_poll
> 
> On Tue, Mar 20, 2012 at 09:49, Paolo Bonzini <pbonzini@redhat.com>
> wrote:
> > On w32, glib implements g_poll using WaitForMultipleObjects
> > or MsgWaitForMultipleObjects.  This means that we can simplify
> > our code by switching to g_poll, and at the same time prepare for
> > adding back glib sources.
> 
> Unfortunately g_poll does not seem to be available in glib-2.0:
>   CC    main-loop.o
> /src/qemu/main-loop.c: In function 'os_host_main_loop_wait':
> /src/qemu/main-loop.c:438: warning: implicit declaration of function
> 'g_poll'
> /src/qemu/main-loop.c:438: warning: nested extern declaration of
> 'g_poll'
>   LINK  qemu-img.exe
> main-loop.o: In function `os_host_main_loop_wait':
> /src/qemu/main-loop.c:438: undefined reference to `_g_poll'

Supporting old glibs makes sense on Linux where we have enterprise
distributions to support, but not on Windows where glib is going to
be bundled with the executable anyway.  If anyone is interested they
can simply lift g_poll from glib and put it somewhere in the QEMU
sources.  I don't care enough; until we decide what to do, applying
patches 2-4 will fix some of the breakage.

(Also, the lowest common denominator for Linux would be 2.12, not 2.0.
Win32 g_poll was not available until 2.20).

Paolo
Peter Maydell April 5, 2012, 8:48 a.m. UTC | #4
On 5 April 2012 09:12, Paolo Bonzini <pbonzini@redhat.com> wrote:
> (Also, the lowest common denominator for Linux would be 2.12, not 2.0.

...this doesn't seem to be what configure checks for? AFAICT it
just wants something providing gthread-2.0.

-- PMM
Paolo Bonzini April 5, 2012, 8:56 a.m. UTC | #5
> On 5 April 2012 09:12, Paolo Bonzini <pbonzini@redhat.com> wrote:
> > (Also, the lowest common denominator for Linux would be 2.12, not
> > 2.0.
> 
> ...this doesn't seem to be what configure checks for? AFAICT it
> just wants something providing gthread-2.0.

Yes, that's correct.  Our checks are way too strict.

Paolo
diff mbox

Patch

diff --git a/main-loop.c b/main-loop.c
index 7364074..4d02568 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -220,9 +220,9 @@  int main_loop_init(void)
 
 static fd_set rfds, wfds, xfds;
 static int nfds;
+static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
 
 #ifndef _WIN32
-static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
 static int n_poll_fds;
 static int max_priority;
 
@@ -351,6 +351,7 @@  void qemu_del_polling_cb(PollingFunc *func, void *opaque)
 /* Wait objects support */
 typedef struct WaitObjects {
     int num;
+    int revents[MAXIMUM_WAIT_OBJECTS + 1];
     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
     WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
     void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
@@ -367,6 +368,7 @@  int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     w->events[w->num] = handle;
     w->func[w->num] = func;
     w->opaque[w->num] = opaque;
+    w->revents[w->num] = 0;
     w->num++;
     return 0;
 }
@@ -385,6 +387,7 @@  void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
             w->events[i] = w->events[i + 1];
             w->func[i] = w->func[i + 1];
             w->opaque[i] = w->opaque[i + 1];
+            w->revents[i] = w->revents[i + 1];
         }
     }
     if (found) {
@@ -400,9 +403,8 @@  void qemu_fd_register(int fd)
 
 static int os_host_main_loop_wait(int timeout)
 {
-    int ret, ret2, i;
+    int ret, i;
     PollingEntry *pe;
-    int err;
     WaitObjects *w = &wait_objects;
     static struct timeval tv0;
 
@@ -422,33 +424,25 @@  static int os_host_main_loop_wait(int timeout)
         }
     }
 
+    for (i = 0; i < w->num; i++) {
+        poll_fds[i].fd = (DWORD) w->events[i];
+        poll_fds[i].events = G_IO_IN;
+    }
+
     qemu_mutex_unlock_iothread();
-    ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
+    ret = g_poll(poll_fds, w->num, timeout);
     qemu_mutex_lock_iothread();
-    if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-        if (w->func[ret - WAIT_OBJECT_0]) {
-            w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+    if (ret > 0) {
+        for (i = 0; i < w->num; i++) {
+            w->revents[i] = poll_fds[i].revents;
         }
-
-        /* Check for additional signaled events */
-        for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-            /* Check if event is signaled */
-            ret2 = WaitForSingleObject(w->events[i], 0);
-            if (ret2 == WAIT_OBJECT_0) {
-                if (w->func[i]) {
-                    w->func[i](w->opaque[i]);
-                }
-            } else if (ret2 != WAIT_TIMEOUT) {
-                err = GetLastError();
-                fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+        for (i = 0; i < w->num; i++) {
+            if (w->revents[i] && w->func[i]) {
+                w->func[i](w->opaque[i]);
             }
         }
-    } else if (ret != WAIT_TIMEOUT) {
-        err = GetLastError();
-        fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
     }
 
-
     /* If an edge-triggered socket event occurred, select will return a
      * positive result on the next iteration.  We do not need to do anything
      * here.