aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-04-20 07:35:42 -0700
committerChris Robinson <[email protected]>2021-04-20 07:35:42 -0700
commit37730927efe488e63114b5c665bd53e9ee5b478c (patch)
tree80363099564e4dc4ab61764a24ff1ddb4cc70236
parent22818b3e8399985e3174583cfaba6cb4436d7010 (diff)
Lower RLIMIT_RTTIME to allow RTKit to give RT priority
-rw-r--r--alc/alc.cpp5
-rw-r--r--alc/alcmain.h1
-rw-r--r--alc/helpers.cpp66
-rw-r--r--alsoftrc.sample5
4 files changed, 65 insertions, 12 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp
index 267e5fef..5ec0ab11 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -1130,6 +1130,8 @@ void alc_initconfig(void)
if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio"))
RTPrioLevel = *priopt;
+ if(auto limopt = ConfigValueBool(nullptr, nullptr, "rt-time-limit"))
+ AllowRTTimeLimit = *limopt;
aluInit();
aluInitMixer();
@@ -1317,6 +1319,9 @@ void ProbeCaptureDeviceList()
/* Mixing thread piority level */
int RTPrioLevel{1};
+/* Allow reducing the process's RTTime limit for RTKit. */
+bool AllowRTTimeLimit{true};
+
FILE *gLogFile{stderr};
#ifdef _DEBUG
LogLevel gLogLevel{LogLevel::Warning};
diff --git a/alc/alcmain.h b/alc/alcmain.h
index 7134dccf..d8cbb1a0 100644
--- a/alc/alcmain.h
+++ b/alc/alcmain.h
@@ -359,6 +359,7 @@ struct ALCdevice : public al::intrusive_ref<ALCdevice> {
extern int RTPrioLevel;
+extern bool AllowRTTimeLimit;
void SetRTPriority(void);
/**
diff --git a/alc/helpers.cpp b/alc/helpers.cpp
index 671a1ae5..28cf2a0f 100644
--- a/alc/helpers.cpp
+++ b/alc/helpers.cpp
@@ -204,7 +204,13 @@ void SetRTPriority(void)
#include <sched.h>
#endif
#ifdef HAVE_RTKIT
+#include <sys/time.h>
+#include <sys/resource.h>
+
#include "core/rtkit.h"
+#ifndef RLIMIT_RTTIME
+#define RLIMIT_RTTIME 15
+#endif
#endif
const PathNamePair &GetProcBinary()
@@ -437,34 +443,70 @@ void SetRTPriority()
dbus::Error error;
if(dbus::ConnectionPtr conn{(*pdbus_bus_get)(DBUS_BUS_SYSTEM, &error.get())})
{
+ using ulonglong = unsigned long long;
+ auto limit_rttime = [](DBusConnection *conn) -> int
+ {
+ long long maxrttime{rtkit_get_rttime_usec_max(conn)};
+ if(maxrttime <= 0) return static_cast<int>(std::abs(maxrttime));
+ const ulonglong umaxtime{static_cast<ulonglong>(maxrttime)};
+
+ struct rlimit rlim{};
+ if(getrlimit(RLIMIT_RTTIME, &rlim) != 0)
+ return errno;
+ TRACE("RTTime max: %llu (hard: %llu, soft: %llu)\n", umaxtime,
+ ulonglong{rlim.rlim_max}, ulonglong{rlim.rlim_cur});
+ if(rlim.rlim_max > umaxtime)
+ {
+ rlim.rlim_max = static_cast<rlim_t>(std::min<ulonglong>(umaxtime,
+ std::numeric_limits<rlim_t>::max()));
+ rlim.rlim_cur = std::min(rlim.rlim_cur, rlim.rlim_max);
+ if(setrlimit(RLIMIT_RTTIME, &rlim) != 0)
+ return errno;
+ }
+ return 0;
+ };
+
/* Don't stupidly exit if the connection dies while doing this. */
(*pdbus_connection_set_exit_on_disconnect)(conn.get(), false);
int nicemin{};
- rtkit_get_min_nice_level(conn.get(), &nicemin);
+ err = rtkit_get_min_nice_level(conn.get(), &nicemin);
+ if(err == -ENOENT)
+ {
+ err = std::abs(err);
+ ERR("Could not query RTKit: %s (%d)\n", std::strerror(err), err);
+ return;
+ }
int rtmax{rtkit_get_max_realtime_priority(conn.get())};
TRACE("Maximum real-time priority: %d, minimum niceness: %d\n", rtmax, nicemin);
+ err = EINVAL;
if(rtmax > 0)
{
+ if(AllowRTTimeLimit)
+ {
+ err = limit_rttime(conn.get());
+ if(err != 0)
+ WARN("Failed to set RLIMIT_RTTIME for RTKit: %s (%d)\n",
+ std::strerror(err), err);
+ }
+
/* Use half the maximum real-time priority allowed. */
TRACE("Making real-time with priority %d\n", (rtmax+1)/2);
err = rtkit_make_realtime(conn.get(), 0, (rtmax+1)/2);
- if(err != 0)
- {
- err = std::abs(err);
- WARN("Failed to set real-time priority: %s (%d)\n", std::strerror(err), err);
- }
+ if(err == 0) return;
+
+ err = std::abs(err);
+ WARN("Failed to set real-time priority: %s (%d)\n", std::strerror(err), err);
}
- if(err != 0 && nicemin < 0)
+ if(nicemin < 0)
{
TRACE("Making high priority with niceness %d\n", nicemin);
err = rtkit_make_high_priority(conn.get(), 0, nicemin);
- if(err != 0)
- {
- err = std::abs(err);
- WARN("Failed to set high priority: %s (%d)\n", std::strerror(err), err);
- }
+ if(err == 0) return;
+
+ err = std::abs(err);
+ WARN("Failed to set high priority: %s (%d)\n", std::strerror(err), err);
}
}
else
diff --git a/alsoftrc.sample b/alsoftrc.sample
index 3c964ada..825d74c9 100644
--- a/alsoftrc.sample
+++ b/alsoftrc.sample
@@ -190,6 +190,11 @@
# be a problem.
#rt-prio = 1
+## rt-time-limit: (global)
+# On non-Windows systems, allows reducing the process's RLIMIT_RTTIME resource
+# as necessary for acquiring real-time priority from RTKit.
+#rt-time-limit = true
+
## sources:
# Sets the maximum number of allocatable sources. Lower values may help for
# systems with apps that try to play more sounds than the CPU can handle.