123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- #define _GNU_SOURCE
- #include "gamemode.h"
- #include "common-logging.h"
- #include "gamemode-config.h"
- #include <dirent.h>
- #include <sched.h>
- #include <sys/resource.h>
- #include <sys/sysinfo.h>
- #ifndef SCHED_ISO
- #define SCHED_ISO 4
- #endif
- #define RENICE_INVALID -128
- int game_mode_get_renice(const pid_t client)
- {
-
- errno = 0;
- int priority = getpriority(PRIO_PROCESS, (id_t)client);
- if (priority == -1 && errno) {
- LOG_ERROR("getprority(PRIO_PROCESS, %d) failed : %s\n", client, strerror(errno));
- return RENICE_INVALID;
- }
- return -priority;
- }
- void game_mode_apply_renice(const GameModeContext *self, const pid_t client, int expected)
- {
- if (expected == RENICE_INVALID)
-
- return;
- GameModeConfig *config = game_mode_config_from_context(self);
-
- long int renice = config_get_renice_value(config);
- if (renice == 0) {
- return;
- }
-
- renice = -renice;
-
- if (expected != 0) {
- expected = (int)renice;
- renice = 0;
- }
-
- char tasks[128];
- snprintf(tasks, sizeof(tasks), "/proc/%d/task", client);
- DIR *client_task_dir = opendir(tasks);
- if (client_task_dir == NULL) {
- LOG_ERROR("Could not inspect tasks for client [%d]! Skipping ioprio optimisation.\n",
- client);
- return;
- }
-
- struct dirent *tid_entry;
- while ((tid_entry = readdir(client_task_dir)) != NULL) {
-
- if (tid_entry->d_name[0] == '.')
- continue;
-
- int tid = atoi(tid_entry->d_name);
-
- errno = 0;
- int prio = getpriority(PRIO_PROCESS, (id_t)tid);
- if (prio == -1 && errno) {
-
- LOG_ERROR("getpriority failed for client [%d,%d] with error: %s\n",
- client,
- tid,
- strerror(errno));
- } else if (prio != expected) {
-
- LOG_ERROR("Refused to renice client [%d,%d]: prio was (%d) but we expected (%d)\n",
- client,
- tid,
- prio,
- expected);
- } else if (setpriority(PRIO_PROCESS, (id_t)tid, (int)renice)) {
- LOG_HINTED(ERROR,
- "Failed to renice client [%d,%d], ignoring error condition: %s\n",
- " -- Your user may not have permission to do this. Please read the docs\n"
- " -- to learn how to adjust the pam limits.\n",
- client,
- tid,
- strerror(errno));
- }
- }
- closedir(client_task_dir);
- }
- void game_mode_apply_scheduling(const GameModeContext *self, const pid_t client)
- {
- GameModeConfig *config = game_mode_config_from_context(self);
-
- char softrealtime[CONFIG_VALUE_MAX] = { 0 };
- config_get_soft_realtime(config, softrealtime);
-
- bool enable_softrealtime = (strcmp(softrealtime, "on") == 0) ||
- ((strcmp(softrealtime, "auto") == 0) && (get_nprocs() > 3));
-
- if (enable_softrealtime) {
- const struct sched_param p = { .sched_priority = 0 };
- if (sched_setscheduler(client, SCHED_ISO | SCHED_RESET_ON_FORK, &p)) {
- const char *hint = "";
- HINT_ONCE_ON(
- errno == EPERM,
- hint,
- " -- The error indicates that you may be running a resource management\n"
- " -- daemon managing your game launcher and it leaks lower scheduling\n"
- " -- classes into the games. This is likely a bug in the management daemon\n"
- " -- and not a bug in GameMode, it should be reported upstream.\n"
- " -- If unsure, please also look here:\n"
- " -- https://github.com/FeralInteractive/gamemode/issues/68\n");
- HINT_ONCE_ON(
- errno == EINVAL,
- hint,
- " -- The error indicates that your kernel may not support this. If you\n"
- " -- don't know what SCHED_ISO means, you can safely ignore this. If you\n"
- " -- expected it to work, ensure you're running a kernel with MuQSS or\n"
- " -- PDS scheduler.\n"
- " -- For further technical reading on the topic start here:\n"
- " -- https://lwn.net/Articles/720227/\n");
- LOG_ERROR(
- "Failed setting client [%d] into SCHED_ISO mode, ignoring error condition: %s\n"
- "%s",
- client,
- strerror(errno),
- hint);
- }
- }
- }
|