diff options
Diffstat (limited to 'src/pulsecore')
33 files changed, 621 insertions, 612 deletions
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c index e191b05f..083d9de2 100644 --- a/src/pulsecore/asyncmsgq.c +++ b/src/pulsecore/asyncmsgq.c @@ -172,11 +172,11 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi return i.ret; } -int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, pa_bool_t wait) { +int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, pa_bool_t wait_op) { pa_assert(PA_REFCNT_VALUE(a) > 0); pa_assert(!a->current); - if (!(a->current = pa_asyncq_pop(a->asyncq, wait))) { + if (!(a->current = pa_asyncq_pop(a->asyncq, wait_op))) { /* pa_log("failure"); */ return -1; } diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c index 67f661fe..072ef02c 100644 --- a/src/pulsecore/asyncq.c +++ b/src/pulsecore/asyncq.c @@ -131,7 +131,7 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) { pa_xfree(l); } -static int push(pa_asyncq*l, void *p, pa_bool_t wait) { +static int push(pa_asyncq*l, void *p, pa_bool_t wait_op) { unsigned idx; pa_atomic_ptr_t *cells; @@ -145,7 +145,7 @@ static int push(pa_asyncq*l, void *p, pa_bool_t wait) { if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) { - if (!wait) + if (!wait_op) return -1; /* pa_log("sleeping on push"); */ @@ -163,14 +163,14 @@ static int push(pa_asyncq*l, void *p, pa_bool_t wait) { return 0; } -static pa_bool_t flush_postq(pa_asyncq *l, pa_bool_t wait) { +static pa_bool_t flush_postq(pa_asyncq *l, pa_bool_t wait_op) { struct localq *q; pa_assert(l); while ((q = l->last_localq)) { - if (push(l, q->data, wait) < 0) + if (push(l, q->data, wait_op) < 0) return FALSE; l->last_localq = q->prev; @@ -184,13 +184,13 @@ static pa_bool_t flush_postq(pa_asyncq *l, pa_bool_t wait) { return TRUE; } -int pa_asyncq_push(pa_asyncq*l, void *p, pa_bool_t wait) { +int pa_asyncq_push(pa_asyncq*l, void *p, pa_bool_t wait_op) { pa_assert(l); - if (!flush_postq(l, wait)) + if (!flush_postq(l, wait_op)) return -1; - return push(l, p, wait); + return push(l, p, wait_op); } void pa_asyncq_post(pa_asyncq*l, void *p) { @@ -221,7 +221,7 @@ void pa_asyncq_post(pa_asyncq*l, void *p) { return; } -void* pa_asyncq_pop(pa_asyncq*l, pa_bool_t wait) { +void* pa_asyncq_pop(pa_asyncq*l, pa_bool_t wait_op) { unsigned idx; void *ret; pa_atomic_ptr_t *cells; @@ -235,7 +235,7 @@ void* pa_asyncq_pop(pa_asyncq*l, pa_bool_t wait) { if (!(ret = pa_atomic_ptr_load(&cells[idx]))) { - if (!wait) + if (!wait_op) return NULL; /* pa_log("sleeping on pop"); */ diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c index 56d9d3dd..f1f08bcc 100644 --- a/src/pulsecore/avahi-wrap.c +++ b/src/pulsecore/avahi-wrap.c @@ -23,6 +23,7 @@ #include <config.h> #endif +#include <pulse/timeval.h> #include <pulse/xmalloc.h> #include <pulsecore/log.h> @@ -116,14 +117,13 @@ struct AvahiTimeout { void *userdata; }; -static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { - AvahiTimeout *t = userdata; +static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { + AvahiTimeout *to = userdata; pa_assert(a); pa_assert(e); - pa_assert(t); - t->callback(t, t->userdata); + to->callback(to, to->userdata); } static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { @@ -145,6 +145,7 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, } static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { + pa_assert(t); if (t->time_event && tv) diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/core-rtclock.c index 65c826a6..3b3e3a64 100644 --- a/src/pulsecore/rtclock.c +++ b/src/pulsecore/core-rtclock.c @@ -37,7 +37,7 @@ #include <pulsecore/macro.h> #include <pulsecore/core-error.h> -#include "rtclock.h" +#include "core-rtclock.h" pa_usec_t pa_rtclock_age(const struct timeval *tv) { struct timeval now; @@ -65,7 +65,7 @@ struct timeval *pa_rtclock_get(struct timeval *tv) { pa_assert(tv); tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / 1000; + tv->tv_usec = ts.tv_nsec / PA_NSEC_PER_USEC; return tv; @@ -82,11 +82,11 @@ pa_bool_t pa_rtclock_hrtimer(void) { #ifdef CLOCK_MONOTONIC if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0) - return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; + return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC); #endif pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0); - return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; + return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC); #else /* HAVE_CLOCK_GETTIME */ @@ -122,12 +122,6 @@ void pa_rtclock_hrtimer_enable(void) { #endif } -pa_usec_t pa_rtclock_usec(void) { - struct timeval tv; - - return pa_timeval_load(pa_rtclock_get(&tv)); -} - struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) { #ifdef HAVE_CLOCK_GETTIME @@ -156,3 +150,41 @@ pa_usec_t pa_timespec_load(const struct timespec *ts) { (pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC + (pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC; } + + +static struct timeval* wallclock_from_rtclock(struct timeval *tv) { + +#ifdef HAVE_CLOCK_GETTIME + struct timeval wc_now, rt_now; + + pa_gettimeofday(&wc_now); + pa_rtclock_get(&rt_now); + + pa_assert(tv); + + if (pa_timeval_cmp(&rt_now, tv) < 0) + pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now)); + else + pa_timeval_sub(&wc_now, pa_timeval_diff(&rt_now, tv)); + + *tv = wc_now; +#endif + + return tv; +} + +struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock) { + pa_assert(tv); + + if (v == PA_USEC_INVALID) + return NULL; + + pa_timeval_store(tv, v); + + if (rtclock) + tv->tv_usec |= PA_TIMEVAL_RTCLOCK; + else + wallclock_from_rtclock(tv); + + return tv; +} diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/core-rtclock.h index 03cc1c72..9f5ae2dd 100644 --- a/src/pulsecore/rtclock.h +++ b/src/pulsecore/core-rtclock.h @@ -31,8 +31,6 @@ struct timeval; struct timeval *pa_rtclock_get(struct timeval *ts); -pa_usec_t pa_rtclock_usec(void); - pa_usec_t pa_rtclock_age(const struct timeval *tv); pa_bool_t pa_rtclock_hrtimer(void); void pa_rtclock_hrtimer_enable(void); @@ -40,8 +38,13 @@ void pa_rtclock_hrtimer_enable(void); /* timer with a resolution better than this are considered high-resolution */ #define PA_HRTIMER_THRESHOLD_USEC 10 +/* bit to set in tv.tv_usec to mark that the timeval is in monotonic time */ +#define PA_TIMEVAL_RTCLOCK ((time_t) (1LU << 30)) + struct timeval* pa_rtclock_from_wallclock(struct timeval *tv); pa_usec_t pa_timespec_load(const struct timespec *ts); +struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock); + #endif diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 086f5fcb..4c5a4b26 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -47,6 +47,7 @@ #include <pulse/util.h> #include <pulse/volume.h> #include <pulse/xmalloc.h> +#include <pulse/rtclock.h> #include <pulsecore/sink-input.h> #include <pulsecore/sample-util.h> @@ -54,6 +55,7 @@ #include <pulsecore/core-subscribe.h> #include <pulsecore/namereg.h> #include <pulsecore/sound-file.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/core-util.h> #include <pulsecore/log.h> #include <pulsecore/core-error.h> @@ -61,11 +63,10 @@ #include "core-scache.h" -#define UNLOAD_POLL_TIME 60 +#define UNLOAD_POLL_TIME (60 * PA_USEC_PER_SEC) -static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_core *c = userdata; - struct timeval ntv; pa_assert(c); pa_assert(c->mainloop == m); @@ -73,9 +74,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct t pa_scache_unload_unused(c); - pa_gettimeofday(&ntv); - ntv.tv_sec += UNLOAD_POLL_TIME; - m->time_restart(e, &ntv); + pa_core_rttime_restart(c, e, pa_rtclock_now() + UNLOAD_POLL_TIME); } static void free_entry(pa_scache_entry *e) { @@ -256,12 +255,8 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, pa_proplist_sets(e->proplist, PA_PROP_MEDIA_FILENAME, filename); - if (!c->scache_auto_unload_event) { - struct timeval ntv; - pa_gettimeofday(&ntv); - ntv.tv_sec += UNLOAD_POLL_TIME; - c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); - } + if (!c->scache_auto_unload_event) + c->scache_auto_unload_event = pa_core_rttime_new(c, pa_rtclock_now() + UNLOAD_POLL_TIME, timeout_callback, c); if (idx) *idx = e->index; diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index a71ba0b0..04e7eb24 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -43,6 +43,7 @@ #include <regex.h> #include <langinfo.h> #include <sys/utsname.h> +#include <sys/socket.h> #ifdef HAVE_STRTOF_L #include <locale.h> @@ -50,6 +51,10 @@ #ifdef HAVE_SCHED_H #include <sched.h> + +#if defined(__linux__) && !defined(SCHED_RESET_ON_FORK) +#define SCHED_RESET_ON_FORK 0x40000000 +#endif #endif #ifdef HAVE_SYS_RESOURCE_H @@ -92,6 +97,10 @@ #include <xlocale.h> #endif +#ifdef HAVE_DBUS +#include "rtkit.h" +#endif + #include <pulse/xmalloc.h> #include <pulse/util.h> #include <pulse/utf8.h> @@ -552,127 +561,121 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } -/* Make the current thread a realtime thread, and acquire the highest - * rtprio we can get that is less or equal the specified parameter. If - * the thread is already realtime, don't do anything. */ -int pa_make_realtime(int rtprio) { - -#ifdef _POSIX_PRIORITY_SCHEDULING +static int set_scheduler(int rtprio) { struct sched_param sp; - int r, policy; + int r; +#ifdef HAVE_DBUS + DBusError error; + DBusConnection *bus; - memset(&sp, 0, sizeof(sp)); - policy = 0; + dbus_error_init(&error); +#endif - if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { - pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r)); - return -1; + pa_zero(sp); + sp.sched_priority = rtprio; + +#ifdef SCHED_RESET_ON_FORK + if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) { + pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked."); + return 0; } +#endif - if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) { - pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority); + if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) { + pa_log_debug("SCHED_RR worked."); return 0; } - sp.sched_priority = rtprio; - if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) { +#ifdef HAVE_DBUS + /* Try to talk to RealtimeKit */ - while (sp.sched_priority > 1) { - sp.sched_priority --; + if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { + pa_log("Failed to connect to system bus: %s\n", error.message); + dbus_error_free(&error); + errno = -EIO; + return -1; + } - if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) == 0) { - pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp.sched_priority, rtprio); - return 0; - } - } + r = rtkit_make_realtime(bus, 0, rtprio); + dbus_connection_unref(bus); - pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r)); - return -1; + if (r >= 0) { + pa_log_debug("RealtimeKit worked."); + return 0; } - pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority); - return 0; + errno = -r; #else + errno = r; +#endif - errno = ENOTSUP; return -1; -#endif } -/* This is merely used for giving the user a hint. This is not correct - * for anything security related */ -pa_bool_t pa_can_realtime(void) { - - if (geteuid() == 0) - return TRUE; +/* Make the current thread a realtime thread, and acquire the highest + * rtprio we can get that is less or equal the specified parameter. If + * the thread is already realtime, don't do anything. */ +int pa_make_realtime(int rtprio) { -#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO) - { - struct rlimit rl; +#ifdef _POSIX_PRIORITY_SCHEDULING + int p; - if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0) - if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY) - return TRUE; + if (set_scheduler(rtprio) >= 0) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio); + return 0; } -#endif - -#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE) - { - cap_t cap; - if ((cap = cap_get_proc())) { - cap_flag_value_t flag = CAP_CLEAR; + for (p = rtprio-1; p >= 1; p--) + if (set_scheduler(p)) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio); + return 0; + } - if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0) - if (flag == CAP_SET) { - cap_free(cap); - return TRUE; - } + pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno)); + return -1; +#else - cap_free(cap); - } - } + errno = ENOTSUP; + return -1; #endif - - return FALSE; } -/* This is merely used for giving the user a hint. This is not correct - * for anything security related */ -pa_bool_t pa_can_high_priority(void) { - - if (geteuid() == 0) - return TRUE; +static int set_nice(int nice_level) { +#ifdef HAVE_DBUS + DBusError error; + DBusConnection *bus; + int r; -#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO) - { - struct rlimit rl; + dbus_error_init(&error); +#endif - if (getrlimit(RLIMIT_NICE, &rl) >= 0) - if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY) - return TRUE; + if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) { + pa_log_debug("setpriority() worked."); + return 0; } -#endif -#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE) - { - cap_t cap; +#ifdef HAVE_DBUS + /* Try to talk to RealtimeKit */ - if ((cap = cap_get_proc())) { - cap_flag_value_t flag = CAP_CLEAR; + if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { + pa_log("Failed to connect to system bus: %s\n", error.message); + dbus_error_free(&error); + errno = -EIO; + return -1; + } - if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0) - if (flag == CAP_SET) { - cap_free(cap); - return TRUE; - } + r = rtkit_make_high_priority(bus, 0, nice_level); + dbus_connection_unref(bus); - cap_free(cap); - } + if (r >= 0) { + pa_log_debug("RealtimeKit worked."); + return 0; } + + errno = -r; #endif - return FALSE; + return -1; } /* Raise the priority of the current process as much as possible that @@ -680,22 +683,21 @@ pa_bool_t pa_can_high_priority(void) { int pa_raise_priority(int nice_level) { #ifdef HAVE_SYS_RESOURCE_H - if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) { - int n; + int n; - for (n = nice_level+1; n < 0; n++) { + if (set_nice(nice_level) >= 0) { + pa_log_info("Successfully gained nice level %i.", nice_level); + return 0; + } - if (setpriority(PRIO_PROCESS, 0, n) == 0) { - pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level); - return 0; - } + for (n = nice_level+1; n < 0; n++) + if (set_nice(n) > 0) { + pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level); + return 0; } - pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); - return -1; - } - - pa_log_info("Successfully gained nice level %i.", nice_level); + pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno)); + return -1; #endif #ifdef OS_IS_WIN32 @@ -703,9 +705,10 @@ int pa_raise_priority(int nice_level) { if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) { pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); errno = EPERM; - return .-1; - } else - pa_log_info("Successfully gained high priority class."); + return -1; + } + + pa_log_info("Successfully gained high priority class."); } #endif @@ -720,8 +723,8 @@ void pa_reset_priority(void) { setpriority(PRIO_PROCESS, 0, 0); - memset(&sp, 0, sizeof(sp)); - pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp) == 0); + pa_zero(sp); + pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp); #endif #ifdef OS_IS_WIN32 @@ -1191,22 +1194,22 @@ int pa_check_in_group(gid_t g) { (advisory on UNIX, mandatory on Windows) */ int pa_lock_fd(int fd, int b) { #ifdef F_SETLKW - struct flock flock; + struct flock f_lock; /* Try a R/W lock first */ - flock.l_type = (short) (b ? F_WRLCK : F_UNLCK); - flock.l_whence = SEEK_SET; - flock.l_start = 0; - flock.l_len = 0; + f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK); + f_lock.l_whence = SEEK_SET; + f_lock.l_start = 0; + f_lock.l_len = 0; - if (fcntl(fd, F_SETLKW, &flock) >= 0) + if (fcntl(fd, F_SETLKW, &f_lock) >= 0) return 0; /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */ if (b && errno == EBADF) { - flock.l_type = F_RDLCK; - if (fcntl(fd, F_SETLKW, &flock) >= 0) + f_lock.l_type = F_RDLCK; + if (fcntl(fd, F_SETLKW, &f_lock) >= 0) return 0; } @@ -2236,10 +2239,9 @@ int pa_close_all(int except_fd, ...) { int pa_close_allv(const int except_fds[]) { struct rlimit rl; int maxfd, fd; - int saved_errno; #ifdef __linux__ - + int saved_errno; DIR *d; if ((d = opendir("/proc/self/fd"))) { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index b841edbb..96a0480a 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -80,9 +80,6 @@ int pa_make_realtime(int rtprio); int pa_raise_priority(int nice_level); void pa_reset_priority(void); -pa_bool_t pa_can_realtime(void); -pa_bool_t pa_can_high_priority(void); - int pa_parse_boolean(const char *s) PA_GCC_PURE; static inline const char *pa_yes_no(pa_bool_t b) { diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 06573f17..f5eb8352 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <signal.h> +#include <pulse/rtclock.h> #include <pulse/timeval.h> #include <pulse/xmalloc.h> @@ -35,6 +36,7 @@ #include <pulsecore/sink.h> #include <pulsecore/source.h> #include <pulsecore/namereg.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/core-util.h> #include <pulsecore/core-scache.h> #include <pulsecore/core-subscribe.h> @@ -214,7 +216,7 @@ static void core_free(pa_object *o) { pa_xfree(c); } -static void exit_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void exit_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_core *c = userdata; pa_assert(c->exit_event == e); @@ -229,11 +231,7 @@ void pa_core_check_idle(pa_core *c) { c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) { - struct timeval tv; - pa_gettimeofday(&tv); - tv.tv_sec+= c->exit_idle_time; - - c->exit_event = c->mainloop->time_new(c->mainloop, &tv, exit_callback, c); + c->exit_event = pa_core_rttime_new(c, pa_rtclock_now() + c->exit_idle_time * PA_USEC_PER_SEC, exit_callback, c); } else if (c->exit_event && pa_idxset_size(c->clients) > 0) { c->mainloop->time_free(c->exit_event); @@ -261,3 +259,21 @@ void pa_core_maybe_vacuum(pa_core *c) { pa_log_debug("Hmm, no streams around, trying to vacuum."); pa_mempool_vacuum(c->mempool); } + +pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) { + struct timeval tv; + + pa_assert(c); + pa_assert(c->mainloop); + + return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, TRUE), cb, userdata); +} + +void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) { + struct timeval tv; + + pa_assert(c); + pa_assert(c->mainloop); + + c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, TRUE)); +} diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 09a880c4..e7abd61b 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -183,4 +183,8 @@ int pa_core_exit(pa_core *c, pa_bool_t force, int retval); void pa_core_maybe_vacuum(pa_core *c); +/* wrapper for c->mainloop->time_*() RT time events */ +pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata); +void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec); + #endif diff --git a/src/pulsecore/dbus-shared.c b/src/pulsecore/dbus-shared.c index 9d9445b6..20ef9b1e 100644 --- a/src/pulsecore/dbus-shared.c +++ b/src/pulsecore/dbus-shared.c @@ -70,7 +70,7 @@ pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *err if ((pconn = pa_shared_get(c, prop_name[type]))) return pa_dbus_connection_ref(pconn); - if (!(conn = pa_dbus_wrap_connection_new(c->mainloop, type, error))) + if (!(conn = pa_dbus_wrap_connection_new(c->mainloop, TRUE, type, error))) return NULL; return dbus_connection_new(c, conn, prop_name[type]); diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c index ece36def..4e6148f0 100644 --- a/src/pulsecore/dbus-util.c +++ b/src/pulsecore/dbus-util.c @@ -26,9 +26,11 @@ #include <stdarg.h> -#include <pulse/xmalloc.h> +#include <pulse/rtclock.h> #include <pulse/timeval.h> +#include <pulse/xmalloc.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/core-util.h> #include <pulsecore/log.h> @@ -38,6 +40,12 @@ struct pa_dbus_wrap_connection { pa_mainloop_api *mainloop; DBusConnection *connection; pa_defer_event* dispatch_event; + pa_bool_t use_rtclock:1; +}; + +struct timeout_data { + pa_dbus_wrap_connection *c; + DBusTimeout *timeout; }; static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) { @@ -118,16 +126,18 @@ static void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_e } /* pa_time_event_cb_t timer event handler */ -static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *tv, void *userdata) { - DBusTimeout *timeout = userdata; +static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *t, void *userdata) { + struct timeval tv; + struct timeout_data *d = userdata; - if (dbus_timeout_get_enabled(timeout)) { - struct timeval next = *tv; - dbus_timeout_handle(timeout); + pa_assert(d); + pa_assert(d->c); + + if (dbus_timeout_get_enabled(d->timeout)) { + dbus_timeout_handle(d->timeout); /* restart it for the next scheduled time */ - pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - ea->time_restart(e, &next); + ea->time_restart(e, pa_timeval_rtstore(&tv, pa_timeval_load(t) + dbus_timeout_get_interval(d->timeout) * PA_USEC_PER_MSEC, d->c->use_rtclock)); } } @@ -179,11 +189,16 @@ static void toggle_watch(DBusWatch *watch, void *data) { c->mainloop->io_enable(ev, get_watch_flags(watch)); } +static void time_event_destroy_cb(pa_mainloop_api *a, pa_time_event *e, void *userdata) { + pa_xfree(userdata); +} + /* DBusAddTimeoutFunction callback for pa mainloop */ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { pa_dbus_wrap_connection *c = data; pa_time_event *ev; struct timeval tv; + struct timeout_data *d; pa_assert(timeout); pa_assert(c); @@ -191,10 +206,11 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { if (!dbus_timeout_get_enabled(timeout)) return FALSE; - pa_gettimeofday(&tv); - pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - - ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout); + d = pa_xnew(struct timeout_data, 1); + d->c = c; + d->timeout = timeout; + ev = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + dbus_timeout_get_interval(timeout) * PA_USEC_PER_MSEC, c->use_rtclock), handle_time_event, d); + c->mainloop->time_set_destroy(ev, time_event_destroy_cb); dbus_timeout_set_data(timeout, ev, NULL); @@ -215,23 +231,20 @@ static void remove_timeout(DBusTimeout *timeout, void *data) { /* DBusTimeoutToggledFunction callback for pa mainloop */ static void toggle_timeout(DBusTimeout *timeout, void *data) { - pa_dbus_wrap_connection *c = data; + struct timeout_data *d = data; pa_time_event *ev; + struct timeval tv; + pa_assert(d); + pa_assert(d->c); pa_assert(timeout); - pa_assert(c); pa_assert_se(ev = dbus_timeout_get_data(timeout)); if (dbus_timeout_get_enabled(timeout)) { - struct timeval tv; - - pa_gettimeofday(&tv); - pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - - c->mainloop->time_restart(ev, &tv); + d->c->mainloop->time_restart(ev, pa_timeval_rtstore(&tv, pa_rtclock_now() + dbus_timeout_get_interval(timeout) * PA_USEC_PER_MSEC, d->c->use_rtclock)); } else - c->mainloop->time_restart(ev, NULL); + d->c->mainloop->time_restart(ev, pa_timeval_rtstore(&tv, PA_USEC_INVALID, d->c->use_rtclock)); } static void wakeup_main(void *userdata) { @@ -244,7 +257,7 @@ static void wakeup_main(void *userdata) { c->mainloop->defer_enable(c->dispatch_event, 1); } -pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBusType type, DBusError *error) { +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, pa_bool_t use_rtclock, DBusBusType type, DBusError *error) { DBusConnection *conn; pa_dbus_wrap_connection *pconn; char *id; @@ -257,6 +270,7 @@ pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBus pconn = pa_xnew(pa_dbus_wrap_connection, 1); pconn->mainloop = m; pconn->connection = conn; + pconn->use_rtclock = use_rtclock; dbus_connection_set_exit_on_disconnect(conn, FALSE); dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); diff --git a/src/pulsecore/dbus-util.h b/src/pulsecore/dbus-util.h index 55cda7a0..9ff298d8 100644 --- a/src/pulsecore/dbus-util.h +++ b/src/pulsecore/dbus-util.h @@ -30,7 +30,7 @@ /* A wrap connection is not shared or refcounted, it is available in client side */ typedef struct pa_dbus_wrap_connection pa_dbus_wrap_connection; -pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, DBusBusType type, DBusError *error); +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, pa_bool_t use_rtclock, DBusBusType type, DBusError *error); void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* conn); DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *conn); diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 15d192d6..8c21ee6c 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -38,6 +38,7 @@ #include <syslog.h> #endif +#include <pulse/rtclock.h> #include <pulse/utf8.h> #include <pulse/xmalloc.h> #include <pulse/util.h> @@ -45,7 +46,7 @@ #include <pulsecore/macro.h> #include <pulsecore/core-util.h> -#include <pulsecore/rtclock.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/once.h> #include <pulsecore/ratelimit.h> @@ -294,7 +295,7 @@ void pa_log_levelv_meta( static pa_usec_t start, last; pa_usec_t u, a, r; - u = pa_rtclock_usec(); + u = pa_rtclock_now(); PA_ONCE_BEGIN { start = u; diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 9a57895b..2c3f98a5 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -257,7 +257,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * (size_t) idx)); if (!slot) { - pa_log_info("Pool full"); + pa_log_debug("Pool full"); pa_atomic_inc(&p->stat.n_pool_full); return NULL; } @@ -509,13 +509,16 @@ static void memblock_free(pa_memblock *b) { /* FIXME! This should be implemented lock-free */ - segment = b->per_type.imported.segment; - pa_assert(segment); - import = segment->import; - pa_assert(import); + pa_assert_se(segment = b->per_type.imported.segment); + pa_assert_se(import = segment->import); pa_mutex_lock(import->mutex); - pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); + + pa_hashmap_remove( + import->blocks, + PA_UINT32_TO_PTR(b->per_type.imported.id)); + + pa_assert(segment->n_blocks >= 1); if (-- segment->n_blocks <= 0) segment_detach(segment); @@ -525,6 +528,7 @@ static void memblock_free(pa_memblock *b) { if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) pa_xfree(b); + break; } @@ -657,7 +661,8 @@ pa_memblock *pa_memblock_will_need(pa_memblock *b) { /* Self-locked. This function is not multiple-caller safe */ static void memblock_replace_import(pa_memblock *b) { - pa_memimport_segment *seg; + pa_memimport_segment *segment; + pa_memimport *import; pa_assert(b); pa_assert(b->type == PA_MEMBLOCK_IMPORTED); @@ -667,23 +672,22 @@ static void memblock_replace_import(pa_memblock *b) { pa_atomic_dec(&b->pool->stat.n_imported); pa_atomic_sub(&b->pool->stat.imported_size, (int) b->length); - seg = b->per_type.imported.segment; - pa_assert(seg); - pa_assert(seg->import); + pa_assert_se(segment = b->per_type.imported.segment); + pa_assert_se(import = segment->import); - pa_mutex_lock(seg->import->mutex); + pa_mutex_lock(import->mutex); pa_hashmap_remove( - seg->import->blocks, + import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); memblock_make_local(b); - if (-- seg->n_blocks <= 0) { - pa_mutex_unlock(seg->import->mutex); - segment_detach(seg); - } else - pa_mutex_unlock(seg->import->mutex); + pa_assert(segment->n_blocks >= 1); + if (-- segment->n_blocks <= 0) + segment_detach(segment); + + pa_mutex_unlock(import->mutex); } pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) { diff --git a/src/pulsecore/memtrap.c b/src/pulsecore/memtrap.c index e06f60ca..c647e507 100644 --- a/src/pulsecore/memtrap.c +++ b/src/pulsecore/memtrap.c @@ -37,6 +37,7 @@ #include <pulsecore/aupdate.h> #include <pulsecore/atomic.h> #include <pulsecore/once.h> +#include <pulsecore/mutex.h> #include "memtrap.h" @@ -49,6 +50,7 @@ struct pa_memtrap { static pa_memtrap *memtraps[2] = { NULL, NULL }; static pa_aupdate *aupdate; +static pa_static_mutex mutex = PA_STATIC_MUTEX_INIT; /* only required to serialize access to the write side */ static void allocate_aupdate(void) { PA_ONCE_BEGIN { @@ -63,7 +65,7 @@ pa_bool_t pa_memtrap_is_good(pa_memtrap *m) { } static void sigsafe_error(const char *s) { - write(STDERR_FILENO, s, strlen(s)); + (void) write(STDERR_FILENO, s, strlen(s)); } static void signal_handler(int sig, siginfo_t* si, void *data) { @@ -124,6 +126,7 @@ static void memtrap_unlink(pa_memtrap *m, unsigned j) { pa_memtrap* pa_memtrap_add(const void *start, size_t size) { pa_memtrap *m = NULL; unsigned j; + pa_mutex *mx; pa_assert(start); pa_assert(size > 0); @@ -138,33 +141,45 @@ pa_memtrap* pa_memtrap_add(const void *start, size_t size) { allocate_aupdate(); + mx = pa_static_mutex_get(&mutex, FALSE, TRUE); + pa_mutex_lock(mx); + j = pa_aupdate_write_begin(aupdate); memtrap_link(m, j); j = pa_aupdate_write_swap(aupdate); memtrap_link(m, j); pa_aupdate_write_end(aupdate); + pa_mutex_unlock(mx); + return m; } void pa_memtrap_remove(pa_memtrap *m) { unsigned j; + pa_mutex *mx; pa_assert(m); allocate_aupdate(); + mx = pa_static_mutex_get(&mutex, FALSE, TRUE); + pa_mutex_lock(mx); + j = pa_aupdate_write_begin(aupdate); memtrap_unlink(m, j); j = pa_aupdate_write_swap(aupdate); memtrap_unlink(m, j); pa_aupdate_write_end(aupdate); + pa_mutex_unlock(mx); + pa_xfree(m); } pa_memtrap *pa_memtrap_update(pa_memtrap *m, const void *start, size_t size) { unsigned j; + pa_mutex *mx; pa_assert(m); @@ -176,6 +191,9 @@ pa_memtrap *pa_memtrap_update(pa_memtrap *m, const void *start, size_t size) { allocate_aupdate(); + mx = pa_static_mutex_get(&mutex, FALSE, TRUE); + pa_mutex_lock(mx); + j = pa_aupdate_write_begin(aupdate); if (m->start == start && m->size == size) @@ -194,6 +212,8 @@ pa_memtrap *pa_memtrap_update(pa_memtrap *m, const void *start, size_t size) { unlock: pa_aupdate_write_end(aupdate); + pa_mutex_unlock(mx); + return m; } diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 4388831a..fc8ce76f 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -27,6 +27,7 @@ #include <stdio.h> #include <stdlib.h> +#include <pulse/rtclock.h> #include <pulse/timeval.h> #include <pulse/xmalloc.h> @@ -37,6 +38,7 @@ #include <pulsecore/macro.h> #include <pulsecore/refcnt.h> #include <pulsecore/flist.h> +#include <pulsecore/core-rtclock.h> #include "pdispatch.h" @@ -204,6 +206,7 @@ struct pa_pdispatch { pa_pdispatch_drain_callback drain_callback; void *drain_userdata; const pa_creds *creds; + pa_bool_t use_rtclock:1; }; static void reply_info_free(struct reply_info *r) { @@ -220,7 +223,7 @@ static void reply_info_free(struct reply_info *r) { pa_xfree(r); } -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_t*table, unsigned entries) { +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, pa_bool_t use_rtclock, const pa_pdispatch_cb_t *table, unsigned entries) { pa_pdispatch *pd; pa_assert(mainloop); @@ -235,6 +238,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ pd->drain_callback = NULL; pd->drain_userdata = NULL; pd->creds = NULL; + pd->use_rtclock = use_rtclock; return pd; } @@ -342,7 +346,7 @@ finish: return ret; } -static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, const struct timeval *t, void *userdata) { struct reply_info*r = userdata; pa_assert(r); @@ -371,10 +375,7 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa r->free_cb = free_cb; r->tag = tag; - pa_gettimeofday(&tv); - tv.tv_sec += timeout; - - pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r)); + pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + timeout * PA_USEC_PER_SEC, pd->use_rtclock), timeout_callback, r)); PA_LLIST_PREPEND(struct reply_info, pd->replies, r); } diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 5c31d80e..dae475af 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -37,7 +37,7 @@ typedef struct pa_pdispatch pa_pdispatch; typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); typedef void (*pa_pdispatch_drain_callback)(pa_pdispatch *pd, void *userdata); -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table, unsigned entries); +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, pa_bool_t use_rtclock, const pa_pdispatch_cb_t*table, unsigned entries); void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index ad7cd045..f64552aa 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include <limits.h> +#include <pulse/rtclock.h> #include <pulse/sample.h> #include <pulse/timeval.h> #include <pulse/utf8.h> @@ -63,7 +64,7 @@ #define MAX_CONNECTIONS 64 /* Kick a client if it doesn't authenticate within this time */ -#define AUTH_TIMEOUT 5 +#define AUTH_TIMEOUT (5*PA_USEC_PER_SEC) #define DEFAULT_COOKIE_FILE ".esd_auth" @@ -1459,11 +1460,10 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { /*** entry points ***/ -static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auth_timeout(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { connection *c = CONNECTION(userdata); pa_assert(m); - pa_assert(tv); connection_assert_ref(c); pa_assert(c->auth_timeout_event == e); @@ -1553,12 +1553,9 @@ void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esou c->authorized = TRUE; } - if (!c->authorized) { - struct timeval tv; - pa_gettimeofday(&tv); - tv.tv_sec += AUTH_TIMEOUT; - c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); - } else + if (!c->authorized) + c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c); + else c->auth_timeout_event = NULL; c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 48f7b135..9a37c565 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -29,6 +29,7 @@ #include <stdlib.h> #include <unistd.h> +#include <pulse/rtclock.h> #include <pulse/timeval.h> #include <pulse/version.h> #include <pulse/utf8.h> @@ -61,7 +62,7 @@ #include "protocol-native.h" /* Kick a client if it doesn't authenticate within this time */ -#define AUTH_TIMEOUT 60 +#define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC) /* Don't accept more connection than this */ #define MAX_CONNECTIONS 64 @@ -2549,7 +2550,7 @@ static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uin reply = reply_new(tag); pa_tagstruct_put_usec(reply, s->current_sink_latency + - pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sample_spec)); + pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec)); pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, s->playing_for > 0 && @@ -2688,7 +2689,9 @@ static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uin CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY); - if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0) + if (!s->memchunk.memblock) + pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE); + else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0) pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL); else pa_pstream_send_simple_ack(c->pstream, tag); @@ -4479,11 +4482,10 @@ static void client_send_event_cb(pa_client *client, const char*event, pa_proplis /*** module entry points ***/ -static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_assert(m); - pa_assert(tv); pa_native_connection_assert_ref(c); pa_assert(c->auth_timeout_event == e); @@ -4541,12 +4543,9 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati c->authorized = TRUE; } - if (!c->authorized) { - struct timeval tv; - pa_gettimeofday(&tv); - tv.tv_sec += AUTH_TIMEOUT; - c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); - } else + if (!c->authorized) + c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c); + else c->auth_timeout_event = NULL; c->is_local = pa_iochannel_socket_is_local(io); @@ -4565,7 +4564,7 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c); pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c); - c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); + c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX); c->record_streams = pa_idxset_new(NULL, NULL); c->output_streams = pa_idxset_new(NULL, NULL); diff --git a/src/pulsecore/ratelimit.c b/src/pulsecore/ratelimit.c index e913ca19..844dd77d 100644 --- a/src/pulsecore/ratelimit.c +++ b/src/pulsecore/ratelimit.c @@ -23,7 +23,8 @@ #include <config.h> #endif -#include <pulsecore/rtclock.h> +#include <pulse/rtclock.h> + #include <pulsecore/log.h> #include <pulsecore/mutex.h> @@ -38,7 +39,7 @@ pa_bool_t pa_ratelimit_test(pa_ratelimit *r) { pa_usec_t now; pa_mutex *m; - now = pa_rtclock_usec(); + now = pa_rtclock_now(); m = pa_static_mutex_get(&mutex, FALSE, FALSE); pa_mutex_lock(m); diff --git a/src/pulsecore/rtkit.c b/src/pulsecore/rtkit.c new file mode 100644 index 00000000..aecc4e32 --- /dev/null +++ b/src/pulsecore/rtkit.c @@ -0,0 +1,189 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +/*** + Copyright 2009 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include <errno.h> + +#include "rtkit.h" + +#ifdef __linux__ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/syscall.h> + +static pid_t _gettid(void) { + return (pid_t) syscall(SYS_gettid); +} + +static int translate_error(const char *name) { + if (strcmp(name, DBUS_ERROR_NO_MEMORY) == 0) + return -ENOMEM; + if (strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 || + strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0) + return -ENOENT; + if (strcmp(name, DBUS_ERROR_ACCESS_DENIED) == 0 || + strcmp(name, DBUS_ERROR_AUTH_FAILED) == 0) + return -EACCES; + + return -EIO; +} + +int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) { + DBusMessage *m = NULL, *r = NULL; + dbus_uint64_t u64; + dbus_uint32_t u32; + DBusError error; + int ret; + + dbus_error_init(&error); + + if (thread == 0) + thread = _gettid(); + + if (!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.RealtimeKit1", + "MakeThreadRealtime"))) { + ret = -ENOMEM; + goto finish; + } + + u64 = (dbus_uint64_t) thread; + u32 = (dbus_uint32_t) priority; + + if (!dbus_message_append_args( + m, + DBUS_TYPE_UINT64, &u64, + DBUS_TYPE_UINT32, &u32, + DBUS_TYPE_INVALID)) { + ret = -ENOMEM; + goto finish; + } + + if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { + ret = translate_error(error.name); + goto finish; + } + + + if (dbus_set_error_from_message(&error, r)) { + ret = translate_error(error.name); + goto finish; + } + + ret = 0; + +finish: + + if (m) + dbus_message_unref(m); + + if (r) + dbus_message_unref(r); + + dbus_error_free(&error); + + return ret; +} + +int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) { + DBusMessage *m = NULL, *r = NULL; + dbus_uint64_t u64; + dbus_int32_t s32; + DBusError error; + int ret; + + dbus_error_init(&error); + + if (thread == 0) + thread = _gettid(); + + if (!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.RealtimeKit1", + "MakeThreadHighPriority"))) { + ret = -ENOMEM; + goto finish; + } + + u64 = (dbus_uint64_t) thread; + s32 = (dbus_int32_t) nice_level; + + if (!dbus_message_append_args( + m, + DBUS_TYPE_UINT64, &u64, + DBUS_TYPE_INT32, &s32, + DBUS_TYPE_INVALID)) { + ret = -ENOMEM; + goto finish; + } + + + + if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { + ret = translate_error(error.name); + goto finish; + } + + + if (dbus_set_error_from_message(&error, r)) { + ret = translate_error(error.name); + goto finish; + } + + ret = 0; + +finish: + + if (m) + dbus_message_unref(m); + + if (r) + dbus_message_unref(r); + + dbus_error_free(&error); + + return ret; +} + +#else + +int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) { + return -ENOTSUP; +} + +int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) { + return -ENOTSUP; +} + +#endif diff --git a/src/pulsecore/rtkit.h b/src/pulsecore/rtkit.h new file mode 100644 index 00000000..2081b4e9 --- /dev/null +++ b/src/pulsecore/rtkit.h @@ -0,0 +1,62 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +#ifndef foortkithfoo +#define foortkithfoo + +/*** + Copyright 2009 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include <sys/types.h> +#include <dbus/dbus.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the reference implementation for a client for + * RealtimeKit. You don't have to use this, but if do, just copy these + * sources into your repository */ + +#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" +#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" + +/* This is mostly equivalent to sched_setparam(thread, SCHED_RR, { + * .sched_priority = priority }). 'thread' needs to be a kernel thread + * id as returned by gettid(), not a pthread_t! If 'thread' is 0 the + * current thread is used. The returned value is a negative errno + * style error code, or 0 on success. */ +int rtkit_make_realtime(DBusConnection *system_bus, pid_t thread, int priority); + +/* This is mostly equivalent to setpriority(PRIO_PROCESS, thread, + * nice_level). 'thread' needs to be a kernel thread id as returned by + * gettid(), not a pthread_t! If 'thread' is 0 the current thread is + * used. The returned value is a negative errno style error code, or 0 + * on success.*/ +int rtkit_make_high_priority(DBusConnection *system_bus, pid_t thread, int nice_level); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c index aa8ca321..42708a8a 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -30,10 +30,6 @@ #include <string.h> #include <errno.h> -#ifdef __linux__ -#include <sys/utsname.h> -#endif - #ifdef HAVE_POLL_H #include <poll.h> #else @@ -44,10 +40,9 @@ #include <pulse/timeval.h> #include <pulsecore/core-error.h> -#include <pulsecore/rtclock.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/macro.h> #include <pulsecore/llist.h> -#include <pulsecore/rtsig.h> #include <pulsecore/flist.h> #include <pulsecore/core-util.h> #include <pulsecore/winsock.h> @@ -66,20 +61,9 @@ struct pa_rtpoll { pa_bool_t scan_for_dead:1; pa_bool_t running:1; - pa_bool_t installed:1; pa_bool_t rebuild_needed:1; pa_bool_t quit:1; -#ifdef HAVE_PPOLL - 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 - #ifdef DEBUG_TIMING pa_usec_t timestamp; pa_usec_t slept, awake; @@ -107,52 +91,20 @@ struct pa_rtpoll_item { PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree); -static void signal_handler_noop(int s) { /* write(2, "signal\n", 7); */ } - pa_rtpoll *pa_rtpoll_new(void) { pa_rtpoll *p; p = pa_xnew(pa_rtpoll, 1); -#ifdef HAVE_PPOLL - -#ifdef __linux__ - /* ppoll is broken on Linux < 2.6.16 */ - p->dont_use_ppoll = FALSE; - - { - 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 - - p->rtsig = -1; - sigemptyset(&p->sigset_unblocked); - p->timer = (timer_t) -1; - p->timer_armed = FALSE; - -#endif - p->n_pollfd_alloc = 32; p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc); p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc); p->n_pollfd_used = 0; - memset(&p->next_elapse, 0, sizeof(p->next_elapse)); + pa_zero(p->next_elapse); p->timer_enabled = FALSE; p->running = FALSE; - p->installed = FALSE; p->scan_for_dead = FALSE; p->rebuild_needed = FALSE; p->quit = FALSE; @@ -160,53 +112,13 @@ pa_rtpoll *pa_rtpoll_new(void) { PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items); #ifdef DEBUG_TIMING - p->timestamp = pa_rtclock_usec(); + p->timestamp = pa_rtclock_now(); p->slept = p->awake = 0; #endif return p; } -void pa_rtpoll_install(pa_rtpoll *p) { - pa_assert(p); - pa_assert(!p->installed); - - p->installed = TRUE; - -#ifdef HAVE_PPOLL -# ifdef __linux__ - if (p->dont_use_ppoll) - return; -# endif - - if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) { - pa_log_warn("Failed to reserve POSIX realtime signal."); - return; - } - - pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig)); - - { - sigset_t ss; - struct sigaction sa; - - pa_assert_se(sigemptyset(&ss) == 0); - pa_assert_se(sigaddset(&ss, p->rtsig) == 0); - pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0); - pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0); - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = signal_handler_noop; - pa_assert_se(sigemptyset(&sa.sa_mask) == 0); - - pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0); - - /* We never reset the signal handler. Why should we? */ - } - -#endif -} - static void rtpoll_rebuild(pa_rtpoll *p) { struct pollfd *e, *t; @@ -250,7 +162,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) { @@ -279,11 +190,6 @@ void pa_rtpoll_free(pa_rtpoll *p) { pa_xfree(p->pollfd); pa_xfree(p->pollfd2); -#ifdef HAVE_PPOLL - if (p->timer != (timer_t) -1) - timer_delete(p->timer); -#endif - pa_xfree(p); } @@ -314,14 +220,13 @@ static void reset_all_revents(pa_rtpoll *p) { } } -int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { +int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait_op) { pa_rtpoll_item *i; int r = 0; struct timeval timeout; pa_assert(p); pa_assert(!p->running); - pa_assert(p->installed); p->running = TRUE; @@ -384,7 +289,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { memset(&timeout, 0, sizeof(timeout)); /* Calculate timeout */ - if (wait && !p->quit && p->timer_enabled) { + if (wait_op && !p->quit && p->timer_enabled) { struct timeval now; pa_rtclock_get(&now); @@ -394,7 +299,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { #ifdef DEBUG_TIMING { - pa_usec_t now = pa_rtclock_usec(); + pa_usec_t now = pa_rtclock_now(); p->awake = now - p->timestamp; p->timestamp = now; } @@ -402,26 +307,19 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { /* OK, now let's sleep */ #ifdef HAVE_PPOLL - -#ifdef __linux__ - if (!p->dont_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); + r = ppoll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? &ts : NULL, NULL); } -#ifdef __linux__ - else -#endif - +#else + r = poll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1); #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); #ifdef DEBUG_TIMING { - pa_usec_t now = pa_rtclock_usec(); + pa_usec_t now = pa_rtclock_now(); p->slept = now - p->timestamp; p->timestamp = now; @@ -472,73 +370,11 @@ finish: return r < 0 ? r : !p->quit; } -static void update_timer(pa_rtpoll *p) { - pa_assert(p); - -#ifdef HAVE_PPOLL - -#ifdef __linux__ - if (p->dont_use_ppoll) - return; -#endif - - if (p->timer == (timer_t) -1) { - struct sigevent se; - - memset(&se, 0, sizeof(se)); - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = p->rtsig; - - if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0) - if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) { - pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno)); - p->timer = (timer_t) -1; - } - } - - if (p->timer != (timer_t) -1) { - struct itimerspec its; - struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; - sigset_t ss; - - if (p->timer_armed) { - /* First disarm timer */ - memset(&its, 0, sizeof(its)); - pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0); - - /* Remove a signal that might be waiting in the signal q */ - pa_assert_se(sigemptyset(&ss) == 0); - pa_assert_se(sigaddset(&ss, p->rtsig) == 0); - sigtimedwait(&ss, NULL, &ts); - } - - /* And install the new timer */ - if (p->timer_enabled) { - 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; - - /* 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); - } - - p->timer_armed = p->timer_enabled; - } - -#endif -} - void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) { pa_assert(p); pa_timeval_store(&p->next_elapse, usec); p->timer_enabled = TRUE; - - update_timer(p); } void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) { @@ -550,8 +386,6 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) { pa_rtclock_get(&p->next_elapse); pa_timeval_add(&p->next_elapse, usec); p->timer_enabled = TRUE; - - update_timer(p); } void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) { @@ -559,8 +393,6 @@ void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) { memset(&p->next_elapse, 0, sizeof(p->next_elapse)); p->timer_enabled = FALSE; - - update_timer(p); } pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) { diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h index 08776ef0..d2d69cad 100644 --- a/src/pulsecore/rtpoll.h +++ b/src/pulsecore/rtpoll.h @@ -62,9 +62,6 @@ typedef enum pa_rtpoll_priority { pa_rtpoll *pa_rtpoll_new(void); void pa_rtpoll_free(pa_rtpoll *p); -/* Install the rtpoll in the current thread */ -void pa_rtpoll_install(pa_rtpoll *p); - /* Sleep on the rtpoll until the time event, or any of the fd events * is triggered. If "wait" is 0 we don't sleep but only update the * struct pollfd. Returns negative on error, positive if the loop diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c deleted file mode 100644 index 4cd6aa8f..00000000 --- a/src/pulsecore/rtsig.c +++ /dev/null @@ -1,131 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB - - 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 <signal.h> - -#include <pulsecore/macro.h> -#include <pulsecore/flist.h> -#include <pulsecore/once.h> -#include <pulsecore/thread.h> -#include <pulsecore/core-util.h> - -#include "rtsig.h" - -#ifdef SIGRTMIN - -static void _free_rtsig(void *p) { - pa_rtsig_put(PA_PTR_TO_INT(p)); -} - -PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two((unsigned) (SIGRTMAX-SIGRTMIN+1)), NULL); -PA_STATIC_TLS_DECLARE(rtsig_tls, _free_rtsig); - -static pa_atomic_t rtsig_current = PA_ATOMIC_INIT(-1); - -static int rtsig_start = -1, rtsig_end = -1; - -int pa_rtsig_get(void) { - void *p; - int sig; - - if ((p = pa_flist_pop(PA_STATIC_FLIST_GET(rtsig_flist)))) - return PA_PTR_TO_INT(p); - - sig = pa_atomic_dec(&rtsig_current); - - pa_assert(sig <= SIGRTMAX); - pa_assert(sig <= rtsig_end); - - if (sig < rtsig_start) { - pa_atomic_inc(&rtsig_current); - return -1; - } - - return sig; -} - -int pa_rtsig_get_for_thread(void) { - int sig; - void *p; - - if ((p = PA_STATIC_TLS_GET(rtsig_tls))) - return PA_PTR_TO_INT(p); - - if ((sig = pa_rtsig_get()) < 0) - return -1; - - PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig)); - return sig; -} - -void pa_rtsig_put(int sig) { - pa_assert(sig >= rtsig_start); - pa_assert(sig <= rtsig_end); - - pa_assert_se(pa_flist_push(PA_STATIC_FLIST_GET(rtsig_flist), PA_INT_TO_PTR(sig)) >= 0); -} - -void pa_rtsig_configure(int start, int end) { - int s; - sigset_t ss; - - pa_assert(pa_atomic_load(&rtsig_current) == -1); - - pa_assert(SIGRTMIN <= start); - pa_assert(start <= end); - pa_assert(end <= SIGRTMAX); - - rtsig_start = start; - rtsig_end = end; - - sigemptyset(&ss); - - for (s = rtsig_start; s <= rtsig_end; s++) - pa_assert_se(sigaddset(&ss, s) == 0); - - pa_assert(pthread_sigmask(SIG_BLOCK, &ss, NULL) == 0); - - /* We allocate starting from the end */ - pa_atomic_store(&rtsig_current, rtsig_end); -} - -#else /* SIGRTMIN */ - -int pa_rtsig_get(void) { - return -1; -} - -int pa_rtsig_get_for_thread(void) { - return -1; -} - -void pa_rtsig_put(int sig) { -} - -void pa_rtsig_configure(int start, int end) { -} - -#endif /* SIGRTMIN */ diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h deleted file mode 100644 index e414122d..00000000 --- a/src/pulsecore/rtsig.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef foopulsertsighfoo -#define foopulsertsighfoo - -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 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. -***/ - -/* Return the next unused POSIX Realtime signals */ -int pa_rtsig_get(void); - -/* If not called before in the current thread, return the next unused - * rtsig, and install it in a TLS region and give it up automatically - * when the thread shuts down */ -int pa_rtsig_get_for_thread(void); - -/* Give an rtsig back. */ -void pa_rtsig_put(int sig); - -/* Block all RT signals */ -void pa_rtsig_configure(int start, int end); - -#endif diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index fab2b3b6..6e428426 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -39,6 +39,11 @@ #include <sys/mman.h> #endif +/* This is deprecated on glibc but is still used by FreeBSD */ +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +#endif + #include <pulse/xmalloc.h> #include <pulse/gccmacro.h> diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 47792293..d8f3c7d1 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -181,6 +181,7 @@ pa_sink* pa_sink_new( s = pa_msgobject_new(pa_sink); if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) { + pa_log_debug("Failed to register name %s.", data->name); pa_xfree(s); return NULL; } @@ -2383,30 +2384,35 @@ pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) { } pa_bool_t pa_device_init_description(pa_proplist *p) { - const char *s; + const char *s, *d = NULL, *k; pa_assert(p); if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION)) return TRUE; if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) - if (pa_streq(s, "internal")) { - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio")); - return TRUE; - } + if (pa_streq(s, "internal")) + d = _("Internal Audio"); - if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) - if (pa_streq(s, "modem")) { - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Modem")); - return TRUE; - } + if (!d) + if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) + if (pa_streq(s, "modem")) + d = _("Modem"); - if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) { - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); - return TRUE; - } + if (!d) + d = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME); - return FALSE; + if (!d) + return FALSE; + + k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION); + + if (d && k) + pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k); + else if (d) + pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d); + + return TRUE; } pa_bool_t pa_device_init_intended_roles(pa_proplist *p) { diff --git a/src/pulsecore/sndfile-util.c b/src/pulsecore/sndfile-util.c index 032aefca..4f7f8bdb 100644 --- a/src/pulsecore/sndfile-util.c +++ b/src/pulsecore/sndfile-util.c @@ -113,7 +113,7 @@ int pa_sndfile_write_sample_spec(SF_INFO *sfi, pa_sample_spec *ss) { break; case PA_SAMPLE_S32LE: - case PA_SAMPLE_S32RE: + case PA_SAMPLE_S32BE: ss->format = PA_SAMPLE_S32NE; sfi->format |= SF_FORMAT_PCM_32; break; diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index dc23bff6..24535157 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -52,12 +52,14 @@ #include <asyncns.h> #endif +#include <pulse/rtclock.h> #include <pulse/timeval.h> #include <pulse/xmalloc.h> #include <pulsecore/winsock.h> #include <pulsecore/core-error.h> #include <pulsecore/socket-util.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/core-util.h> #include <pulsecore/socket-util.h> #include <pulsecore/log.h> @@ -420,12 +422,11 @@ fail: #endif -static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_socket_client *c = userdata; pa_assert(m); pa_assert(e); - pa_assert(tv); pa_assert(c); if (c->fd >= 0) { @@ -437,17 +438,16 @@ static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeva do_call(c); } -static void start_timeout(pa_socket_client *c) { +static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) { struct timeval tv; + pa_assert(c); pa_assert(!c->timeout_event); - pa_gettimeofday(&tv); - pa_timeval_add(&tv, CONNECT_TIMEOUT * PA_USEC_PER_SEC); - c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); + c->timeout_event = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + CONNECT_TIMEOUT * PA_USEC_PER_SEC, use_rtclock), timeout_cb, c); } -pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*name, uint16_t default_port) { +pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char*name, uint16_t default_port) { pa_socket_client *c = NULL; pa_parsed_address a; @@ -463,7 +463,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam switch (a.type) { case PA_PARSED_ADDRESS_UNIX: if ((c = pa_socket_client_new_unix(m, a.path_or_host))) - start_timeout(c); + start_timeout(c, use_rtclock); break; case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ @@ -499,7 +499,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c); c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints); pa_assert(c->asyncns_query); - start_timeout(c); + start_timeout(c, use_rtclock); } #elif defined(HAVE_GETADDRINFO) { @@ -513,7 +513,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam if (res->ai_addr) { if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) - start_timeout(c); + start_timeout(c, use_rtclock); } freeaddrinfo(res); @@ -546,7 +546,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam s.sin_port = htons(a.port); if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s)))) - start_timeout(c); + start_timeout(c, use_rtclock); } #endif /* HAVE_LIBASYNCNS */ } diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h index ed36400c..b896afa9 100644 --- a/src/pulsecore/socket-client.h +++ b/src/pulsecore/socket-client.h @@ -40,7 +40,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[ #endif pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename); pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); -pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char *a, uint16_t default_port); +pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char *a, uint16_t default_port); pa_socket_client* pa_socket_client_ref(pa_socket_client *c); void pa_socket_client_unref(pa_socket_client *c); diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 1e431160..74f38bc5 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -149,6 +149,7 @@ pa_source* pa_source_new( s = pa_msgobject_new(pa_source); if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) { + pa_log_debug("Failed to register name %s.", data->name); pa_xfree(s); return NULL; } |