mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
prepare move to rtpoll
This commit is contained in:
parent
dd40006718
commit
3a09a88fd1
16 changed files with 436 additions and 70 deletions
|
|
@ -1329,7 +1329,7 @@ static void thread_func(void *userdata) {
|
|||
} else if (u->use_tsched)
|
||||
|
||||
/* OK, we're in an invalid state, let's disable our timers */
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
pa_rtpoll_disable_timer(u->rtpoll);
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
|
|
|
|||
|
|
@ -1188,7 +1188,7 @@ static void thread_func(void *userdata) {
|
|||
} else if (u->use_tsched)
|
||||
|
||||
/* OK, we're in an invalid state, let's disable our timers */
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
pa_rtpoll_disable_timer(u->rtpoll);
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
|
|
|
|||
|
|
@ -1161,7 +1161,7 @@ static void thread_func(void *userdata) {
|
|||
}
|
||||
|
||||
if (disable_timer)
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
pa_rtpoll_disable_timer(u->rtpoll);
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if (pollfd)
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ static void thread_func(void *userdata) {
|
|||
pa_rtpoll_set_timer_absolute(u->rtpoll, u->thread_info.timestamp);
|
||||
u->thread_info.in_null_mode = TRUE;
|
||||
} else {
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
pa_rtpoll_disable_timer(u->rtpoll);
|
||||
u->thread_info.in_null_mode = FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ static void thread_func(void *userdata) {
|
|||
|
||||
pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
|
||||
} else
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
pa_rtpoll_disable_timer(u->rtpoll);
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ static void thread_func(void *userdata) {
|
|||
|
||||
pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
|
||||
} else
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
pa_rtpoll_disable_timer(u->rtpoll);
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
|
|
|
|||
|
|
@ -2631,3 +2631,24 @@ char *pa_realpath(const char *path) {
|
|||
|
||||
return t;
|
||||
}
|
||||
|
||||
pa_bool_t pa_linux_newer_than(unsigned major, unsigned minor, unsigned micro) {
|
||||
|
||||
#ifdef __linux__
|
||||
unsigned _major, _minor, _micro;
|
||||
struct utsname u;
|
||||
|
||||
pa_assert_se(uname(&u) == 0);
|
||||
|
||||
if (sscanf(u.release, "%u.%u.%u", &_major, &_minor, &_micro) != 3)
|
||||
return FALSE;
|
||||
|
||||
return
|
||||
(_major > major) ||
|
||||
(_major == major && _minor > minor) ||
|
||||
(_major == major && _minor == minor && _micro > micro);
|
||||
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,4 +223,6 @@ char *pa_unescape(char *p);
|
|||
|
||||
char *pa_realpath(const char *path);
|
||||
|
||||
pa_bool_t pa_linux_newer_than(unsigned major, unsigned minor, unsigned micro);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -226,6 +226,8 @@ typedef int pa_bool_t;
|
|||
#define PA_DEBUG_TRAP raise(SIGTRAP)
|
||||
#endif
|
||||
|
||||
typedef void (*pa_function_t) (...);
|
||||
|
||||
/* We include this at the very last place */
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/winsock.h>
|
||||
|
|
|
|||
|
|
@ -145,6 +145,15 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
|
|||
return tv;
|
||||
}
|
||||
|
||||
struct timespec *pa_timespec_store(struct timespec *ts, pa_usec_t v) {
|
||||
pa_assert(ts);
|
||||
|
||||
ts->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
|
||||
ts->tv_nsec = (long) ((v % PA_USEC_PER_SEC) * PA_NSEC_PER_USEC);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
pa_usec_t pa_timespec_load(const struct timespec *ts) {
|
||||
pa_assert(ts);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ void pa_rtclock_hrtimer_enable(void);
|
|||
|
||||
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv);
|
||||
|
||||
struct timespec *pa_timespec_store(struct timespec *ts, pa_usec_t v);
|
||||
pa_usec_t pa_timespec_load(const struct timespec *ts);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
157
src/pulsecore/rtpoll-api.c
Normal file
157
src/pulsecore/rtpoll-api.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2009 Lennart Poettering
|
||||
|
||||
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.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "rtpoll-api.h"
|
||||
|
||||
struct event {
|
||||
pa_function_t callback;
|
||||
void *userdata;
|
||||
pa_function_t destroy;
|
||||
};
|
||||
|
||||
PA_STATIC_FLIST_DECLARE(events, 0, pa_xfree);
|
||||
|
||||
static short map_flags_to_libc(pa_io_event_flags_t flags) {
|
||||
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) {
|
||||
return
|
||||
(flags & POLLIN ? PA_IO_EVENT_INPUT : 0) |
|
||||
(flags & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) |
|
||||
(flags & POLLERR ? PA_IO_EVENT_ERROR : 0) |
|
||||
(flags & POLLHUP ? PA_IO_EVENT_HANGUP : 0);
|
||||
}
|
||||
|
||||
static pa_io_event* rtpoll_io_new(
|
||||
pa_mainloop_api*a,
|
||||
int fd,
|
||||
pa_io_event_flags_t f,
|
||||
pa_io_event_cb_t callback,
|
||||
void *userdata) {
|
||||
|
||||
pa_rtpoll_item *i;
|
||||
struct pollfd *pollfd;
|
||||
struct event *d;
|
||||
|
||||
i = pa_rtpoll_item_new(a->userdata, PA_RTPOLL_LATE, 1);
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
|
||||
pollfd->fd = fd;
|
||||
pollfd->events = map_flags_to_libc(f);
|
||||
|
||||
if (!(d = pa_flist_pop(PA_STATIC_FLIST_GET(events))))
|
||||
d = pa_xnew(struct event, 1);
|
||||
|
||||
d->callback = (pa_function_t) callback;
|
||||
d->userdata = userdata;
|
||||
d->destroy = NULL;
|
||||
|
||||
pa_rtpoll_item_set_userdata(i, d);
|
||||
|
||||
pa_rtpoll_item_set_work_callback(i, work_callback);
|
||||
|
||||
return (pa_io_event*) i;
|
||||
}
|
||||
|
||||
static void rtpoll_io_enable(pa_io_event *e, pa_io_event_flags_t f) {
|
||||
struct pollfd *pollfd;
|
||||
pa_rtpoll_item *i = (pa_rtpoll_item*) e;
|
||||
|
||||
pa_assert(i);
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
|
||||
pollfd->events = map_flags_to_libc(f);
|
||||
}
|
||||
|
||||
static void rtpoll_io_free(pa_io_event *e) {
|
||||
pa_rtpoll_item *i = (pa_rtpoll_item*) e;
|
||||
struct event *d;
|
||||
|
||||
pa_assert(i);
|
||||
|
||||
d = pa_rtpoll_item_get_userdata(i);
|
||||
|
||||
if (d->destroy_callback)
|
||||
d->destroy_callback(pa_rtpoll_get_userdata(pa_rtpoll_item_rtpoll(i)), i, d->userdata);
|
||||
|
||||
if (pa_flist_push(PA_STATIC_FLIST_GET(events), d) < 0)
|
||||
pa_xfree(d);
|
||||
|
||||
pa_rtpoll_item_free(i);
|
||||
}
|
||||
|
||||
static void rtpoll_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cb) {
|
||||
pa_rtpoll_item *i = (pa_rtpoll_item*) e;
|
||||
struct event *d;
|
||||
|
||||
pa_assert(e);
|
||||
|
||||
d = pa_rtpoll_item_get_userdata(i);
|
||||
|
||||
d->destroy = (pa_function_t) cb);
|
||||
}
|
||||
|
||||
static const pa_mainloop_api vtable = {
|
||||
.userdata = NULL,
|
||||
|
||||
.io_new = rtpoll_io_new,
|
||||
.io_enable = rtpoll_io_enable,
|
||||
.io_free = rtpoll_io_free,
|
||||
.io_set_destroy= rtpoll_io_set_destroy,
|
||||
|
||||
.time_new = rtpoll_time_new,
|
||||
.time_restart = rtpoll_time_restart,
|
||||
.time_free = rtpoll_time_free,
|
||||
.time_set_destroy = rtpoll_time_set_destroy,
|
||||
|
||||
.defer_new = rtpoll_defer_new,
|
||||
.defer_enable = rtpoll_defer_enable,
|
||||
.defer_free = rtpoll_defer_free,
|
||||
.defer_set_destroy = rtpoll_defer_set_destroy,
|
||||
|
||||
.quit = rtpoll_quit,
|
||||
};
|
||||
|
||||
pa_mainloop_api* pa_rtpoll_api_new(pa_rtpoll *p) {
|
||||
pa_mainloop_api *api;
|
||||
|
||||
pa_assert(p);
|
||||
|
||||
api = pa_memdup(pa_mainloop_api, vtable, 1);
|
||||
api->userdata = p;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void pa_rtpoll_api_free(pa_mainloop_api *api) {
|
||||
pa_assert(p);
|
||||
|
||||
pa_xfree(p);
|
||||
}
|
||||
32
src/pulsecore/rtpoll-api.h
Normal file
32
src/pulsecore/rtpoll-api.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef foopulsertpollapihfoo
|
||||
#define foopulsertpollapihfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2009 Lennart Poettering
|
||||
|
||||
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.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
/* A pa_mainloop_api implementation on top of rtpoll */
|
||||
|
||||
#include <pulse/mainloop-api.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
|
||||
pa_mainloop_api* pa_rtpoll_get_api(pa_rtpoll *p);
|
||||
|
||||
#endif
|
||||
|
|
@ -52,6 +52,7 @@
|
|||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/ratelimit.h>
|
||||
#include <pulsecore/prioq.h>
|
||||
|
||||
#include "rtpoll.h"
|
||||
|
||||
|
|
@ -61,7 +62,9 @@ struct pa_rtpoll {
|
|||
struct pollfd *pollfd, *pollfd2;
|
||||
unsigned n_pollfd_alloc, n_pollfd_used;
|
||||
|
||||
struct timeval next_elapse;
|
||||
pa_prioq *prioq;
|
||||
|
||||
pa_usec_t elapse;
|
||||
pa_bool_t timer_enabled:1;
|
||||
|
||||
pa_bool_t scan_for_dead:1;
|
||||
|
|
@ -70,16 +73,18 @@ struct pa_rtpoll {
|
|||
pa_bool_t rebuild_needed:1;
|
||||
pa_bool_t quit:1;
|
||||
|
||||
#ifdef HAVE_PPOLL
|
||||
#if defined(HAVE_PPOLL) && defined(__linux__)
|
||||
pa_bool_t use_ppoll:1;
|
||||
pa_bool_t use_signals:1;
|
||||
|
||||
pa_bool_t timer_armed:1;
|
||||
#ifdef __linux__
|
||||
pa_bool_t dont_use_ppoll:1;
|
||||
#endif
|
||||
int rtsig;
|
||||
sigset_t sigset_unblocked;
|
||||
timer_t timer;
|
||||
#endif
|
||||
|
||||
void *userdata;
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
pa_usec_t timestamp;
|
||||
pa_usec_t slept, awake;
|
||||
|
|
@ -90,10 +95,15 @@ struct pa_rtpoll {
|
|||
|
||||
struct pa_rtpoll_item {
|
||||
pa_rtpoll *rtpoll;
|
||||
pa_bool_t dead;
|
||||
|
||||
pa_rtpoll_priority_t priority;
|
||||
|
||||
pa_bool_t dead:1;
|
||||
|
||||
pa_bool_t timer_enabled:1;
|
||||
pa_usec_t elapse;
|
||||
|
||||
pa_prioq_item *prioq_item;
|
||||
|
||||
struct pollfd *pollfd;
|
||||
unsigned n_pollfd;
|
||||
|
||||
|
|
@ -109,38 +119,40 @@ PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
|
|||
|
||||
static void signal_handler_noop(int s) { /* write(2, "signal\n", 7); */ }
|
||||
|
||||
static int item_compare(const void *_a, const void *_b) {
|
||||
const pa_rtpoll_item *a = _a, *b = _b;
|
||||
|
||||
pa_assert(a->timer_enabled);
|
||||
pa_assert(b->timer_enabled);
|
||||
|
||||
if (a->elapse < b->elapse)
|
||||
return -1;
|
||||
if (a->elapse > b->elapse)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pa_rtpoll *pa_rtpoll_new(void) {
|
||||
pa_rtpoll *p;
|
||||
|
||||
p = pa_xnew(pa_rtpoll, 1);
|
||||
|
||||
#ifdef HAVE_PPOLL
|
||||
p->userdata = NULL;
|
||||
|
||||
#ifdef __linux__
|
||||
/* ppoll is broken on Linux < 2.6.16 */
|
||||
p->dont_use_ppoll = FALSE;
|
||||
#if defined(HAVE_PPOLL) && defined(__linux__)
|
||||
/* ppoll() is broken on Linux < 2.6.16. Don't use it. */
|
||||
p->use_ppoll = pa_linux_newer_than(2, 6, 16);
|
||||
|
||||
{
|
||||
struct utsname u;
|
||||
unsigned major, minor, micro;
|
||||
|
||||
pa_assert_se(uname(&u) == 0);
|
||||
|
||||
if (sscanf(u.release, "%u.%u.%u", &major, &minor, µ) != 3 ||
|
||||
(major < 2) ||
|
||||
(major == 2 && minor < 6) ||
|
||||
(major == 2 && minor == 6 && micro < 16))
|
||||
|
||||
p->dont_use_ppoll = TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Starting with Linux 2.6.28 ppoll() does no longer round up
|
||||
* timeouts to multiple of HZ, hence using signal based timers is
|
||||
* no longer necessary. */
|
||||
p->use_signals = p->use_ppoll && !pa_linux_newer_than(2, 6, 28);
|
||||
|
||||
p->rtsig = -1;
|
||||
sigemptyset(&p->sigset_unblocked);
|
||||
p->timer = (timer_t) -1;
|
||||
p->timer_armed = FALSE;
|
||||
|
||||
#endif
|
||||
|
||||
p->n_pollfd_alloc = 32;
|
||||
|
|
@ -148,7 +160,9 @@ pa_rtpoll *pa_rtpoll_new(void) {
|
|||
p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
|
||||
p->n_pollfd_used = 0;
|
||||
|
||||
memset(&p->next_elapse, 0, sizeof(p->next_elapse));
|
||||
p->prioq = pa_prioq_new(item_compare);
|
||||
|
||||
p->elapse = 0;
|
||||
p->timer_enabled = FALSE;
|
||||
|
||||
p->running = FALSE;
|
||||
|
|
@ -173,11 +187,10 @@ void pa_rtpoll_install(pa_rtpoll *p) {
|
|||
|
||||
p->installed = TRUE;
|
||||
|
||||
#ifdef HAVE_PPOLL
|
||||
# ifdef __linux__
|
||||
if (p->dont_use_ppoll)
|
||||
#if defined(HAVE_PPOLL) && defined(__linux__)
|
||||
|
||||
if (!p->use_signals)
|
||||
return;
|
||||
# endif
|
||||
|
||||
if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
|
||||
pa_log_warn("Failed to reserve POSIX realtime signal.");
|
||||
|
|
@ -250,7 +263,6 @@ static void rtpoll_rebuild(pa_rtpoll *p) {
|
|||
|
||||
if (ra)
|
||||
p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
|
||||
|
||||
}
|
||||
|
||||
static void rtpoll_item_destroy(pa_rtpoll_item *i) {
|
||||
|
|
@ -262,11 +274,15 @@ static void rtpoll_item_destroy(pa_rtpoll_item *i) {
|
|||
|
||||
PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
|
||||
|
||||
pa_assert(p->n_pollfd_used >= i->n_pollfd);
|
||||
p->n_pollfd_used -= i->n_pollfd;
|
||||
|
||||
if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
|
||||
pa_xfree(i);
|
||||
|
||||
if (i->prioq_item)
|
||||
pa_prioq_remove(p->prioq, i->prioq_item);
|
||||
|
||||
p->rebuild_needed = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -279,11 +295,14 @@ void pa_rtpoll_free(pa_rtpoll *p) {
|
|||
pa_xfree(p->pollfd);
|
||||
pa_xfree(p->pollfd2);
|
||||
|
||||
#ifdef HAVE_PPOLL
|
||||
#if defined(HAVE_PPOLL) && defined(__linux__)
|
||||
if (p->timer != (timer_t) -1)
|
||||
timer_delete(p->timer);
|
||||
#endif
|
||||
|
||||
if (p->prioq)
|
||||
pa_prioq_free(p->prioq, NULL, NULL);
|
||||
|
||||
pa_xfree(p);
|
||||
}
|
||||
|
||||
|
|
@ -314,10 +333,36 @@ static void reset_all_revents(pa_rtpoll *p) {
|
|||
}
|
||||
}
|
||||
|
||||
static pa_bool_t next_elapse(pa_rtpoll *p, pa_usec_t *usec) {
|
||||
pa_rtpoll_item *i;
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(usec);
|
||||
|
||||
i = pa_prioq_peek(p->prioq);
|
||||
|
||||
if (p->timer_enabled) {
|
||||
|
||||
if (i && i->timer_enabled)
|
||||
*usec = PA_MIN(i->elapse, p->elapse);
|
||||
else
|
||||
*usec = p->elapse;
|
||||
|
||||
return TRUE;
|
||||
|
||||
} else if (i && i->timer_enabled) {
|
||||
*usec = i->elapse;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
|
||||
pa_rtpoll_item *i;
|
||||
int r = 0;
|
||||
struct timeval timeout;
|
||||
pa_usec_t timeout;
|
||||
pa_bool_t timeout_valid;
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(!p->running);
|
||||
|
|
@ -381,15 +426,20 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
|
|||
if (p->rebuild_needed)
|
||||
rtpoll_rebuild(p);
|
||||
|
||||
memset(&timeout, 0, sizeof(timeout));
|
||||
timeout = 0;
|
||||
timeout_valid = FALSE;
|
||||
|
||||
/* Calculate timeout */
|
||||
if (wait && !p->quit && p->timer_enabled) {
|
||||
struct timeval now;
|
||||
pa_rtclock_get(&now);
|
||||
if (wait && !p->quit) {
|
||||
pa_usec_t elapse;
|
||||
|
||||
if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
|
||||
pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
|
||||
if (next_elapse(p, &elapse)) {
|
||||
pa_usec_t now;
|
||||
|
||||
now = pa_rtclock_usec();
|
||||
timeout = now >= elapse ? 0 : elapse - now;
|
||||
timeout_valid = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
|
|
@ -404,20 +454,22 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
|
|||
#ifdef HAVE_PPOLL
|
||||
|
||||
#ifdef __linux__
|
||||
if (!p->dont_use_ppoll)
|
||||
if (p->use_ppoll)
|
||||
#endif
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout.tv_sec;
|
||||
ts.tv_nsec = timeout.tv_usec * 1000;
|
||||
r = ppoll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? &ts : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
|
||||
pa_timespec_store(&ts, timeout);
|
||||
r = ppoll(p->pollfd, p->n_pollfd_used,
|
||||
(!wait || p->quit || timeout_valid) ? &ts : NULL,
|
||||
p->rtsig < 0 ? NULL : &p->sigset_unblocked);
|
||||
}
|
||||
#ifdef __linux__
|
||||
else
|
||||
#endif
|
||||
|
||||
#endif
|
||||
r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1);
|
||||
r = poll(p->pollfd, p->n_pollfd_used,
|
||||
(!wait || p->quit || timeout_valid) ? (int) (timeout / PA_USEC_PER_MSEC) : -1);
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
{
|
||||
|
|
@ -475,12 +527,10 @@ finish:
|
|||
static void update_timer(pa_rtpoll *p) {
|
||||
pa_assert(p);
|
||||
|
||||
#ifdef HAVE_PPOLL
|
||||
#if defined(HAVE_PPOLL) && defined(__linux__)
|
||||
|
||||
#ifdef __linux__
|
||||
if (p->dont_use_ppoll)
|
||||
if (!p->use_signals)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (p->timer == (timer_t) -1) {
|
||||
struct sigevent se;
|
||||
|
|
@ -500,6 +550,7 @@ static void update_timer(pa_rtpoll *p) {
|
|||
struct itimerspec its;
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
sigset_t ss;
|
||||
pa_usec_t elapse;
|
||||
|
||||
if (p->timer_armed) {
|
||||
/* First disarm timer */
|
||||
|
|
@ -513,16 +564,16 @@ static void update_timer(pa_rtpoll *p) {
|
|||
}
|
||||
|
||||
/* And install the new timer */
|
||||
if (p->timer_enabled) {
|
||||
if (next_elapse(p, &elapse)) {
|
||||
memset(&its, 0, sizeof(its));
|
||||
|
||||
its.it_value.tv_sec = p->next_elapse.tv_sec;
|
||||
its.it_value.tv_nsec = p->next_elapse.tv_usec*1000;
|
||||
pa_timespec_store(&its.it_value, elapse);
|
||||
|
||||
/* Make sure that 0,0 is not understood as
|
||||
* "disarming" */
|
||||
if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
|
||||
its.it_value.tv_nsec = 1;
|
||||
|
||||
pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
|
||||
}
|
||||
|
||||
|
|
@ -535,7 +586,10 @@ static void update_timer(pa_rtpoll *p) {
|
|||
void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
|
||||
pa_assert(p);
|
||||
|
||||
pa_timeval_store(&p->next_elapse, usec);
|
||||
if (p->timer_enabled && p->elapse == usec)
|
||||
return
|
||||
|
||||
p->elapse = usec;
|
||||
p->timer_enabled = TRUE;
|
||||
|
||||
update_timer(p);
|
||||
|
|
@ -547,20 +601,32 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
|
|||
/* Scheduling a timeout for more than an hour is very very suspicious */
|
||||
pa_assert(usec <= PA_USEC_PER_SEC*60ULL*60ULL);
|
||||
|
||||
pa_rtclock_get(&p->next_elapse);
|
||||
pa_timeval_add(&p->next_elapse, usec);
|
||||
p->timer_enabled = TRUE;
|
||||
pa_rtpoll_set_timer_absolute(p, pa_rtclock_usec() + usec);
|
||||
}
|
||||
|
||||
void pa_rtpoll_disable_timer(pa_rtpoll *p) {
|
||||
pa_assert(p);
|
||||
|
||||
if (!p->timer_enabled)
|
||||
return;
|
||||
|
||||
p->elapse = 0;
|
||||
p->timer_enabled = FALSE;
|
||||
|
||||
update_timer(p);
|
||||
}
|
||||
|
||||
void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
|
||||
|
||||
void pa_rtpoll_set_userdata(pa_rtpoll *p, void *userdata) {
|
||||
pa_assert(p);
|
||||
|
||||
memset(&p->next_elapse, 0, sizeof(p->next_elapse));
|
||||
p->timer_enabled = FALSE;
|
||||
p->userdata = userdata;
|
||||
}
|
||||
|
||||
update_timer(p);
|
||||
void* pa_rtpoll_get_userdata(pa_rtpoll *p) {
|
||||
pa_assert(p);
|
||||
|
||||
return p->userdata;
|
||||
}
|
||||
|
||||
pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
|
||||
|
|
@ -576,6 +642,9 @@ pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsi
|
|||
i->n_pollfd = n_fds;
|
||||
i->pollfd = NULL;
|
||||
i->priority = prio;
|
||||
i->timer_enabled = FALSE;
|
||||
i->elapse = 0;
|
||||
i->prioq_item = NULL;
|
||||
|
||||
i->userdata = NULL;
|
||||
i->before_cb = NULL;
|
||||
|
|
@ -592,7 +661,7 @@ pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsi
|
|||
PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
|
||||
|
||||
if (n_fds > 0) {
|
||||
p->rebuild_needed = 1;
|
||||
p->rebuild_needed = TRUE;
|
||||
p->n_pollfd_used += n_fds;
|
||||
}
|
||||
|
||||
|
|
@ -624,6 +693,63 @@ struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
|
|||
return i->pollfd;
|
||||
}
|
||||
|
||||
void pa_rtpoll_item_set_n_fds(pa_rtpoll_item *i, unsigned n_fds) {
|
||||
pa_assert(i);
|
||||
|
||||
if (i->n_pollfd == n_fds)
|
||||
return;
|
||||
|
||||
pa_assert(i->rtpoll->n_pollfd_used >= i->n_pollfd);
|
||||
i->rtpoll->n_pollfd_used = i->rtpoll->n_pollfd_used - i->n_pollfd + n_fds;
|
||||
i->n_pollfd = n_fds;
|
||||
|
||||
i->pollfd = NULL;
|
||||
i->rtpoll->rebuild_needed = TRUE;
|
||||
}
|
||||
|
||||
void pa_rtpoll_item_set_timer_absolute(pa_rtpoll_item *i, pa_usec_t usec){
|
||||
pa_assert(i);
|
||||
|
||||
if (i->timer_enabled && i->elapse == usec)
|
||||
return;
|
||||
|
||||
i->timer_enabled = TRUE;
|
||||
i->elapse = usec;
|
||||
|
||||
if (i->prioq_item)
|
||||
pa_prioq_reshuffle(i->rtpoll->prioq, i->prioq_item);
|
||||
else
|
||||
i->prioq_item = pa_prioq_put(i->rtpoll->prioq, i);
|
||||
|
||||
update_timer(i->rtpoll);
|
||||
}
|
||||
|
||||
void pa_rtpoll_item_set_timer_relative(pa_rtpoll_item *i, pa_usec_t usec) {
|
||||
pa_assert(i);
|
||||
|
||||
/* Scheduling a timeout for more than an hour is very very suspicious */
|
||||
pa_assert(usec <= PA_USEC_PER_SEC*60ULL*60ULL);
|
||||
|
||||
pa_rtpoll_item_set_timer_absolute(i, pa_rtclock_usec() + usec);
|
||||
}
|
||||
|
||||
void pa_rtpoll_item_disable_timer(pa_rtpoll_item *i) {
|
||||
pa_assert(i);
|
||||
|
||||
if (!i->timer_enabled)
|
||||
return;
|
||||
|
||||
i->timer_enabled = FALSE;
|
||||
i->elapse = 0;
|
||||
|
||||
if (i->prioq_item) {
|
||||
pa_prioq_remove(i->rtpoll->prioq, i->prioq_item);
|
||||
i->prioq_item = NULL;
|
||||
}
|
||||
|
||||
update_timer(i->rtpoll);
|
||||
}
|
||||
|
||||
void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
|
||||
pa_assert(i);
|
||||
pa_assert(i->priority < PA_RTPOLL_NEVER);
|
||||
|
|
@ -657,6 +783,12 @@ void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
|
|||
return i->userdata;
|
||||
}
|
||||
|
||||
pa_rtpoll *pa_rtpoll_item_rtpoll(pa_rtpoll_item *i) {
|
||||
pa_assert(i);
|
||||
|
||||
return i->rtpoll;
|
||||
}
|
||||
|
||||
static int fdsem_before(pa_rtpoll_item *i) {
|
||||
|
||||
if (pa_fdsem_before_poll(i->userdata) < 0)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ int pa_rtpoll_run(pa_rtpoll *f, pa_bool_t wait);
|
|||
|
||||
void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec);
|
||||
void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec);
|
||||
void pa_rtpoll_set_timer_disabled(pa_rtpoll *p);
|
||||
void pa_rtpoll_disable_timer(pa_rtpoll *p);
|
||||
|
||||
void pa_rtpoll_set_userdata(pa_rtpoll *i, void *userdata);
|
||||
void* pa_rtpoll_get_userdata(pa_rtpoll *i);
|
||||
|
||||
/* A new fd wakeup item for pa_rtpoll */
|
||||
pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds);
|
||||
|
|
@ -85,6 +88,8 @@ void pa_rtpoll_item_free(pa_rtpoll_item *i);
|
|||
* using the pointer and don't save the result anywhere */
|
||||
struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds);
|
||||
|
||||
void pa_rtpoll_item_set_n_fds(pa_rtpoll_item *i, unsigned n_fds);
|
||||
|
||||
/* Set the callback that shall be called when there's time to do some work: If the
|
||||
* callback returns a value > 0, the poll is skipped and the next
|
||||
* iteraton of the loop will start immediately. */
|
||||
|
|
@ -103,6 +108,12 @@ void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rt
|
|||
void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata);
|
||||
void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i);
|
||||
|
||||
void pa_rtpoll_item_set_timer_absolute(pa_rtpoll_item *i, pa_usec_t usec);
|
||||
void pa_rtpoll_item_set_timer_relative(pa_rtpoll_item *i, pa_usec_t usec);
|
||||
void pa_rtpoll_item_disable_timer(pa_rtpoll_item *i);
|
||||
|
||||
pa_rtpoll *pa_rtpoll_item_rtpoll(pa_rtpoll_item *i);
|
||||
|
||||
pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *s);
|
||||
pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q);
|
||||
pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue