sway: request SCHED_RR via RTKit

This tries to connect to DBUS to request RTTimeUSecMax from RTKit and
than changes the scheduling policy of sway to SCHED_RR. I tested the
impact using hackbench, with this patch I don't see any cursor
stuttering while running the following hackbench command:

  $ hackbench -f 100 -l 100000 -s 100000

This also fixes the "your compositor is too slow"-warnings from
libinput.

The rtkit feature is currently auto, so if one of the SD-Bus libraries
is installed we will select it. However we will fail graciously with
only a debug note if we can't reach RTKit and won't touch RLIMIT_RTTIME
in this case. Users who don't want to have DBUS within sway itself can
disable the feature.
This commit is contained in:
Rouven Czerwinski 2022-05-13 20:30:19 +02:00
parent ffc603d451
commit 4fa003dff1
6 changed files with 89 additions and 0 deletions

View file

@ -173,4 +173,6 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data);
void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, void xdg_activation_v1_handle_request_activate(struct wl_listener *listener,
void *data); void *data);
void gain_realtime(void);
#endif #endif

View file

@ -106,6 +106,12 @@ if get_option('tray').enabled() and not tray_deps_found
endif endif
have_tray = (not get_option('tray').disabled()) and tray_deps_found have_tray = (not get_option('tray').disabled()) and tray_deps_found
rt_deps_found = sdbus.found()
if get_option('rtkit').enabled() and not rt_deps_found
error('Building with -Drtkit=enabled, but sd-bus has not been not found')
endif
have_rtkit = (not get_option('rtkit').disabled()) and rt_deps_found
conf_data = configuration_data() conf_data = configuration_data()
conf_data.set10('HAVE_XWAYLAND', have_xwayland) conf_data.set10('HAVE_XWAYLAND', have_xwayland)
@ -114,6 +120,7 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd
conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind')
conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu') conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu')
conf_data.set10('HAVE_TRAY', have_tray) conf_data.set10('HAVE_TRAY', have_tray)
conf_data.set10('HAVE_RTKIT', have_rtkit)
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
if scdoc.found() if scdoc.found()
@ -319,6 +326,7 @@ summary({
'xwayland': have_xwayland, 'xwayland': have_xwayland,
'gdk-pixbuf': gdk_pixbuf.found(), 'gdk-pixbuf': gdk_pixbuf.found(),
'tray': have_tray, 'tray': have_tray,
'rtkit': have_rtkit,
'man-pages': scdoc.found(), 'man-pages': scdoc.found(),
}, bool_yn: true) }, bool_yn: true)

View file

@ -6,6 +6,7 @@ option('swaybar', type: 'boolean', value: true, description: 'Enable support for
option('swaynag', type: 'boolean', value: true, description: 'Enable support for swaynag') option('swaynag', type: 'boolean', value: true, description: 'Enable support for swaynag')
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray') option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray')
option('rtkit', type: 'feature', value: 'auto', description: 'Enable support to request realtime policy via RTKit')
option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg') option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg')
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')
option('sd-bus-provider', type: 'combo', choices: ['auto', 'libsystemd', 'libelogind', 'basu'], value: 'auto', description: 'Provider of the sd-bus library') option('sd-bus-provider', type: 'combo', choices: ['auto', 'libsystemd', 'libelogind', 'basu'], value: 'auto', description: 'Provider of the sd-bus library')

View file

@ -413,6 +413,8 @@ int main(int argc, char **argv) {
goto shutdown; goto shutdown;
} }
gain_realtime();
if (!server_start(&server)) { if (!server_start(&server)) {
sway_terminate(EXIT_FAILURE); sway_terminate(EXIT_FAILURE);
goto shutdown; goto shutdown;

View file

@ -7,6 +7,7 @@ sway_sources = files(
'ipc-server.c', 'ipc-server.c',
'lock.c', 'lock.c',
'main.c', 'main.c',
'rtkit.c',
'server.c', 'server.c',
'swaynag.c', 'swaynag.c',
'xdg_activation_v1.c', 'xdg_activation_v1.c',
@ -229,6 +230,10 @@ if have_xwayland
sway_deps += xcb sway_deps += xcb
endif endif
if have_rtkit
sway_deps += sdbus
endif
executable( executable(
'sway', 'sway',
sway_sources, sway_sources,

71
sway/rtkit.c Normal file
View file

@ -0,0 +1,71 @@
#include <sys/resource.h>
#include <sched.h>
#include <unistd.h>
#include "sway/server.h"
#include "log.h"
#if HAVE_LIBSYSTEMD
#include <systemd/sd-bus.h>
#elif HAVE_LIBELOGIND
#include <elogind/sd-bus.h>
#elif HAVE_BASU
#include <basu/sd-bus.h>
#endif
#if HAVE_RTKIT
void gain_realtime(void) {
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *m = NULL;
sd_bus *bus = NULL;
uint32_t prio = sched_get_priority_min(SCHED_RR);
int ret;
struct rlimit rl;
int max_usec;
ret = sd_bus_open_system(&bus);
if (ret < 0) {
sway_log(SWAY_DEBUG, "Failed to connect to system bus");
goto finish;
}
ret = sd_bus_get_property_trivial(bus, "org.freedesktop.RealtimeKit1",
"/org/freedesktop/RealtimeKit1", "org.freedesktop.RealtimeKit1",
"RTTimeUSecMax", &error, 'x', &max_usec);
if (ret < 0) {
sway_log(SWAY_DEBUG, "Couldn't query RTTimeUSecMax");
goto finish;
}
rl.rlim_cur = max_usec;
rl.rlim_max = max_usec;
if (setrlimit(RLIMIT_RTTIME, &rl) < 0) {
sway_log(SWAY_INFO, "Failed to setrlimit, no RT via RTKit possible");
goto finish;
}
ret = sd_bus_call_method(bus, "org.freedesktop.RealtimeKit1", "/org/freedesktop/RealtimeKit1",
"org.freedesktop.RealtimeKit1", "MakeThreadRealtime", &error, &m, "tu",
(uint64_t)getpid(), prio);
if (ret < 0) {
sway_log(SWAY_ERROR, "Failed to setup SCHED_RR: %s", error.message);
goto finish;
}
sway_log(SWAY_INFO, "Successfully setup SCHED_RR");
finish:
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_unref(bus);
return;
}
#else
void gain_realtime(void)
{
return;
}
#endif