summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/core-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore/core-util.c')
-rw-r--r--src/pulsecore/core-util.c96
1 files changed, 78 insertions, 18 deletions
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 <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 +96,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,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;