Compare commits
3 Commits
master
...
rtkit-real
Author | SHA1 | Date | |
---|---|---|---|
3a02588fbf | |||
27d430d9cf | |||
b84ffa265c |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
/output/
|
||||
|
||||
__pycache__/
|
||||
|
||||
result
|
||||
|
@ -192,6 +192,7 @@ option('solaris_output', type: 'feature', description: 'Solaris /dev/audio suppo
|
||||
#
|
||||
|
||||
option('dbus', type: 'feature', description: 'D-Bus support')
|
||||
option('rtkit', type: 'feature', description: 'Use RealtimeKit for requesting realtime scheduling')
|
||||
option('expat', type: 'feature', description: 'Expat XML support')
|
||||
option('icu', type: 'feature', description: 'Use libicu for Unicode')
|
||||
option('iconv', type: 'feature', description: 'Use iconv() for character set conversion')
|
||||
|
80
shell.nix
Normal file
80
shell.nix
Normal file
@ -0,0 +1,80 @@
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
pkgs.mkShell {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
|
||||
# For documentation
|
||||
doxygen
|
||||
python3Packages.sphinx
|
||||
python3Packages.sphinx-rtd-theme
|
||||
];
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
glib
|
||||
systemd
|
||||
boost
|
||||
fmt
|
||||
|
||||
# Inputs
|
||||
curl
|
||||
libmms
|
||||
libnfs
|
||||
liburing
|
||||
samba
|
||||
|
||||
# Archive support
|
||||
bzip2
|
||||
zziplib
|
||||
|
||||
# Codecs
|
||||
audiofile
|
||||
faad2
|
||||
ffmpeg
|
||||
flac
|
||||
fluidsynth
|
||||
game-music-emu
|
||||
libmad
|
||||
libmikmod
|
||||
mpg123
|
||||
libopus
|
||||
libvorbis
|
||||
lame
|
||||
|
||||
# Filters
|
||||
libsamplerate
|
||||
soxr
|
||||
|
||||
# Outputs
|
||||
alsa-lib
|
||||
libjack2
|
||||
libpulseaudio
|
||||
libshout
|
||||
pipewire
|
||||
|
||||
# Misc
|
||||
icu
|
||||
sqlite
|
||||
avahi
|
||||
dbus
|
||||
pcre2
|
||||
libgcrypt
|
||||
expat
|
||||
|
||||
# Services
|
||||
# yajl # This is broken, maybe because of the fork used in nixpkgs?
|
||||
|
||||
# Client support
|
||||
libmpdclient
|
||||
|
||||
# Tag support
|
||||
libid3tag
|
||||
|
||||
# For tests
|
||||
gtest
|
||||
zip
|
||||
];
|
||||
|
||||
hardeningDisable = [ "fortify" ];
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
#include "lib/fmt/ExceptionFormatter.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "Log.hxx"
|
||||
#include <boost/stacktrace.hpp>
|
||||
|
||||
#ifdef HAVE_URING
|
||||
#include "util/ScopeExit.hxx"
|
||||
@ -54,7 +55,8 @@ EventThread::Run() noexcept
|
||||
} catch (...) {
|
||||
FmtInfo(event_domain,
|
||||
"RTIOThread could not get realtime scheduling, continuing anyway: {}",
|
||||
std::current_exception());
|
||||
/* std::current_exception()); */
|
||||
boost::stacktrace::to_string(boost::stacktrace::stacktrace()));
|
||||
}
|
||||
} else {
|
||||
#ifdef HAVE_URING
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <yajl_parse.h>
|
||||
#include <yajl/yajl_parse.h>
|
||||
|
||||
namespace Yajl {
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <yajl_gen.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <span>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <yajl_parse.h>
|
||||
#include <yajl/yajl_parse.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
@ -8,10 +8,207 @@
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include "lib/fmt/RuntimeError.hxx"
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
const char* RTKIT_SERVICE_NAME = "org.freedesktop.RealtimeKit1";
|
||||
const char* RTKIT_OBJECT_PATH = "/org/freedesktop/RealtimeKit1";
|
||||
|
||||
// static int
|
||||
// rtkit_get_max_realtime_priority(DBusConnection &connection)
|
||||
// {
|
||||
// // TODO: Implement this function
|
||||
// DBusError error;
|
||||
// }
|
||||
|
||||
// static void
|
||||
// rtkit_make_realtime(DBusConnection &connection, pid_t thread, int priority)
|
||||
// {
|
||||
// // TODO: Implement this function
|
||||
|
||||
// }
|
||||
#endif
|
||||
|
||||
// TODO: minimize and drop
|
||||
#ifdef __linux__
|
||||
|
||||
#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
|
||||
#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static long long rtkit_get_int_property(DBusConnection *connection, const char* propname, long long* propval) {
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
DBusMessageIter iter, subiter;
|
||||
dbus_int64_t i64;
|
||||
dbus_int32_t i32;
|
||||
DBusError error;
|
||||
int current_type;
|
||||
long long ret;
|
||||
const char * interfacestr = "org.freedesktop.RealtimeKit1";
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"Get"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_STRING, &interfacestr,
|
||||
DBUS_TYPE_STRING, &propname,
|
||||
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 = -EBADMSG;
|
||||
dbus_message_iter_init(r, &iter);
|
||||
while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_VARIANT) {
|
||||
dbus_message_iter_recurse(&iter, &subiter);
|
||||
|
||||
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_INT32) {
|
||||
dbus_message_iter_get_basic(&subiter, &i32);
|
||||
*propval = i32;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (current_type == DBUS_TYPE_INT64) {
|
||||
dbus_message_iter_get_basic(&subiter, &i64);
|
||||
*propval = i64;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dbus_message_iter_next (&subiter);
|
||||
}
|
||||
}
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtkit_get_max_realtime_priority(DBusConnection *connection) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#ifndef ANDROID
|
||||
@ -75,14 +272,50 @@ SetThreadRealtime()
|
||||
{
|
||||
#ifdef __linux__
|
||||
struct sched_param sched_param;
|
||||
sched_param.sched_priority = 40;
|
||||
sched_param.sched_priority = 20;
|
||||
|
||||
int policy = SCHED_FIFO;
|
||||
#ifdef SCHED_RESET_ON_FORK
|
||||
policy |= SCHED_RESET_ON_FORK;
|
||||
#endif
|
||||
|
||||
if (linux_sched_setscheduler(0, policy, &sched_param) < 0)
|
||||
throw MakeErrno("sched_setscheduler failed");
|
||||
int res = linux_sched_setscheduler(0, policy, &sched_param);
|
||||
|
||||
if (res < 0 && errno == EPERM) {
|
||||
DBusError error;
|
||||
DBusConnection *system_bus;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
system_bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (dbus_error_is_set(&error)) {
|
||||
throw FmtRuntimeError("could not connect to dbus: %s", error.message);
|
||||
}
|
||||
dbus_error_free(&error);
|
||||
|
||||
int max_realtime_priority;
|
||||
if ((max_realtime_priority = rtkit_get_max_realtime_priority(system_bus)) < 0) {
|
||||
dbus_connection_unref(system_bus);
|
||||
throw MakeErrno("could not retrieve maximum realtime priority allowed");
|
||||
}
|
||||
|
||||
if (max_realtime_priority < sched_param.sched_priority) {
|
||||
sched_param.sched_priority = max_realtime_priority;
|
||||
/* dbus_connection_unref(system_bus); */
|
||||
/* throw MakeErrno("maximum realtime priority is below 40"); */
|
||||
}
|
||||
|
||||
if (rtkit_make_realtime(system_bus, 0, sched_param.sched_priority) < 0) {
|
||||
dbus_connection_unref(system_bus);
|
||||
throw MakeErrno("failed to request realtime scheduling");
|
||||
}
|
||||
|
||||
dbus_connection_unref(system_bus);
|
||||
res = 0;
|
||||
}
|
||||
|
||||
// if (res < 0) {
|
||||
// throw MakeErrno("sched_setscheduler failed");
|
||||
// }
|
||||
#endif // __linux__
|
||||
}
|
||||
|
@ -7,6 +7,13 @@ else
|
||||
threads_dep = dependency('threads')
|
||||
endif
|
||||
|
||||
if is_linux
|
||||
dbus_dep = dependency('dbus-1', required: get_option('dbus'))
|
||||
conf.set('ENABLE_DBUS', dbus_dep.found())
|
||||
else
|
||||
dbus_dep = []
|
||||
endif
|
||||
|
||||
conf.set('HAVE_PTHREAD_SETNAME_NP', compiler.has_function('pthread_setname_np', dependencies: threads_dep))
|
||||
|
||||
thread = static_library(
|
||||
@ -16,6 +23,7 @@ thread = static_library(
|
||||
include_directories: inc,
|
||||
dependencies: [
|
||||
threads_dep,
|
||||
dbus_dep,
|
||||
],
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user