X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/b32f5994e9d1872c3a2ed8fd44d6d1866bb8387f..HEAD:/src/pulse/mainloop.c diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 4f3b676f..66a14756 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -25,34 +25,27 @@ #endif #include -#include #include #include -#include #include #include -#ifdef HAVE_POLL_H -#include -#else -#include -#endif - #ifndef HAVE_PIPE #include #endif -#include #include #include #include +#include #include #include +#include #include #include #include -#include +#include #include #include "mainloop.h" @@ -60,7 +53,7 @@ struct pa_io_event { pa_mainloop *mainloop; - pa_bool_t dead:1; + bool dead:1; int fd; pa_io_event_flags_t events; @@ -75,9 +68,10 @@ struct pa_io_event { struct pa_time_event { pa_mainloop *mainloop; - pa_bool_t dead:1; + bool dead:1; - pa_bool_t enabled:1; + bool enabled:1; + bool use_rtclock:1; pa_usec_t time; pa_time_event_cb_t callback; @@ -89,9 +83,9 @@ struct pa_time_event { struct pa_defer_event { pa_mainloop *mainloop; - pa_bool_t dead:1; + bool dead:1; - pa_bool_t enabled:1; + bool enabled:1; pa_defer_event_cb_t callback; void *userdata; @@ -108,7 +102,7 @@ struct pa_mainloop { 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; + bool rebuild_pollfds:1; struct pollfd *pollfds; unsigned max_pollfds, n_pollfds; @@ -118,9 +112,9 @@ struct pa_mainloop { pa_mainloop_api api; int retval; - pa_bool_t quit:1; + bool quit:1; - pa_bool_t wakeup_requested:1; + pa_atomic_t wakeup_requested; int wakeup_pipe[2]; int wakeup_pipe_type; @@ -155,7 +149,7 @@ static pa_io_event_flags_t map_flags_from_libc(short flags) { /* 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, @@ -181,28 +175,8 @@ static pa_io_event* mainloop_io_new( e->callback = callback; e->userdata = userdata; -#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("Cannot monitor non-socket file descriptors."); - e->dead = TRUE; - } - } -#endif - PA_LLIST_PREPEND(pa_io_event, m->io_events, e); - m->rebuild_pollfds = TRUE; + m->rebuild_pollfds = true; m->n_io_events ++; pa_mainloop_wakeup(m); @@ -222,7 +196,7 @@ 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 - e->mainloop->rebuild_pollfds = TRUE; + e->mainloop->rebuild_pollfds = true; pa_mainloop_wakeup(e->mainloop); } @@ -231,11 +205,11 @@ static void mainloop_io_free(pa_io_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = TRUE; + e->dead = true; e->mainloop->io_events_please_scan ++; e->mainloop->n_io_events --; - e->mainloop->rebuild_pollfds = TRUE; + e->mainloop->rebuild_pollfds = true; pa_mainloop_wakeup(e->mainloop); } @@ -248,7 +222,7 @@ static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cal /* 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) { @@ -265,7 +239,7 @@ static pa_defer_event* mainloop_defer_new( e = pa_xnew0(pa_defer_event, 1); e->mainloop = m; - e->enabled = TRUE; + e->enabled = true; m->n_enabled_defer_events++; e->callback = callback; @@ -297,13 +271,13 @@ static void mainloop_defer_free(pa_defer_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = TRUE; + e->dead = true; e->mainloop->defer_events_please_scan ++; if (e->enabled) { pa_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; - e->enabled = FALSE; + e->enabled = false; } } @@ -315,23 +289,27 @@ static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy } /* Time events */ -static pa_usec_t make_rt(const struct timeval *tv) { +static pa_usec_t make_rt(const struct timeval *tv, bool *use_rtclock) { struct timeval ttv; - if (!tv) + if (!tv) { + *use_rtclock = false; return PA_USEC_INVALID; + } + + ttv = *tv; + *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); - if (tv->tv_usec & PA_TIMEVAL_RTCLOCK) { - ttv = *tv; + if (*use_rtclock) ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; - tv = pa_rtclock_from_wallclock(&ttv); - } + else + pa_rtclock_from_wallclock(&ttv); - return pa_timeval_load(tv); + return pa_timeval_load(&ttv); } 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) { @@ -339,12 +317,13 @@ static pa_time_event* mainloop_time_new( pa_mainloop *m; pa_time_event *e; pa_usec_t t; + bool use_rtclock = false; pa_assert(a); pa_assert(a->userdata); pa_assert(callback); - t = make_rt(tv); + t = make_rt(tv, &use_rtclock); m = a->userdata; pa_assert(a == &m->api); @@ -354,6 +333,7 @@ static pa_time_event* mainloop_time_new( if ((e->enabled = (t != PA_USEC_INVALID))) { e->time = t; + e->use_rtclock = use_rtclock; m->n_enabled_time_events++; @@ -377,13 +357,14 @@ static pa_time_event* mainloop_time_new( } static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { - pa_bool_t valid; + bool valid; pa_usec_t t; + bool use_rtclock = false; pa_assert(e); pa_assert(!e->dead); - t = make_rt(tv); + t = make_rt(tv, &use_rtclock); valid = (t != PA_USEC_INVALID); if (e->enabled && !valid) { @@ -394,29 +375,32 @@ static void mainloop_time_restart(pa_time_event *e, const struct 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) + e->mainloop->cached_next_time_event = NULL; + if (e->mainloop->cached_next_time_event && e->enabled) { pa_assert(e->mainloop->cached_next_time_event->enabled); 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) { pa_assert(e); pa_assert(!e->dead); - e->dead = TRUE; + e->dead = true; e->mainloop->time_events_please_scan ++; if (e->enabled) { pa_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; - e->enabled = FALSE; + e->enabled = false; } if (e->mainloop->cached_next_time_event == e) @@ -434,7 +418,7 @@ static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb /* 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_assert(a); @@ -473,7 +457,7 @@ pa_mainloop *pa_mainloop_new(void) { m = pa_xnew0(pa_mainloop, 1); - if (pipe(m->wakeup_pipe) < 0) { + if (pa_pipe_cloexec(m->wakeup_pipe) < 0) { pa_log_error("ERROR: cannot create wakeup pipe"); pa_xfree(m); return NULL; @@ -481,10 +465,8 @@ pa_mainloop *pa_mainloop_new(void) { pa_make_fd_nonblock(m->wakeup_pipe[0]); pa_make_fd_nonblock(m->wakeup_pipe[1]); - pa_make_fd_cloexec(m->wakeup_pipe[0]); - pa_make_fd_cloexec(m->wakeup_pipe[1]); - m->rebuild_pollfds = TRUE; + m->rebuild_pollfds = true; m->api = vtable; m->api.userdata = m; @@ -496,12 +478,10 @@ pa_mainloop *pa_mainloop_new(void) { return m; } -static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) { - pa_io_event *e; +static void cleanup_io_events(pa_mainloop *m, bool 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; @@ -519,21 +499,17 @@ static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) { pa_xfree(e); - m->rebuild_pollfds = TRUE; + m->rebuild_pollfds = true; } - - e = n; } pa_assert(m->io_events_please_scan == 0); } -static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) { - pa_time_event *e; +static void cleanup_time_events(pa_mainloop *m, bool 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; @@ -549,7 +525,7 @@ static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) { if (!e->dead && e->enabled) { pa_assert(m->n_enabled_time_events > 0); m->n_enabled_time_events--; - e->enabled = FALSE; + e->enabled = false; } if (e->destroy_callback) @@ -557,19 +533,15 @@ static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) { pa_xfree(e); } - - e = n; } pa_assert(m->time_events_please_scan == 0); } -static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) { - pa_defer_event *e; +static void cleanup_defer_events(pa_mainloop *m, bool 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; @@ -585,7 +557,7 @@ static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) { if (!e->dead && e->enabled) { pa_assert(m->n_enabled_defer_events > 0); m->n_enabled_defer_events--; - e->enabled = FALSE; + e->enabled = false; } if (e->destroy_callback) @@ -593,20 +565,17 @@ static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) { pa_xfree(e); } - - e = n; } pa_assert(m->defer_events_please_scan == 0); } - -void pa_mainloop_free(pa_mainloop* m) { +void pa_mainloop_free(pa_mainloop *m) { pa_assert(m); - cleanup_io_events(m, TRUE); - cleanup_defer_events(m, TRUE); - cleanup_time_events(m, TRUE); + cleanup_io_events(m, true); + cleanup_defer_events(m, true); + cleanup_time_events(m, true); pa_xfree(m->pollfds); @@ -619,13 +588,13 @@ static void scan_dead(pa_mainloop *m) { pa_assert(m); if (m->io_events_please_scan) - cleanup_io_events(m, FALSE); + cleanup_io_events(m, false); if (m->time_events_please_scan) - cleanup_time_events(m, FALSE); + cleanup_time_events(m, false); if (m->defer_events_please_scan) - cleanup_defer_events(m, FALSE); + cleanup_defer_events(m, false); } static void rebuild_pollfds(pa_mainloop *m) { @@ -643,15 +612,13 @@ static void rebuild_pollfds(pa_mainloop *m) { m->n_pollfds = 0; p = m->pollfds; - if (m->wakeup_pipe[0] >= 0) { - m->pollfds[0].fd = m->wakeup_pipe[0]; - m->pollfds[0].events = POLLIN; - m->pollfds[0].revents = 0; - p++; - m->n_pollfds++; - } + m->pollfds[0].fd = m->wakeup_pipe[0]; + m->pollfds[0].events = POLLIN; + m->pollfds[0].revents = 0; + p++; + 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; @@ -666,39 +633,49 @@ static void rebuild_pollfds(pa_mainloop *m) { m->n_pollfds++; } - m->rebuild_pollfds = FALSE; + m->rebuild_pollfds = false; } -static int dispatch_pollfds(pa_mainloop *m) { +static unsigned dispatch_pollfds(pa_mainloop *m) { pa_io_event *e; - int r = 0, k; + unsigned r = 0, k; pa_assert(m->poll_func_ret > 0); - for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) { + k = m->poll_func_ret; + + PA_LLIST_FOREACH(e, m->io_events) { + + if (k <= 0 || m->quit) + break; + if (e->dead || !e->pollfd || !e->pollfd->revents) continue; 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++; - k--; } return r; } -static int dispatch_defer(pa_mainloop *m) { +static unsigned dispatch_defer(pa_mainloop *m) { pa_defer_event *e; - int r = 0; + unsigned r = 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; @@ -717,7 +694,7 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) { 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; @@ -755,10 +732,10 @@ static pa_usec_t calc_next_timeout(pa_mainloop *m) { return t->time - clock_now; } -static int dispatch_timeout(pa_mainloop *m) { +static unsigned dispatch_timeout(pa_mainloop *m) { pa_time_event *e; pa_usec_t now; - int r = 0; + unsigned r = 0; pa_assert(m); if (m->n_enabled_time_events <= 0) @@ -766,7 +743,10 @@ static int dispatch_timeout(pa_mainloop *m) { now = pa_rtclock_now(); - for (e = m->time_events; e && !m->quit; e = e->next) { + PA_LLIST_FOREACH(e, m->time_events) { + + if (m->quit) + break; if (e->dead || !e->enabled) continue; @@ -778,7 +758,7 @@ static int dispatch_timeout(pa_mainloop *m) { /* Disable time event */ mainloop_time_restart(e, NULL); - e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, FALSE), e->userdata); + e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata); r++; } @@ -791,10 +771,11 @@ void pa_mainloop_wakeup(pa_mainloop *m) { char c = 'W'; 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); - m->wakeup_requested++; - } + if (pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type) < 0) + /* Not much options for recovering from the error. Let's at least log something. */ + pa_log("pa_write() failed while trying to wake up the mainloop: %s", pa_cstrerror(errno)); + + pa_atomic_store(&m->wakeup_requested, true); } static void clear_wakeup(pa_mainloop *m) { @@ -802,12 +783,9 @@ static void clear_wakeup(pa_mainloop *m) { pa_assert(m); - 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)); - m->wakeup_requested = 0; + if (pa_atomic_cmpxchg(&m->wakeup_requested, true, false)) { + while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c)) + ; } } @@ -844,10 +822,15 @@ quit: } static int usec_to_timeout(pa_usec_t u) { + int timeout; + if (u == PA_USEC_INVALID) return -1; - return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC; + timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC; + pa_assert(timeout >= 0); + + return timeout; } int pa_mainloop_poll(pa_mainloop *m) { @@ -878,7 +861,7 @@ int pa_mainloop_poll(pa_mainloop *m) { m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout), NULL); #else - m->poll_func_ret = poll( + m->poll_func_ret = pa_poll( m->pollfds, m->n_pollfds, usec_to_timeout(m->prepared_timeout)); #endif @@ -901,7 +884,7 @@ quit: } int pa_mainloop_dispatch(pa_mainloop *m) { - int dispatched = 0; + unsigned dispatched = 0; pa_assert(m); pa_assert(m->state == STATE_POLLED); @@ -927,7 +910,7 @@ int pa_mainloop_dispatch(pa_mainloop *m) { m->state = STATE_PASSIVE; - return dispatched; + return (int) dispatched; quit: m->state = STATE_QUIT; @@ -936,6 +919,7 @@ quit: int pa_mainloop_get_retval(pa_mainloop *m) { pa_assert(m); + return m->retval; } @@ -964,26 +948,26 @@ quit: 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; - else if (r < 0) - return -1; else - return 0; + return -1; } void pa_mainloop_quit(pa_mainloop *m, int retval) { pa_assert(m); - m->quit = TRUE; + m->quit = true; m->retval = retval; pa_mainloop_wakeup(m); } -pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) { +pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) { pa_assert(m); + return &m->api; } @@ -994,7 +978,7 @@ void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *use m->poll_func_userdata = userdata; } -pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m) { +bool pa_mainloop_is_our_api(pa_mainloop_api *m) { pa_assert(m); return m->io_new == mainloop_io_new;