Leverage soft real time capabilities

Kernels that support SCHED_ISO scheduling policy can give processes soft
real time support. This improves latency without compromising system
stability. See https://lwn.net/Articles/720227/.

This commit adds support for setting this policy with a safe fall back if
kernel support is lacking by just ignoring the error condition.

Additionally, it also tries to raise the nice priority of the game to -4
to give it a slight IO and CPU priority over other background processes.
This needs PAM adjustments to allow users raising priority to certain
levels. If it doesn't work, the fall back strategy is also ignoring the
error condition. See /etc/security/limits.conf.

Kernels that currently support SCHED_ISO include kernels with Con
Kolivas MuQSS patchset (likely the CK patchset). This patchset is
generally recommended for desktop machines but usually not found in
standard distribution kernels due to lack of widespread stability tests.

Signed-off-by: Kai Krakow <kai@kaishome.de>
This commit is contained in:
Kai Krakow 2018-05-23 21:56:25 +02:00
parent 1ad1f3bbcf
commit 76ece2fc26
2 changed files with 48 additions and 0 deletions

View File

@ -5,6 +5,10 @@ The design has a clear-cut abstraction between the host daemon and library (`gam
GameMode was designed primarily as a stop-gap solution to problems with the Intel and AMD CPU powersave or ondemand governors, but is now able to launch custom user defined plugins, and is intended to be expanded further, as there are a wealth of automation tasks one might want to apply.
GameMode can leverage support for soft real time mode if the running kernel supports `SCHED_ISO`. This adjusts the scheduling of the game to real time without sacrificing system stability by starving other processes.
GameMode adjusts the nice priority of games to -4 to give it a slight IO and CPU priority over other background processes. This only works if your user is permitted to adjust priorities within the limits configured by PAM.
Issues with GameMode should be reported here in the issues section, and not reported to Feral directly.
---

View File

@ -38,12 +38,26 @@ POSSIBILITY OF SUCH DAMAGE.
#include "logging.h"
#include <linux/limits.h>
#include <linux/sched.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdatomic.h>
#include <string.h>
#include <sys/resource.h>
#include <systemd/sd-daemon.h>
/* SCHED_ISO may not be defined as it is a reserved value not yet
* implemented in official kernel sources, see linux/sched.h.
*/
#ifndef SCHED_ISO
#define SCHED_ISO 4
#endif
/* Priority to renice the process to.
*/
#define NICE_PRIORITY -4
/**
* The GameModeClient encapsulates the remote connection, providing a list
* form to contain the pid and credentials.
@ -150,6 +164,33 @@ void game_mode_context_destroy(GameModeContext *self)
pthread_rwlock_destroy(&self->rwlock);
}
/**
* Apply scheduling policies
*
* This tries to change the scheduler of the client to soft realtime mode
* available in some kernels as SCHED_ISO. It also tries to adjust the nice
* level. If some of each fail, ignore this and log a warning.
*
* We don't need to store the current values because when the client exits,
* everything will be good: Scheduling is only applied to the client and
* its children.
*/
static void game_mode_apply_scheduler(pid_t client)
{
LOG_MSG("Setting scheduling policies...\n");
if (setpriority(PRIO_PROCESS, (id_t)client, NICE_PRIORITY)) {
LOG_ERROR("Renicing client [%d] failed with error %d, ignoring.\n", client, errno);
}
const struct sched_param p = { .sched_priority = 0 };
if (sched_setscheduler(client, SCHED_ISO, &p)) {
LOG_ERROR("Setting client [%d] to SCHED_ISO failed with error %d, ignoring.\n",
client,
errno);
}
}
/**
* Pivot into game mode.
*
@ -343,6 +384,9 @@ bool game_mode_context_register(GameModeContext *self, pid_t client)
game_mode_context_enter(self);
}
/* Apply scheduler policies */
game_mode_apply_scheduler(client);
return true;
}