From c5dbf754b578d70d5bf01494fedad74c1829ac38 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:13:01 +0200 Subject: core-util: implement pa_xstrfreev() --- src/pulsecore/core-util.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/pulsecore/core-util.c') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index b747cd84..0b64edba 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2732,3 +2732,15 @@ void pa_disable_sigpipe(void) { } #endif } + +void pa_xfreev(void**a) { + void **p; + + if (!a) + return; + + for (p = a; *p; p++) + pa_xfree(*p); + + pa_xfree(a); +} -- cgit From 7fa05bea7e9980243cf58902b9d42e995d1a18bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:13:32 +0200 Subject: core-util: implement pa_split_spaces_strv() --- src/pulsecore/core-util.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/pulsecore/core-util.c') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 0b64edba..e39adb12 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2744,3 +2744,27 @@ void pa_xfreev(void**a) { pa_xfree(a); } + +char **pa_split_spaces_strv(const char *s) { + char **t, *e; + unsigned i = 0, n = 8; + const char *state = NULL; + + t = pa_xnew(char*, n); + while ((e = pa_split_spaces(s, &state))) { + t[i++] = e; + + if (i >= n) { + n *= 2; + t = pa_xrenew(char*, t, n); + } + } + + if (i <= 0) { + pa_xfree(t); + return NULL; + } + + t[i] = NULL; + return t; +} -- cgit From 0fa1ddf8380d6b86bd7e911ac6db7771dcb14dd6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:13:59 +0200 Subject: core-util: implement pa_maybe_prefix_path() --- src/pulsecore/core-util.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/pulsecore/core-util.c') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index e39adb12..a71ba0b0 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2768,3 +2768,12 @@ char **pa_split_spaces_strv(const char *s) { t[i] = NULL; return t; } + +char* pa_maybe_prefix_path(const char *path, const char *prefix) { + pa_assert(path); + + if (pa_is_path_absolute(path)) + return pa_xstrdup(path); + + return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path); +} -- cgit From 8474fd7c62712470465800ddccd6ea291d04151e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Jun 2009 04:19:08 +0200 Subject: core: ask RealtimeKit for RT scheduling --- src/pulsecore/core-util.c | 96 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 18 deletions(-) (limited to 'src/pulsecore/core-util.c') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index a71ba0b0..1fdd1890 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -50,6 +50,10 @@ #ifdef HAVE_SCHED_H #include + +#if defined(__linux__) && !defined(SCHED_RESET_ON_FORK) +#define SCHED_RESET_ON_FORK 0x40000000 +#endif #endif #ifdef HAVE_SYS_RESOURCE_H @@ -92,6 +96,10 @@ #include #endif +#ifdef HAVE_DBUS +#include "rtkit.h" +#endif + #include #include #include @@ -552,16 +560,68 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } +static int set_scheduler(int rtprio) { + struct sched_param sp; + int r; +#ifdef HAVE_DBUS + DBusError error; + DBusConnection *bus; + + dbus_error_init(&error); +#endif + + 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 ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) { + pa_log_debug("SCHED_RR worked."); + return 0; + } + +#ifdef HAVE_DBUS + /* Try to talk to RealtimeKit */ + + 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; + } + + r = rtkit_make_realtime(bus, 0, rtprio); + dbus_connection_unref(bus); + + if (r >= 0) { + pa_log_debug("RealtimeKit worked."); + return 0; + } + + errno = -r; +#else + errno = r; +#endif + + return -1; +} + /* 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 - struct sched_param sp; int r, policy; + struct sched_param sp; + int rtprio_try; - memset(&sp, 0, sizeof(sp)); + pa_zero(sp); policy = 0; if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { @@ -569,29 +629,29 @@ int pa_make_realtime(int rtprio) { return -1; } - if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) { - pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority); +#ifdef SCHED_RESET_ON_FORK + policy &= ~SCHED_RESET_ON_FORK; +#endif + + if ((policy == SCHED_FIFO || policy == SCHED_RR) && sp.sched_priority >= rtprio) { + pa_log_info("Thread already being scheduled with SCHED_FIFO/SCHED_RR with priority %i.", sp.sched_priority); return 0; } - sp.sched_priority = rtprio; - if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) { - - while (sp.sched_priority > 1) { - sp.sched_priority --; + if (set_scheduler(rtprio) >= 0) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio); + return 0; + } - 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; - } + for (rtprio_try = rtprio-1; rtprio_try >= 1; rtprio_try--) { + if (set_scheduler(rtprio_try)) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", rtprio_try, rtprio); + return 0; } - - pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r)); - return -1; } - pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority); - return 0; + pa_log_warn("Failed to acquire real-time scheduling: %s", pa_cstrerror(r)); + return -1; #else errno = ENOTSUP; -- cgit From bacc5ca6f48f280c781af508250a25bb2012327f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Jun 2009 04:45:19 +0200 Subject: core: use rtkit to acquire high-priority scheduling --- src/pulsecore/core-util.c | 150 ++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 104 deletions(-) (limited to 'src/pulsecore/core-util.c') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 1fdd1890..4550344f 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -617,40 +617,20 @@ static int set_scheduler(int rtprio) { int pa_make_realtime(int rtprio) { #ifdef _POSIX_PRIORITY_SCHEDULING - int r, policy; - struct sched_param sp; - int rtprio_try; - - pa_zero(sp); - policy = 0; - - if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { - pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r)); - return -1; - } - -#ifdef SCHED_RESET_ON_FORK - policy &= ~SCHED_RESET_ON_FORK; -#endif - - if ((policy == SCHED_FIFO || policy == SCHED_RR) && sp.sched_priority >= rtprio) { - pa_log_info("Thread already being scheduled with SCHED_FIFO/SCHED_RR with priority %i.", sp.sched_priority); - return 0; - } + int p; if (set_scheduler(rtprio) >= 0) { pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio); return 0; } - for (rtprio_try = rtprio-1; rtprio_try >= 1; rtprio_try--) { - if (set_scheduler(rtprio_try)) { - pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", rtprio_try, rtprio); + 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; } - } - pa_log_warn("Failed to acquire real-time scheduling: %s", pa_cstrerror(r)); + pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno)); return -1; #else @@ -659,80 +639,42 @@ int pa_make_realtime(int rtprio) { #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; - -#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO) - { - struct rlimit rl; +static int set_nice(int nice_level) { +#ifdef HAVE_DBUS + DBusError error; + DBusConnection *bus; + int r; - if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0) - if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY) - return TRUE; - } + dbus_error_init(&error); #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; - - if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0) - if (flag == CAP_SET) { - cap_free(cap); - return TRUE; - } - - cap_free(cap); - } + if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) { + pa_log_debug("setpriority() worked."); + return 0; } -#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; - -#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO) - { - struct rlimit rl; +#ifdef HAVE_DBUS + /* Try to talk to RealtimeKit */ - if (getrlimit(RLIMIT_NICE, &rl) >= 0) - if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY) - return TRUE; + 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; } -#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; - - 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 @@ -740,22 +682,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 @@ -763,9 +704,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 @@ -780,8 +722,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 -- cgit