Commit 91d78daa authored by Martin Flöser's avatar Martin Flöser

Ensure libinput connection thread uses real time scheduling

Summary:
The SCHED_RESET_ON_FORK results in threads (not only processes) to have
the scheduling policy reset to default. This means that the libinput
thread is not real time, but this was actually intended.

To solve this problem KWin does start without the RESET_ON_FORK flag
during startup. Once createInput has been called the scheduling is
adjusted again and RESET_ON_FORK is added again. This results in the
libinput thread and all threads Qt starts in between (e.g. dbus) to gain
real time policy. But it is still not leaked to other processes or to
threads in KWin which don't need it.

Other options considered: just don't use RESET_ON_FORK and instead
manually reset on fork. This would mean all threads in KWin gain real
time, but we don't need this. It's only interesting for the main
(rendering, Wayland thread) and the input thread. Also the danger to
leak into another process is too high.

Keeping the capability till the libinput thread is created and adjust
the thread itself. This option was discarded as I don't want KWin to
have any capabilities when the QApplication is started.

Test Plan: ps -eL -o class,rtprio,cmd,comm  | grep kwin_wayland

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D8065
parent f25088c4
......@@ -1460,6 +1460,7 @@ InputRedirection::InputRedirection(QObject *parent)
if (LogindIntegration::self()->hasSessionControl()) {
setupLibInput();
} else {
LibInput::Connection::createThread();
if (LogindIntegration::self()->isConnected()) {
LogindIntegration::self()->takeControl();
} else {
......
......@@ -81,7 +81,7 @@ Q_SIGNALS:
};
Connection *Connection::s_self = nullptr;
QThread *Connection::s_thread = nullptr;
QPointer<QThread> Connection::s_thread;
static ConnectionAdaptor *s_adaptor = nullptr;
static Context *s_context = nullptr;
......@@ -107,6 +107,16 @@ Connection::Connection(QObject *parent)
// only here to fix build, using will crash, BUG 343529
}
void Connection::createThread()
{
if (s_thread) {
return;
}
s_thread = new QThread();
s_thread->setObjectName(QStringLiteral("libinput-connection"));
s_thread->start();
}
Connection *Connection::create(QObject *parent)
{
Q_ASSERT(!s_self);
......@@ -131,10 +141,9 @@ Connection *Connection::create(QObject *parent)
return nullptr;
}
}
s_thread = new QThread();
Connection::createThread();
s_self = new Connection(s_context);
s_self->moveToThread(s_thread);
s_thread->start();
QObject::connect(s_thread, &QThread::finished, s_self, &QObject::deleteLater);
QObject::connect(s_thread, &QThread::finished, s_thread, &QObject::deleteLater);
QObject::connect(parent, &QObject::destroyed, s_thread, &QThread::quit);
......
......@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwinglobals.h>
#include <QObject>
#include <QPointer>
#include <QSize>
#include <QMutex>
#include <QVector>
......@@ -91,6 +92,8 @@ public:
void updateLEDs(KWin::Xkb::LEDs leds);
static void createThread();
Q_SIGNALS:
void keyChanged(quint32 key, KWin::InputRedirection::KeyboardKeyState, quint32 time, KWin::LibInput::Device *device);
void pointerButtonChanged(quint32 button, KWin::InputRedirection::PointerButtonState state, quint32 time, KWin::LibInput::Device *device);
......@@ -149,7 +152,7 @@ private:
Xkb::LEDs m_leds;
KWIN_SINGLETON(Connection)
static QThread *s_thread;
static QPointer<QThread> s_thread;
};
}
......
......@@ -82,6 +82,28 @@ static void sighandler(int)
static void readDisplay(int pipe);
enum class RealTimeFlags
{
DontReset,
ResetOnFork
};
namespace {
void gainRealTime(RealTimeFlags flags = RealTimeFlags::DontReset)
{
#if HAVE_SCHED_RESET_ON_FORK
const int minPriority = sched_get_priority_min(SCHED_RR);
struct sched_param sp;
sp.sched_priority = minPriority;
int policy = SCHED_RR;
if (flags == RealTimeFlags::ResetOnFork) {
policy |= SCHED_RESET_ON_FORK;
}
sched_setscheduler(0, policy, &sp);
#endif
}
}
//************************************
// ApplicationWayland
//************************************
......@@ -139,6 +161,9 @@ void ApplicationWayland::performStartup()
// try creating the Wayland Backend
createInput();
// now libinput thread has been created, adjust scheduler to not leak into other processes
gainRealTime(RealTimeFlags::ResetOnFork);
VirtualKeyboard::create(this);
createBackend();
}
......@@ -460,16 +485,6 @@ static void unsetDumpable(int sig)
return;
}
void gainRealTime()
{
#if HAVE_SCHED_RESET_ON_FORK
const int minPriority = sched_get_priority_min(SCHED_RR);
struct sched_param sp;
sp.sched_priority = minPriority;
sched_setscheduler(0, SCHED_RR | SCHED_RESET_ON_FORK, &sp);
#endif
}
void dropNiceCapability()
{
#if HAVE_LIBCAP
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment