]> code.delx.au - pulseaudio/blobdiff - src/pulse/mainloop.c
core: Proper poll() emulation to fix pacat and friends on Windows
[pulseaudio] / src / pulse / mainloop.c
index eaa41d5125807d561a815f731d7d93c87ee7b70c..725bdb4f3bfb863d4b6940ee9bd004375b0e4933 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 /***
   This file is part of PulseAudio.
 
@@ -8,7 +6,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
 #endif
 
 #include <stdio.h>
 #endif
 
 #include <stdio.h>
-#include <signal.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <string.h>
-#include <assert.h>
 #include <fcntl.h>
 #include <errno.h>
 
 #include <fcntl.h>
 #include <errno.h>
 
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#else
-#include "../pulsecore/poll.h"
-#endif
-
-#include "../pulsecore/winsock.h"
-
 #ifndef HAVE_PIPE
 #ifndef HAVE_PIPE
-#include "../pulsecore/pipe.h"
+#include <pulsecore/pipe.h>
 #endif
 
 #endif
 
-#include <pulsecore/core-error.h>
+#include <pulse/rtclock.h>
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/poll.h>
+#include <pulsecore/core-rtclock.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/i18n.h>
 #include <pulsecore/llist.h>
 #include <pulsecore/log.h>
 #include <pulsecore/llist.h>
 #include <pulsecore/log.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/socket.h>
+#include <pulsecore/macro.h>
 
 #include "mainloop.h"
 
 #include "mainloop.h"
+#include "internal.h"
 
 struct pa_io_event {
     pa_mainloop *mainloop;
 
 struct pa_io_event {
     pa_mainloop *mainloop;
-    int dead;
+    pa_bool_t dead:1;
 
     int fd;
     pa_io_event_flags_t events;
 
     int fd;
     pa_io_event_flags_t events;
@@ -74,10 +68,11 @@ struct pa_io_event {
 
 struct pa_time_event {
     pa_mainloop *mainloop;
 
 struct pa_time_event {
     pa_mainloop *mainloop;
-    int dead;
+    pa_bool_t dead:1;
 
 
-    int enabled;
-    struct timeval timeval;
+    pa_bool_t enabled:1;
+    pa_bool_t use_rtclock:1;
+    pa_usec_t time;
 
     pa_time_event_cb_t callback;
     void *userdata;
 
     pa_time_event_cb_t callback;
     void *userdata;
@@ -88,9 +83,9 @@ struct pa_time_event {
 
 struct pa_defer_event {
     pa_mainloop *mainloop;
 
 struct pa_defer_event {
     pa_mainloop *mainloop;
-    int dead;
+    pa_bool_t dead:1;
 
 
-    int enabled;
+    pa_bool_t enabled:1;
 
     pa_defer_event_cb_t callback;
     void *userdata;
 
     pa_defer_event_cb_t callback;
     void *userdata;
@@ -104,22 +99,24 @@ struct pa_mainloop {
     PA_LLIST_HEAD(pa_time_event, time_events);
     PA_LLIST_HEAD(pa_defer_event, defer_events);
 
     PA_LLIST_HEAD(pa_time_event, time_events);
     PA_LLIST_HEAD(pa_defer_event, defer_events);
 
-    int n_enabled_defer_events, n_enabled_time_events, n_io_events;
-    int io_events_please_scan, time_events_please_scan, defer_events_please_scan;
+    unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events;
+    unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan;
 
 
+    pa_bool_t rebuild_pollfds:1;
     struct pollfd *pollfds;
     unsigned max_pollfds, n_pollfds;
     struct pollfd *pollfds;
     unsigned max_pollfds, n_pollfds;
-    int rebuild_pollfds;
 
 
-    int prepared_timeout;
+    pa_usec_t prepared_timeout;
     pa_time_event *cached_next_time_event;
 
     pa_time_event *cached_next_time_event;
 
-    int quit, retval;
     pa_mainloop_api api;
 
     pa_mainloop_api api;
 
+    int retval;
+    pa_bool_t quit:1;
+
+    pa_bool_t wakeup_requested:1;
     int wakeup_pipe[2];
     int wakeup_pipe_type;
     int wakeup_pipe[2];
     int wakeup_pipe_type;
-    int wakeup_requested;
 
     enum {
         STATE_PASSIVE,
 
     enum {
         STATE_PASSIVE,
@@ -135,11 +132,11 @@ struct pa_mainloop {
 };
 
 static short map_flags_to_libc(pa_io_event_flags_t flags) {
 };
 
 static short map_flags_to_libc(pa_io_event_flags_t flags) {
-    return
-        (flags & PA_IO_EVENT_INPUT ? POLLIN : 0) |
-        (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
-        (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) |
-        (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0);
+    return (short)
+        ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) |
+         (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
+         (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) |
+         (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0));
 }
 
 static pa_io_event_flags_t map_flags_from_libc(short flags) {
 }
 
 static pa_io_event_flags_t map_flags_from_libc(short flags) {
@@ -152,7 +149,7 @@ static pa_io_event_flags_t map_flags_from_libc(short flags) {
 
 /* IO events */
 static pa_io_event* mainloop_io_new(
 
 /* IO events */
 static pa_io_event* mainloop_io_new(
-        pa_mainloop_api*a,
+        pa_mainloop_api *a,
         int fd,
         pa_io_event_flags_t events,
         pa_io_event_cb_t callback,
         int fd,
         pa_io_event_flags_t events,
         pa_io_event_cb_t callback,
@@ -161,48 +158,25 @@ static pa_io_event* mainloop_io_new(
     pa_mainloop *m;
     pa_io_event *e;
 
     pa_mainloop *m;
     pa_io_event *e;
 
-    assert(a);
-    assert(a->userdata);
-    assert(fd >= 0);
-    assert(callback);
+    pa_assert(a);
+    pa_assert(a->userdata);
+    pa_assert(fd >= 0);
+    pa_assert(callback);
 
     m = a->userdata;
 
     m = a->userdata;
-    assert(a == &m->api);
+    pa_assert(a == &m->api);
 
 
-    e = pa_xnew(pa_io_event, 1);
+    e = pa_xnew0(pa_io_event, 1);
     e->mainloop = m;
     e->mainloop = m;
-    e->dead = 0;
 
     e->fd = fd;
     e->events = events;
 
     e->fd = fd;
     e->events = events;
-    e->pollfd = NULL;
 
     e->callback = callback;
     e->userdata = userdata;
 
     e->callback = callback;
     e->userdata = userdata;
-    e->destroy_callback = NULL;
-
-#ifdef OS_IS_WIN32
-    {
-        fd_set xset;
-        struct timeval tv;
-
-        tv.tv_sec = 0;
-        tv.tv_usec = 0;
-
-        FD_ZERO (&xset);
-        FD_SET (fd, &xset);
-
-        if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
-                    SELECT_TYPE_ARG5 &tv) == -1) &&
-             (WSAGetLastError() == WSAENOTSOCK)) {
-            pa_log_warn("WARNING: cannot monitor non-socket file descriptors.");
-            e->dead = 1;
-        }
-    }
-#endif
 
     PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
 
     PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
