mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-08-06 13:18:31 +02:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user