Trying rt scheduling policy while RLIMIT_RTTIME is set could result in
SIGXCPU if the limit is exceeded. Set an infinite limit temporarily
while checking if rt policy is allowed.
Modern heterogenous multiprocessor systems rely increasingly on
scheduler hinting for efficiency gains and system optimisation.
This is especially true on embedded systems, where background
tasks such as audio daemons should be consigned to the most
power-efficient core in the system. Left to its own devices, the
Linux Completely Fair Scheduler tends to migrate Pipewire to
more performant cores, even when this is unnecessary.
Luckily, CFS can be told by a task to clamp its utilisation values.
Coupled with energy-aware scheduling, this allows the scheduler to
make better informed decisions about where tasks should be placed,
and what pstate to set for the CPU it is running on.
Enable the user to configure UCLAMP_MIN and UCLAMP_MAX values via
arguments to libpipewire-module-rt.
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
Add a thead-loop.start-signal option that will do a signal before
entering the thread loop. Doing the signal in all cases can confuse
apps that don't expect the signal.
Make module-rt use the thread-loop.start-signal.
Fixes#3374
Since the recent changes to the RT module in Pipewire 0.3.75, some
applications such as those using OpenAL-Soft crash on startup if
neither the session nor the system bus is available. For example:
bwrap --dev-bind / / \
--bind /dev/null /run/dbus/system_bus_socket \
--bind /dev/null $XDG_RUNTIME_DIR/bus \
openal-info
Will result in a crash with the following error message:
dbus[1626147]: arguments to dbus_message_new_method_call() were
incorrect, assertion "path != NULL" failed in file dbus-message.c
line 1373.
This is normally a bug in some application using the D-Bus library.
The RT module previously failed to load if no bus was available, but
after the recent changes, the init. logic runs in a thread, and failing
to obtain the bus no longer causes the module to fail to load.
Then, functions called later such as `pw_rtkit_make_realtime` assume
the bus is available and try to use it, causing the error above.
Put the logic for obtaining and checking the bus back to `module_init`,
so the module fails to load again if no bus is available.
First check if we can adjust priorities with rlimits, if we can't and we
need to use rtkit, spawn a thread-loop to handle the rtkit stuff.
First do a pw_loop_invoke() to do the rtkit setup, including getting
some properties and then setting the nice level and rlimits.
Use pw_loop_invoke to queue rtkit realtime requests, this ensures we
always perform the requests after the setup and when the properties
are fetched.
See #3357
Don't block on the method calls to make realtime or high priority.
Those calls don't return anything and other errors (invalid method,
invalid arguments, no service,...) can be caught differently async.
Fixes#3357
Ask RTKit what the min nice level is and clamp our value to it to avoid
InvalidArgument errors.
Also add some more info messages when the level is clamped or invalid.
Fixes#3186
Refactor get_rt_priority_range().
When we can't set the requested priority, use rlimit to clamp it
and try again. If this clamped value is bigger than RT_PRIO_MIN,
we can allow this.
The result is that the RTPRIO is set to the max of the user rlimit
RTPRIO, as long as it's more than 11. Previously it would fall back
to RTKit.
The commit cited below mistakenly removed the set_rlimit call from under
`if (impl->use_rtkit)`, saying it doesn't have an rtkit implementation.
However, this function does call rtkit, so it has to be called in the
rtkit flow, otherwise pipewire fails to set the realtime priority,
printing the following error message:
mod.rt: RTKit error: org.freedesktop.DBus.Error.AccessDenied
mod.rt: could not make thread #### realtime using RTKit: Permission denied
Fixes: 5ae1c03d77 ("module-rt: small fixes")
could_use_rtkit -> can_use_rtkit.
Only warn when setting nice and there is no rtkit fallback.
Always call set_rtlimit, it does not have an rtkit implementation, if just
has some properties with limits.
Only try to set nice again with rtkit when we required rtkit for some
functions.
Previously module-rt only checks if the user have the permission to use
realtime scheduling, and will unconditioally disable RtKit if they do,
even when they don't have the permission to set nice or rlimit.
pthread_getschedparam() always returns non-negative values, so checking
if its return value is less than zero always evaluates to false.
Also, pthread functions don't set errno. While logging a warning
message, use the return value of pthread_getschedparam() instead of
errno.
Make helper method to parse thread properties and add 2 new properties
to control name and stack-size of the thread.
Use properties when creating threads with the default utils.
Use the default thread utils instead of pthread_create so that the
properties are used.
Setting a global thread-utils is not a good idea, especially
when multiple contexts will register their own interface.
Instead, set the thread-utils as a context object and use this to
configure the data loop in the context.
In JACK we need a per context implementation of the interface so that
we can find the context specific thread-utils.
See #2252
The policy can of course be higher than zero if the current thread uses
anything other than `SCHED_OTHER`, and `SCHED_RESET_ON_FORK` needs to be
set according to the old policy or we'll either run into errors or cause
unwanted side effects.
There are a couple other ways to allow a user/process to use realtime
priviliges like `CAP_SYS_NICE`. Instead of trying to check every
possible factor, just trying if setting realtime priviliges works is
going to be a much cleaner solution.