-    m->rebuild_pollfds = 1;
+    m->rebuild_pollfds = TRUE;
     m->n_io_events ++;
 
     pa_mainloop_wakeup(m);
     m->n_io_events ++;
 
     pa_mainloop_wakeup(m);
@@ -211,8 +185,8 @@ static pa_io_event* mainloop_io_new(
 }
 
 static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
 }
 
 static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
     if (e->events == events)
         return;
 
     if (e->events == events)
         return;
@@ -222,56 +196,54 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
     if (e->pollfd)
         e->pollfd->events = map_flags_to_libc(events);
     else
     if (e->pollfd)
         e->pollfd->events = map_flags_to_libc(events);
     else
-        e->mainloop->rebuild_pollfds = 1;
+        e->mainloop->rebuild_pollfds = TRUE;
 
     pa_mainloop_wakeup(e->mainloop);
 }
 
 static void mainloop_io_free(pa_io_event *e) {
 
     pa_mainloop_wakeup(e->mainloop);
 }
 
 static void mainloop_io_free(pa_io_event *e) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
 
-    e->dead = 1;
+    e->dead = TRUE;
     e->mainloop->io_events_please_scan ++;
 
     e->mainloop->n_io_events --;
     e->mainloop->io_events_please_scan ++;
 
     e->mainloop->n_io_events --;
-    e->mainloop->rebuild_pollfds = 1;
+    e->mainloop->rebuild_pollfds = TRUE;
 
     pa_mainloop_wakeup(e->mainloop);
 }
 
 static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
 
     pa_mainloop_wakeup(e->mainloop);
 }
 
 static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
