core: ask RealtimeKit for RT scheduling

This commit is contained in:
Lennart Poettering 2009-06-19 04:19:08 +02:00
parent 6ad3855639
commit 8474fd7c62
4 changed files with 337 additions and 20 deletions

View file

@ -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 ((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;
}
}
pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r));
return -1;
if (set_scheduler(rtprio) >= 0) {
pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
return 0;
}
pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority);
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("Failed to acquire real-time scheduling: %s", pa_cstrerror(r));
return -1;
#else
errno = ENOTSUP;