diff options
| author | Daniel Mack <daniel@caiaq.de> | 2009-09-22 11:30:30 +0800 | 
|---|---|---|
| committer | Daniel Mack <daniel@caiaq.de> | 2009-09-22 11:30:30 +0800 | 
| commit | 94aa9097f4ded68623160d754a4bf2632b8efc79 (patch) | |
| tree | 94a5e1192a18f760dc00ff5b36e1f7ba36fd449b /src/pulse/mainloop.c | |
| parent | c1e59f7d762fb147bc5250ebddb9cf5639aba522 (diff) | |
| parent | c194db71b0ff853b4f46df26e135edf63b215451 (diff) | |
Merge branch 'master' of git://0pointer.de/pulseaudio
Diffstat (limited to 'src/pulse/mainloop.c')
| -rw-r--r-- | src/pulse/mainloop.c | 179 | 
1 files changed, 96 insertions, 83 deletions
| diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 93a4742d..090ac8c2 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -78,6 +78,7 @@ struct pa_time_event {      pa_bool_t dead:1;      pa_bool_t enabled:1; +    pa_bool_t use_rtclock:1;      pa_usec_t time;      pa_time_event_cb_t callback; @@ -112,7 +113,7 @@ struct pa_mainloop {      struct pollfd *pollfds;      unsigned max_pollfds, n_pollfds; -    int prepared_timeout; +    pa_usec_t prepared_timeout;      pa_time_event *cached_next_time_event;      pa_mainloop_api api; @@ -172,17 +173,14 @@ static pa_io_event* mainloop_io_new(      m = a->userdata;      pa_assert(a == &m->api); -    e = pa_xnew(pa_io_event, 1); +    e = pa_xnew0(pa_io_event, 1);      e->mainloop = m; -    e->dead = FALSE;      e->fd = fd;      e->events = events; -    e->pollfd = NULL;      e->callback = callback;      e->userdata = userdata; -    e->destroy_callback = NULL;  #ifdef OS_IS_WIN32      { @@ -265,16 +263,14 @@ static pa_defer_event* mainloop_defer_new(      m = a->userdata;      pa_assert(a == &m->api); -    e = pa_xnew(pa_defer_event, 1); +    e = pa_xnew0(pa_defer_event, 1);      e->mainloop = m; -    e->dead = FALSE;      e->enabled = TRUE;      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); @@ -320,18 +316,20 @@ static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy  }  /* Time events */ -static pa_usec_t timeval_load(const struct timeval *tv) { -    pa_bool_t is_rtclock; +static pa_usec_t make_rt(const struct timeval *tv, pa_bool_t *use_rtclock) {      struct timeval ttv; -    if (!tv) +    if (!tv) { +        *use_rtclock = FALSE;          return PA_USEC_INVALID; +    }      ttv = *tv; -    is_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); -    ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; +    *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); -    if (!is_rtclock) +    if (*use_rtclock) +        ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; +    else          pa_rtclock_from_wallclock(&ttv);      return pa_timeval_load(&ttv); @@ -346,22 +344,23 @@ static pa_time_event* mainloop_time_new(      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); -    t = timeval_load(tv); +    t = make_rt(tv, &use_rtclock);      m = a->userdata;      pa_assert(a == &m->api); -    e = pa_xnew(pa_time_event, 1); +    e = pa_xnew0(pa_time_event, 1);      e->mainloop = m; -    e->dead = FALSE;      if ((e->enabled = (t != PA_USEC_INVALID))) {          e->time = t; +        e->use_rtclock= use_rtclock;          m->n_enabled_time_events++; @@ -375,7 +374,6 @@ static pa_time_event* mainloop_time_new(      e->callback = callback;      e->userdata = userdata; -    e->destroy_callback = NULL;      PA_LLIST_PREPEND(pa_time_event, m->time_events, e); @@ -388,11 +386,12 @@ static pa_time_event* mainloop_time_new(  static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {      pa_bool_t valid;      pa_usec_t t; +    pa_bool_t use_rtclock = FALSE;      pa_assert(e);      pa_assert(!e->dead); -    t = timeval_load(tv); +    t = make_rt(tv, &use_rtclock);      valid = (t != PA_USEC_INVALID);      if (e->enabled && !valid) { @@ -403,6 +402,7 @@ 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);      } @@ -480,9 +480,8 @@ pa_mainloop *pa_mainloop_new(void) {      pa_init_i18n(); -    m = pa_xnew(pa_mainloop, 1); +    m = pa_xnew0(pa_mainloop, 1); -    m->wakeup_pipe_type = 0;      if (pipe(m->wakeup_pipe) < 0) {          pa_log_error("ERROR: cannot create wakeup pipe");          pa_xfree(m); @@ -493,43 +492,23 @@ pa_mainloop *pa_mainloop_new(void) {      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->wakeup_requested = FALSE; - -    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; -    m->pollfds = NULL; -    m->max_pollfds = m->n_pollfds = 0;      m->rebuild_pollfds = TRUE; -    m->quit = FALSE; -    m->retval = 0; -      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;  }  static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) { -    pa_io_event *e; +    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; @@ -549,19 +528,15 @@ static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {              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; +    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; @@ -585,19 +560,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; +    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; @@ -621,8 +592,6 @@ 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); @@ -679,7 +648,7 @@ static void rebuild_pollfds(pa_mainloop *m) {          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; @@ -697,36 +666,46 @@ static void rebuild_pollfds(pa_mainloop *m) {      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; @@ -745,7 +724,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; @@ -763,12 +742,12 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {      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_usec_t clock_now; -    if (!m->n_enabled_time_events) -        return -1; +    if (m->n_enabled_time_events <= 0) +        return PA_USEC_INVALID;      pa_assert_se(t = find_next_time_event(m)); @@ -780,13 +759,13 @@ static int calc_next_timeout(pa_mainloop *m) {      if (t->time <= clock_now)          return 0; -    return (int) ((t->time - clock_now) / 1000); /* in milliseconds */ +    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) @@ -794,7 +773,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; @@ -806,7 +788,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, TRUE), e->userdata); +            e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);              r++;          } @@ -834,7 +816,8 @@ static void clear_wakeup(pa_mainloop *m) {          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;      }  } @@ -850,12 +833,17 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) {          goto quit;      if (m->n_enabled_defer_events <= 0) { +          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; @@ -866,6 +854,13 @@ quit:      return -2;  } +static int usec_to_timeout(pa_usec_t u) { +    if (u == PA_USEC_INVALID) +        return -1; + +    return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC; +} +  int pa_mainloop_poll(pa_mainloop *m) {      pa_assert(m);      pa_assert(m->state == STATE_PREPARED); @@ -881,9 +876,24 @@ int pa_mainloop_poll(pa_mainloop *m) {          pa_assert(!m->rebuild_pollfds);          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 = poll( +                    m->pollfds, m->n_pollfds, +                    usec_to_timeout(m->prepared_timeout)); +#endif +        }          if (m->poll_func_ret < 0) {              if (errno == EINTR) @@ -902,7 +912,7 @@ quit:  }  int pa_mainloop_dispatch(pa_mainloop *m) { -    int dispatched = 0; +    unsigned dispatched = 0;      pa_assert(m);      pa_assert(m->state == STATE_POLLED); @@ -928,7 +938,7 @@ int pa_mainloop_dispatch(pa_mainloop *m) {      m->state = STATE_PASSIVE; -    return dispatched; +    return (int) dispatched;  quit:      m->state = STATE_QUIT; @@ -937,6 +947,7 @@ quit:  int pa_mainloop_get_retval(pa_mainloop *m) {      pa_assert(m); +      return m->retval;  } @@ -965,7 +976,8 @@ 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; @@ -985,6 +997,7 @@ void pa_mainloop_quit(pa_mainloop *m, int retval) {  pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {      pa_assert(m); +      return &m->api;  } | 