-    assert(e);
+    pa_assert(e);
 
     e->destroy_callback = callback;
 }
 
 /* Defer events */
 static pa_defer_event* mainloop_defer_new(
 
     e->destroy_callback = callback;
 }
 
 /* Defer events */
 static pa_defer_event* mainloop_defer_new(
-        pa_mainloop_api*a,
+        pa_mainloop_api *a,
         pa_defer_event_cb_t callback,
         void *userdata) {
 
     pa_mainloop *m;
     pa_defer_event *e;
 
         pa_defer_event_cb_t callback,
         void *userdata) {
 
     pa_mainloop *m;
     pa_defer_event *e;
 
-    assert(a);
-    assert(a->userdata);
-    assert(callback);
+    pa_assert(a);
+    pa_assert(a->userdata);
+    pa_assert(callback);
 
     m = a->userdata;
 
     m = a->userdata;
-    assert(a == &m->api);
+    pa_assert(a == &m->api);
 
 
-    e = pa_xnew(pa_defer_event, 1);
+    e = pa_xnew0(pa_defer_event, 1);
     e->mainloop = m;
     e->mainloop = m;
-    e->dead = 0;
 
 
-    e->enabled = 1;
+    e->enabled = TRUE;
     m->n_enabled_defer_events++;
 
     e->callback = callback;
     e->userdata = userdata;
     m->n_enabled_defer_events++;
 
     e->callback = callback;
     e->userdata = userdata;
-    e->destroy_callback = NULL;
 
     PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
 
 
     PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
 
@@ -281,11 +253,11 @@ static pa_defer_event* mainloop_defer_new(
 }
 
 static void mainloop_defer_enable(pa_defer_event *e, int b) {
 }
 
 static void mainloop_defer_enable(pa_defer_event *e, int b) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
     if (e->enabled && !b) {
 
     if (e->enabled && !b) {
-        assert(e->mainloop->n_enabled_defer_events > 0);
+        pa_assert(e->mainloop->n_enabled_defer_events > 0);
         e->mainloop->n_enabled_defer_events--;
     } else if (!e->enabled && b) {
         e->mainloop->n_enabled_defer_events++;
         e->mainloop->n_enabled_defer_events--;
     } else if (!e->enabled && b) {
         e->mainloop->n_enabled_defer_events++;
@@ -296,62 +268,85 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) {
 }
 
 static void mainloop_defer_free(pa_defer_event *e) {
 }
 
 static void mainloop_defer_free(pa_defer_event *e) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
 
-    e->dead = 1;
+    e->dead = TRUE;
     e->mainloop->defer_events_please_scan ++;
 
     if (e->enabled) {
     e->mainloop->defer_events_please_scan ++;
 
     if (e->enabled) {
-        assert(e->mainloop->n_enabled_defer_events > 0);
+        pa_assert(e->mainloop->n_enabled_defer_events > 0);
         e->mainloop->n_enabled_defer_events--;
         e->mainloop->n_enabled_defer_events--;
+        e->enabled = FALSE;
     }
 }
 
 static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) {
     }
 }
 
 static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
     e->destroy_callback = callback;
 }
 
 /* Time events */
 
     e->destroy_callback = callback;
 }
 
 /* Time events */
+static pa_usec_t make_rt(const struct timeval *tv, pa_bool_t *use_rtclock) {
+    struct timeval ttv;
+
+    if (!tv) {
+        *use_rtclock = FALSE;
+        return PA_USEC_INVALID;
+    }
+
+    ttv = *tv;
+    *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
+
+    if (*use_rtclock)
+        ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
+    else
+        pa_rtclock_from_wallclock(&ttv);
+
+    return pa_timeval_load(&ttv);
+}
+
 static pa_time_event* mainloop_time_new(
 static pa_time_event* mainloop_time_new(
-        pa_mainloop_api*a,
+        pa_mainloop_api *a,
         const struct timeval *tv,
         pa_time_event_cb_t callback,
         void *userdata) {
 
     pa_mainloop *m;
     pa_time_event *e;
         const struct timeval *tv,
         pa_time_event_cb_t callback,
         void *userdata) {
 
     pa_mainloop *m;
     pa_time_event *e;
+    pa_usec_t t;
+    pa_bool_t use_rtclock = FALSE;
+
+    pa_assert(a);
+    pa_assert(a->userdata);
+    pa_assert(callback);
 
 
-    assert(a);
-    assert(a->userdata);
-    assert(callback);
+    t = make_rt(tv, &use_rtclock);
 
     m = a->userdata;
 
     m = a->userdata;
-    assert(a == &m->api);
+    pa_assert(a == &m->api);
 
 
-    e = pa_xnew(pa_time_event, 1);
+    e = pa_xnew0(pa_time_event, 1);
     e->mainloop = m;
     e->mainloop = m;
-    e->dead = 0;
 
 
-    if ((e->enabled = !!tv)) {
-        e->timeval = *tv;
+    if ((e->enabled = (t != PA_USEC_INVALID))) {
+        e->time = t;
+        e->use_rtclock = use_rtclock;
 
         m->n_enabled_time_events++;
 
         if (m->cached_next_time_event) {
 
         m->n_enabled_time_events++;
 
         if (m->cached_next_time_event) {
-            assert(m->cached_next_time_event->enabled);
+            pa_assert(m->cached_next_time_event->enabled);
 
 
-            if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0)
+            if (t < m->cached_next_time_event->time)
                 m->cached_next_time_event = e;
         }
     }
 
     e->callback = callback;
     e->userdata = userdata;
                 m->cached_next_time_event = e;
         }
     }
 
     e->callback = callback;
     e->userdata = userdata;
-    e->destroy_callback = NULL;
 
     PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
 
 
     PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
 
@@ -362,39 +357,48 @@ static pa_time_event* mainloop_time_new(
 }
 
 static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
 }
 
 static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
-    assert(e);
-    assert(!e->dead);
+    pa_bool_t valid;
+    pa_usec_t t;
+    pa_bool_t use_rtclock = FALSE;
+
+    pa_assert(e);
+    pa_assert(!e->dead);
+
+    t = make_rt(tv, &use_rtclock);
 
 
-    if (e->enabled && !tv) {
-        assert(e->mainloop->n_enabled_time_events > 0);
+    valid = (t != PA_USEC_INVALID);
+    if (e->enabled && !valid) {
+        pa_assert(e->mainloop->n_enabled_time_events > 0);
         e->mainloop->n_enabled_time_events--;
         e->mainloop->n_enabled_time_events--;
-    } else if (!e->enabled && tv)
+    } else if (!e->enabled && valid)
         e->mainloop->n_enabled_time_events++;
 
         e->mainloop->n_enabled_time_events++;
 
