From 4fa003dff1ba106b7e5f8f9fe32c3812d06cbf59 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Fri, 13 May 2022 20:30:19 +0200 Subject: [PATCH] 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. --- include/sway/server.h | 2 ++ meson.build | 8 +++++ meson_options.txt | 1 + sway/main.c | 2 ++ sway/meson.build | 5 +++ sway/rtkit.c | 71 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+) create mode 100644 sway/rtkit.c diff --git a/include/sway/server.h b/include/sway/server.h index d8ccd64fd..56c711f33 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -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 *data); +void gain_realtime(void); + #endif diff --git a/meson.build b/meson.build index 46352da54..615e5a944 100644 --- a/meson.build +++ b/meson.build @@ -106,6 +106,12 @@ if get_option('tray').enabled() and not tray_deps_found endif 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.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_BASU', sdbus.found() and sdbus.name() == 'basu') 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')) if scdoc.found() @@ -319,6 +326,7 @@ summary({ 'xwayland': have_xwayland, 'gdk-pixbuf': gdk_pixbuf.found(), 'tray': have_tray, + 'rtkit': have_rtkit, 'man-pages': scdoc.found(), }, bool_yn: true) diff --git a/meson_options.txt b/meson_options.txt index 6ba675546..2c63e5485 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') 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('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') diff --git a/sway/main.c b/sway/main.c index 78974e228..5e3cd6ca9 100644 --- a/sway/main.c +++ b/sway/main.c @@ -413,6 +413,8 @@ int main(int argc, char **argv) { goto shutdown; } + gain_realtime(); + if (!server_start(&server)) { sway_terminate(EXIT_FAILURE); goto shutdown; diff --git a/sway/meson.build b/sway/meson.build index 0ad783e3f..0caaecff5 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -7,6 +7,7 @@ sway_sources = files( 'ipc-server.c', 'lock.c', 'main.c', + 'rtkit.c', 'server.c', 'swaynag.c', 'xdg_activation_v1.c', @@ -229,6 +230,10 @@ if have_xwayland sway_deps += xcb endif +if have_rtkit + sway_deps += sdbus +endif + executable( 'sway', sway_sources, diff --git a/sway/rtkit.c b/sway/rtkit.c new file mode 100644 index 000000000..58c4644ca --- /dev/null +++ b/sway/rtkit.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include "sway/server.h" +#include "log.h" +#if HAVE_LIBSYSTEMD +#include +#elif HAVE_LIBELOGIND +#include +#elif HAVE_BASU +#include +#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