-    if ((e->enabled = !!tv)) {
-        e->timeval = *tv;
+    if ((e->enabled = valid)) {
+        e->time = t;
+        e->use_rtclock = use_rtclock;
         pa_mainloop_wakeup(e->mainloop);
     }
 
     if (e->mainloop->cached_next_time_event && e->enabled) {
         pa_mainloop_wakeup(e->mainloop);
     }
 
     if (e->mainloop->cached_next_time_event && e->enabled) {
-        assert(e->mainloop->cached_next_time_event->enabled);
+        pa_assert(e->mainloop->cached_next_time_event->enabled);
 
 
-        if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
+        if (t < e->mainloop->cached_next_time_event->time)
             e->mainloop->cached_next_time_event = e;
     } else if (e->mainloop->cached_next_time_event == e)
         e->mainloop->cached_next_time_event = NULL;
 }
 
 static void mainloop_time_free(pa_time_event *e) {
             e->mainloop->cached_next_time_event = e;
     } else if (e->mainloop->cached_next_time_event == e)
         e->mainloop->cached_next_time_event = NULL;
 }
 
 static void mainloop_time_free(pa_time_event *e) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
 
-    e->dead = 1;
+    e->dead = TRUE;
     e->mainloop->time_events_please_scan ++;
 
     if (e->enabled) {
     e->mainloop->time_events_please_scan ++;
 
     if (e->enabled) {
-        assert(e->mainloop->n_enabled_time_events > 0);
+        pa_assert(e->mainloop->n_enabled_time_events > 0);
         e->mainloop->n_enabled_time_events--;
         e->mainloop->n_enabled_time_events--;
+        e->enabled = FALSE;
     }
 
     if (e->mainloop->cached_next_time_event == e)
     }
 
     if (e->mainloop->cached_next_time_event == e)
@@ -404,21 +408,21 @@ static void mainloop_time_free(pa_time_event *e) {
 }
 
 static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) {
 }
 
 static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) {
-    assert(e);
-    assert(!e->dead);
+    pa_assert(e);
+    pa_assert(!e->dead);
 
     e->destroy_callback = callback;
 }
 
 /* quit() */
 
 
     e->destroy_callback = callback;
 }
 
 /* quit() */
 
-static void mainloop_quit(pa_mainloop_api*a, int retval) {
+static void mainloop_quit(pa_mainloop_api *a, int retval) {
     pa_mainloop *m;
 
     pa_mainloop *m;
 
-    assert(a);
-    assert(a->userdata);
+    pa_assert(a);
+    pa_assert(a->userdata);
     m = a->userdata;
     m = a->userdata;
-    assert(a == &m->api);
+    pa_assert(a == &m->api);
 
     pa_mainloop_quit(m, retval);
 }
 
     pa_mainloop_quit(m, retval);
 }
@@ -426,10 +430,10 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) {
 static const pa_mainloop_api vtable = {
     .userdata = NULL,
 
 static const pa_mainloop_api vtable = {
     .userdata = NULL,
 
-    .io_new= mainloop_io_new,
-    .io_enable= mainloop_io_enable,
-    .io_free= mainloop_io_free,
-    .io_set_destroy= mainloop_io_set_destroy,
+    .io_new = mainloop_io_new,
+    .io_enable = mainloop_io_enable,
+    .io_free = mainloop_io_free,
+    .io_set_destroy = mainloop_io_set_destroy,
 
     .time_new = mainloop_time_new,
     .time_restart = mainloop_time_restart,
 
     .time_new = mainloop_time_new,
     .time_restart = mainloop_time_restart,
@@ -447,53 +451,35 @@ static const pa_mainloop_api vtable = {
 pa_mainloop *pa_mainloop_new(void) {
     pa_mainloop *m;
 
 pa_mainloop *pa_mainloop_new(void) {
     pa_mainloop *m;
 
-    m = pa_xnew(pa_mainloop, 1);
+    pa_init_i18n();
 
 
-    m->wakeup_pipe_type = 0;
-    if (pipe(m->wakeup_pipe) < 0) {
+    m = pa_xnew0(pa_mainloop, 1);
+
+    if (pa_pipe_cloexec(m->wakeup_pipe) < 0) {
         pa_log_error("ERROR: cannot create wakeup pipe");
         pa_xfree(m);
         return NULL;
     }
 
         pa_log_error("ERROR: cannot create wakeup pipe");
         pa_xfree(m);
         return NULL;
     }
 
-    pa_make_nonblock_fd(m->wakeup_pipe[0]);
-    pa_make_nonblock_fd(m->wakeup_pipe[1]);
-    m->wakeup_requested = 0;
-
-    PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
-    PA_LLIST_HEAD_INIT(pa_time_event, m->time_events);
-    PA_LLIST_HEAD_INIT(pa_defer_event, m->defer_events);
-
-    m->n_enabled_defer_events = m->n_enabled_time_events = m->n_io_events = 0;
-    m->io_events_please_scan = m->time_events_please_scan = m->defer_events_please_scan = 0;
-
-    m->cached_next_time_event = NULL;
-    m->prepared_timeout = 0;
+    pa_make_fd_nonblock(m->wakeup_pipe[0]);
+    pa_make_fd_nonblock(m->wakeup_pipe[1]);
 
 
-    m->pollfds = NULL;
-    m->max_pollfds = m->n_pollfds = 0;
-    m->rebuild_pollfds = 1;
-
-    m->quit = m->retval = 0;
+    m->rebuild_pollfds = TRUE;
 
     m->api = vtable;
     m->api.userdata = m;
 
     m->state = STATE_PASSIVE;
 
 
     m->api = vtable;
     m->api.userdata = m;
 
     m->state = STATE_PASSIVE;
 
-    m->poll_func = NULL;
-    m->poll_func_userdata = NULL;
     m->poll_func_ret = -1;
 
     return m;
 }
 
     m->poll_func_ret = -1;
 
     return m;
 }
 
-static void cleanup_io_events(pa_mainloop *m, int force) {
-    pa_io_event *e;
+static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
+    pa_io_event *e, *n;
 
 
-    e = m->io_events;
-    while (e) {
-        pa_io_event *n = e->next;
+    PA_LLIST_FOREACH_SAFE(e, n, m->io_events) {
 
         if (!force && m->io_events_please_scan <= 0)
             break;
 
         if (!force && m->io_events_please_scan <= 0)
             break;
@@ -502,7 +488,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) {
             PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
 
             if (e->dead) {
             PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
 
             if (e->dead) {
-                assert(m->io_events_please_scan > 0);
+                pa_assert(m->io_events_please_scan > 0);
                 m->io_events_please_scan--;
             }
 
                 m->io_events_please_scan--;
             }
 
@@ -511,21 +497,17 @@ static void cleanup_io_events(pa_mainloop *m, int force) {
 
             pa_xfree(e);
 
 
             pa_xfree(e);
 
-            m->rebuild_pollfds = 1;
+            m->rebuild_pollfds = TRUE;
         }
         }
-
-        e = n;
     }
 
     }
 
-    assert(m->io_events_please_scan == 0);
+    pa_assert(m->io_events_please_scan == 0);
 }
 
 }
 
-static void cleanup_time_events(pa_mainloop *m, int force) {
-    pa_time_event *e;
+static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
+    pa_time_event *e, *n;
 
 
-    e = m->time_events;
-    while (e) {
-        pa_time_event *n = e->next;
+    PA_LLIST_FOREACH_SAFE(e, n, m->time_events) {
 
         if (!force && m->time_events_please_scan <= 0)
             break;
 
         if (!force && m->time_events_please_scan <= 0)
             break;
@@ -534,13 +516,14 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
             PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
 
             if (e->dead) {
             PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
 
             if (e->dead) {
-                assert(m->time_events_please_scan > 0);
+                pa_assert(m->time_events_please_scan > 0);
                 m->time_events_please_scan--;
             }
 
             if (!e->dead && e->enabled) {
                 m->time_events_please_scan--;
             }
 
             if (!e->dead && e->enabled) {
-                assert(m->n_enabled_time_events > 0);
+                pa_assert(m->n_enabled_time_events > 0);
                 m->n_enabled_time_events--;
                 m->n_enabled_time_events--;
+                e->enabled = FALSE;
             }
 
             if (e->destroy_callback)
             }
 
             if (e->destroy_callback)
@@ -548,19 +531,15 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
 
             pa_xfree(e);
         }
 
             pa_xfree(e);
         }
-
-        e = n;
     }
 
     }
 
-    assert(m->time_events_please_scan == 0);
+    pa_assert(m->time_events_please_scan == 0);
 }
 
 }
 
-static void cleanup_defer_events(pa_mainloop *m, int force) {
-    pa_defer_event *e;
+static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
+    pa_defer_event *e, *n;
 
 
-    e = m->defer_events;
-    while (e) {
-        pa_defer_event *n = e->next;
+    PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) {
 
         if (!force && m->defer_events_please_scan <= 0)
             break;
 
         if (!force && m->defer_events_please_scan <= 0)
             break;
@@ -569,14 +548,14 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
             PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
 
             if (e->dead) {
             PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
 
             if (e->dead) {
-                assert(m->defer_events_please_scan > 0);
+                pa_assert(m->defer_events_please_scan > 0);
                 m->defer_events_please_scan--;
             }
 
             if (!e->dead && e->enabled) {
                 m->defer_events_please_scan--;
             }
 
             if (!e->dead && e->enabled) {
-                e->enabled = 0;
-                assert(m->n_enabled_defer_events > 0);
+                pa_assert(m->n_enabled_defer_events > 0);
                 m->n_enabled_defer_events--;
                 m->n_enabled_defer_events--;
+                e->enabled = FALSE;
             }
 
             if (e->destroy_callback)
             }
 
             if (e->destroy_callback)
@@ -584,42 +563,37 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
 
             pa_xfree(e);
         }
 
             pa_xfree(e);
         }
-
-        e = n;
     }
 
     }
 
-    assert(m->defer_events_please_scan == 0);
+    pa_assert(m->defer_events_please_scan == 0);
 }
 
 
 }
 
 
-void pa_mainloop_free(pa_mainloopm) {
-    assert(m);
+void pa_mainloop_free(pa_mainloop *m) {
+    pa_assert(m);
 
 
-    cleanup_io_events(m, 1);
-    cleanup_defer_events(m, 1);
-    cleanup_time_events(m, 1);
+    cleanup_io_events(m, TRUE);
+    cleanup_defer_events(m, TRUE);
+    cleanup_time_events(m, TRUE);
 
     pa_xfree(m->pollfds);
 
 
     pa_xfree(m->pollfds);
 
-    if (m->wakeup_pipe[0] >= 0)
-        close(m->wakeup_pipe[0]);
-    if (m->wakeup_pipe[1] >= 0)
-        close(m->wakeup_pipe[1]);
+    pa_close_pipe(m->wakeup_pipe);
 
     pa_xfree(m);
 }
 
 static void scan_dead(pa_mainloop *m) {
 
     pa_xfree(m);
 }
 
 static void scan_dead(pa_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     if (m->io_events_please_scan)
 
     if (m->io_events_please_scan)
-        cleanup_io_events(m, 0);
+        cleanup_io_events(m, FALSE);
 
     if (m->time_events_please_scan)
 
     if (m->time_events_please_scan)
-        cleanup_time_events(m, 0);
+        cleanup_time_events(m, FALSE);
 
     if (m->defer_events_please_scan)
 
     if (m->defer_events_please_scan)
-        cleanup_defer_events(m, 0);
+        cleanup_defer_events(m, FALSE);
 }
 
 static void rebuild_pollfds(pa_mainloop *m) {
 }
 
 static void rebuild_pollfds(pa_mainloop *m) {
@@ -645,7 +619,7 @@ static void rebuild_pollfds(pa_mainloop *m) {
         m->n_pollfds++;
     }
 
         m->n_pollfds++;
     }
 
-    for (e = m->io_events; e; e = e->next) {
+    PA_LLIST_FOREACH(e, m->io_events) {
         if (e->dead) {
             e->pollfd = NULL;
             continue;
         if (e->dead) {
             e->pollfd = NULL;
             continue;
@@ -660,42 +634,53 @@ static void rebuild_pollfds(pa_mainloop *m) {
         m->n_pollfds++;
     }
 
         m->n_pollfds++;
     }
 
-    m->rebuild_pollfds = 0;
+    m->rebuild_pollfds = FALSE;
 }
 
 }
 
-static int dispatch_pollfds(pa_mainloop *m) {
+static unsigned dispatch_pollfds(pa_mainloop *m) {
     pa_io_event *e;
     pa_io_event *e;
-    int r = 0, k;
+    unsigned r = 0, k;
+
+    pa_assert(m->poll_func_ret > 0);
+
+    k = m->poll_func_ret;
 
 
-    assert(m->poll_func_ret > 0);
+    PA_LLIST_FOREACH(e, m->io_events) {
+
+        if (k <= 0 || m->quit)
+            break;
 
 
-    for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
         if (e->dead || !e->pollfd || !e->pollfd->revents)
             continue;
 
         if (e->dead || !e->pollfd || !e->pollfd->revents)
             continue;
 
-        assert(e->pollfd->fd == e->fd && e->callback);
+        pa_assert(e->pollfd->fd == e->fd);
+        pa_assert(e->callback);
+
         e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
         e->pollfd->revents = 0;
         r++;
         e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
         e->pollfd->revents = 0;
         r++;
-
         k--;
     }
 
     return r;
 }
 
         k--;
     }
 
     return r;
 }
 
-static int dispatch_defer(pa_mainloop *m) {
+static unsigned dispatch_defer(pa_mainloop *m) {
     pa_defer_event *e;
     pa_defer_event *e;
-    int r = 0;
+    unsigned r = 0;
 
     if (m->n_enabled_defer_events <= 0)
         return 0;
 
 
     if (m->n_enabled_defer_events <= 0)
         return 0;
 
-    for (e = m->defer_events; e && !m->quit; e = e->next) {
+    PA_LLIST_FOREACH(e, m->defer_events) {
+
+        if (m->quit)
+            break;
+
         if (e->dead || !e->enabled)
             continue;
 
         if (e->dead || !e->enabled)
             continue;
 
-        assert(e->callback);
+        pa_assert(e->callback);
         e->callback(&m->api, e, e->userdata);
         r++;
     }
         e->callback(&m->api, e, e->userdata);
         r++;
     }
@@ -705,21 +690,21 @@ static int dispatch_defer(pa_mainloop *m) {
 
 static pa_time_event* find_next_time_event(pa_mainloop *m) {
     pa_time_event *t, *n = NULL;
 
 static pa_time_event* find_next_time_event(pa_mainloop *m) {
     pa_time_event *t, *n = NULL;
-    assert(m);
+    pa_assert(m);
 
     if (m->cached_next_time_event)
         return m->cached_next_time_event;
 
 
     if (m->cached_next_time_event)
         return m->cached_next_time_event;
 
-    for (t = m->time_events; t; t = t->next) {
+    PA_LLIST_FOREACH(t, m->time_events) {
 
         if (t->dead || !t->enabled)
             continue;
 
 
         if (t->dead || !t->enabled)
             continue;
 
-        if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
+        if (!n || t->time < n->time) {
             n = t;
 
             n = t;
 
-            /* Shortcut for tv = { 0, 0 } */
-            if (n->timeval.tv_sec <= 0)
+            /* Shortcut for time == 0 */
+            if (n->time == 0)
                 break;
         }
     }
                 break;
         }
     }
@@ -728,52 +713,53 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
     return n;
 }
 
     return n;
 }
 
-static int calc_next_timeout(pa_mainloop *m) {
+static pa_usec_t calc_next_timeout(pa_mainloop *m) {
     pa_time_event *t;
     pa_time_event *t;
-    struct timeval now;
-    pa_usec_t usec;
+    pa_usec_t clock_now;
 
 
-    if (!m->n_enabled_time_events)
-        return -1;
+    if (m->n_enabled_time_events <= 0)
+        return PA_USEC_INVALID;
 
 
-    t = find_next_time_event(m);
-    assert(t);
+    pa_assert_se(t = find_next_time_event(m));
 
 
-    if (t->timeval.tv_sec <= 0)
+    if (t->time <= 0)
         return 0;
 
         return 0;
 
-    pa_gettimeofday(&now);
+    clock_now = pa_rtclock_now();
 
 
-    if (pa_timeval_cmp(&t->timeval, &now) <= 0)
+    if (t->time <= clock_now)
         return 0;
 
         return 0;
 
-    usec = pa_timeval_diff(&t->timeval, &now);
-    return (int) (usec / 1000);
+    return t->time - clock_now;
 }
 
 }
 
-static int dispatch_timeout(pa_mainloop *m) {
+static unsigned dispatch_timeout(pa_mainloop *m) {
     pa_time_event *e;
     pa_time_event *e;
-    struct timeval now;
-    int r = 0;
-    assert(m);
+    pa_usec_t now;
+    unsigned r = 0;
+    pa_assert(m);
 
     if (m->n_enabled_time_events <= 0)
         return 0;
 
 
     if (m->n_enabled_time_events <= 0)
         return 0;
 
-    pa_gettimeofday(&now);
+    now = pa_rtclock_now();
+
+    PA_LLIST_FOREACH(e, m->time_events) {
 
 
-    for (e = m->time_events; e && !m->quit; e = e->next) {
+        if (m->quit)
+            break;
 
         if (e->dead || !e->enabled)
             continue;
 
 
         if (e->dead || !e->enabled)
             continue;
 
-        if (pa_timeval_cmp(&e->timeval, &now) <= 0) {
-            assert(e->callback);
+        if (e->time <= now) {
+            struct timeval tv;
+            pa_assert(e->callback);
 
             /* Disable time event */
             mainloop_time_restart(e, NULL);
 
 
             /* Disable time event */
             mainloop_time_restart(e, NULL);
 
-            e->callback(&m->api, e, &e->timeval, e->userdata);
+            e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
 
             r++;
         }
 
             r++;
         }
@@ -784,7 +770,7 @@ static int dispatch_timeout(pa_mainloop *m) {
 
 void pa_mainloop_wakeup(pa_mainloop *m) {
     char c = 'W';
 
 void pa_mainloop_wakeup(pa_mainloop *m) {
     char c = 'W';
-    assert(m);
+    pa_assert(m);
 
     if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) {
         pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type);
 
     if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) {
         pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type);
@@ -795,20 +781,21 @@ void pa_mainloop_wakeup(pa_mainloop *m) {
 static void clear_wakeup(pa_mainloop *m) {
     char c[10];
 
 static void clear_wakeup(pa_mainloop *m) {
     char c[10];
 
-    assert(m);
+    pa_assert(m);
 
     if (m->wakeup_pipe[0] < 0)
         return;
 
     if (m->wakeup_requested) {
 
     if (m->wakeup_pipe[0] < 0)
         return;
 
     if (m->wakeup_requested) {
-        while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c));
+        while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
+            ;
         m->wakeup_requested = 0;
     }
 }
 
 int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
         m->wakeup_requested = 0;
     }
 }
 
 int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
-    assert(m);
-    assert(m->state == STATE_PASSIVE);
+    pa_assert(m);
+    pa_assert(m->state == STATE_PASSIVE);
 
     clear_wakeup(m);
     scan_dead(m);
 
     clear_wakeup(m);
     scan_dead(m);
@@ -817,12 +804,17 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
         goto quit;
 
     if (m->n_enabled_defer_events <= 0) {
         goto quit;
 
     if (m->n_enabled_defer_events <= 0) {
+
         if (m->rebuild_pollfds)
             rebuild_pollfds(m);
 
         m->prepared_timeout = calc_next_timeout(m);
         if (m->rebuild_pollfds)
             rebuild_pollfds(m);
 
         m->prepared_timeout = calc_next_timeout(m);
-        if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
-            m->prepared_timeout = timeout;
+        if (timeout >= 0) {
+            uint64_t u = (uint64_t) timeout * PA_USEC_PER_MSEC;
+
+            if (u < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID)
+                m->prepared_timeout = timeout;
+        }
     }
 
     m->state = STATE_PREPARED;
     }
 
     m->state = STATE_PREPARED;
@@ -833,9 +825,21 @@ quit:
     return -2;
 }
 
     return -2;
 }
 
+static int usec_to_timeout(pa_usec_t u) {
+    int timeout;
+
+    if (u == PA_USEC_INVALID)
+        return -1;
+
+    timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
+    pa_assert(timeout >= 0);
+
+    return timeout;
+}
+
 int pa_mainloop_poll(pa_mainloop *m) {
 int pa_mainloop_poll(pa_mainloop *m) {
-    assert(m);
-    assert(m->state == STATE_PREPARED);
+    pa_assert(m);
+    pa_assert(m->state == STATE_PREPARED);
 
     if (m->quit)
         goto quit;
 
     if (m->quit)
         goto quit;
@@ -845,12 +849,27 @@ int pa_mainloop_poll(pa_mainloop *m) {
     if (m->n_enabled_defer_events )
         m->poll_func_ret = 0;
     else {
     if (m->n_enabled_defer_events )
         m->poll_func_ret = 0;
     else {
-        assert(!m->rebuild_pollfds);
+        pa_assert(!m->rebuild_pollfds);
 
         if (m->poll_func)
 
         if (m->poll_func)
-            m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
-        else
-            m->poll_func_ret = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
+            m->poll_func_ret = m->poll_func(
+                    m->pollfds, m->n_pollfds,
+                    usec_to_timeout(m->prepared_timeout),
+                    m->poll_func_userdata);
+        else {
+#ifdef HAVE_PPOLL
+            struct timespec ts;
+
+            m->poll_func_ret = ppoll(
+                    m->pollfds, m->n_pollfds,
+                    m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
+                    NULL);
+#else
+            m->poll_func_ret = pa_poll(
+                    m->pollfds, m->n_pollfds,
+                    usec_to_timeout(m->prepared_timeout));
+#endif
+        }
 
         if (m->poll_func_ret < 0) {
             if (errno == EINTR)
 
         if (m->poll_func_ret < 0) {
             if (errno == EINTR)
@@ -869,10 +888,10 @@ quit:
 }
 
 int pa_mainloop_dispatch(pa_mainloop *m) {
 }
 
 int pa_mainloop_dispatch(pa_mainloop *m) {
-    int dispatched = 0;
+    unsigned dispatched = 0;
 
 
-    assert(m);
-    assert(m->state == STATE_POLLED);
+    pa_assert(m);
+    pa_assert(m->state == STATE_POLLED);
 
     if (m->quit)
         goto quit;
 
     if (m->quit)
         goto quit;
@@ -895,7 +914,7 @@ int pa_mainloop_dispatch(pa_mainloop *m) {
 
     m->state = STATE_PASSIVE;
 
 
     m->state = STATE_PASSIVE;
 
-    return dispatched;
+    return (int) dispatched;
 
 quit:
     m->state = STATE_QUIT;
 
 quit:
     m->state = STATE_QUIT;
@@ -903,13 +922,14 @@ quit:
 }
 
 int pa_mainloop_get_retval(pa_mainloop *m) {
 }
 
 int pa_mainloop_get_retval(pa_mainloop *m) {
-    assert(m);
+    pa_assert(m);
+
     return m->retval;
 }
 
 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
     int r;
     return m->retval;
 }
 
 int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
     int r;
-    assert(m);
+    pa_assert(m);
 
     if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
         goto quit;
 
     if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
         goto quit;
@@ -932,7 +952,8 @@ quit:
 int pa_mainloop_run(pa_mainloop *m, int *retval) {
     int r;
 
 int pa_mainloop_run(pa_mainloop *m, int *retval) {
     int r;
 
-    while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
+    while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
+        ;
 
     if (r == -2)
         return 1;
 
     if (r == -2)
         return 1;
@@ -943,21 +964,28 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) {
 }
 
 void pa_mainloop_quit(pa_mainloop *m, int retval) {
 }
 
 void pa_mainloop_quit(pa_mainloop *m, int retval) {
-    assert(m);
+    pa_assert(m);
 
 
-    m->quit = 1;
+    m->quit = TRUE;
     m->retval = retval;
     pa_mainloop_wakeup(m);
 }
 
     m->retval = retval;
     pa_mainloop_wakeup(m);
 }
 
-pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
-    assert(m);
+pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) {
+    pa_assert(m);
+
     return &m->api;
 }
 
 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
     return &m->api;
 }
 
 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
-    assert(m);
+    pa_assert(m);
 
     m->poll_func = poll_func;
     m->poll_func_userdata = userdata;
 }
 
     m->poll_func = poll_func;
     m->poll_func_userdata = userdata;
 }
+
+pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api *m) {
+    pa_assert(m);
+
+    return m->io_new == mainloop_io_new;
+}