mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-06-07 08:07:20 +02:00
Merge pull request #108 from mdiluz/bug-and-feature-bash
Assorted small bug fixes
This commit is contained in:
commit
cc9f78fe0a
@ -71,6 +71,7 @@ struct GameModeConfig {
|
|||||||
char whitelist[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
char whitelist[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
char blacklist[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
char blacklist[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
|
|
||||||
|
long script_timeout;
|
||||||
char startscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
char startscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
char endscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
char endscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
|
|
||||||
@ -278,6 +279,8 @@ static int inih_handler(void *user, const char *section, const char *name, const
|
|||||||
valid = append_value_to_list(name, value, self->values.startscripts);
|
valid = append_value_to_list(name, value, self->values.startscripts);
|
||||||
} else if (strcmp(name, "end") == 0) {
|
} else if (strcmp(name, "end") == 0) {
|
||||||
valid = append_value_to_list(name, value, self->values.endscripts);
|
valid = append_value_to_list(name, value, self->values.endscripts);
|
||||||
|
} else if (strcmp(name, "script_timeout") == 0) {
|
||||||
|
valid = get_long_value(name, value, &self->values.script_timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,6 +333,7 @@ static void load_config_files(GameModeConfig *self)
|
|||||||
self->values.reaper_frequency = DEFAULT_REAPER_FREQ;
|
self->values.reaper_frequency = DEFAULT_REAPER_FREQ;
|
||||||
self->values.gpu_device = -1; /* 0 is a valid device ID so use -1 to indicate no value */
|
self->values.gpu_device = -1; /* 0 is a valid device ID so use -1 to indicate no value */
|
||||||
self->values.nv_perf_level = -1;
|
self->values.nv_perf_level = -1;
|
||||||
|
self->values.script_timeout = 10; /* Default to 10 seconds for scripts */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locations to load, in order
|
* Locations to load, in order
|
||||||
@ -506,6 +510,11 @@ void config_get_gamemode_end_scripts(GameModeConfig *self,
|
|||||||
memcpy_locked_config(self, scripts, self->values.endscripts, sizeof(self->values.startscripts));
|
memcpy_locked_config(self, scripts, self->values.endscripts, sizeof(self->values.startscripts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the script timemout value
|
||||||
|
*/
|
||||||
|
DEFINE_CONFIG_GET(script_timeout)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the chosen default governor
|
* Get the chosen default governor
|
||||||
*/
|
*/
|
||||||
|
@ -105,6 +105,11 @@ void config_get_gamemode_start_scripts(GameModeConfig *self,
|
|||||||
void config_get_gamemode_end_scripts(GameModeConfig *self,
|
void config_get_gamemode_end_scripts(GameModeConfig *self,
|
||||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX]);
|
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the script timout value
|
||||||
|
*/
|
||||||
|
long config_get_script_timeout(GameModeConfig *self);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the chosen default governor
|
* Get the chosen default governor
|
||||||
*/
|
*/
|
||||||
|
@ -37,20 +37,49 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static const int default_timout = 5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call an external process
|
* Call an external process
|
||||||
*/
|
*/
|
||||||
int run_external_process(const char *const *exec_args)
|
int run_external_process(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX], int tsec)
|
||||||
{
|
{
|
||||||
pid_t p;
|
pid_t p;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
int pipes[2];
|
||||||
|
char internal[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||||
|
|
||||||
|
if (pipe(pipes) == -1) {
|
||||||
|
LOG_ERROR("Could not create pipe: %s!\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the default timeout */
|
||||||
|
if (tsec == -1) {
|
||||||
|
tsec = default_timout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up our signaling for the child and the timout */
|
||||||
|
sigset_t mask;
|
||||||
|
sigset_t omask;
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGCHLD);
|
||||||
|
if (sigprocmask(SIG_BLOCK, &mask, &omask) < 0) {
|
||||||
|
LOG_ERROR("sigprocmask failed: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((p = fork()) < 0) {
|
if ((p = fork()) < 0) {
|
||||||
LOG_ERROR("Failed to fork(): %s\n", strerror(errno));
|
LOG_ERROR("Failed to fork(): %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
} else if (p == 0) {
|
} else if (p == 0) {
|
||||||
|
/* Send STDOUT to the pipe */
|
||||||
|
dup2(pipes[1], STDOUT_FILENO);
|
||||||
|
close(pipes[0]);
|
||||||
|
close(pipes[1]);
|
||||||
/* Execute the command */
|
/* Execute the command */
|
||||||
/* Note about cast:
|
/* Note about cast:
|
||||||
* The statement about argv[] and envp[] being constants is
|
* The statement about argv[] and envp[] being constants is
|
||||||
@ -65,54 +94,30 @@ int run_external_process(const char *const *exec_args)
|
|||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waitpid(p, &status, 0) < 0) {
|
/* Set up the timout */
|
||||||
LOG_ERROR("Failed to waitpid(%d): %s\n", (int)p, strerror(errno));
|
struct timespec timeout;
|
||||||
return -1;
|
timeout.tv_sec = tsec; /* Magic timeout value of 5s for now - should be sane for most commands
|
||||||
}
|
*/
|
||||||
|
timeout.tv_nsec = 0;
|
||||||
|
|
||||||
/* i.e. sigsev */
|
/* Wait for the child to finish up with a timout */
|
||||||
if (!WIFEXITED(status)) {
|
while (true) {
|
||||||
LOG_ERROR("Child process '%s' exited abnormally\n", exec_args[0]);
|
if (sigtimedwait(&mask, NULL, &timeout) < 0) {
|
||||||
} else if (WEXITSTATUS(status) != 0) {
|
if (errno == EINTR) {
|
||||||
LOG_ERROR("External process failed\n");
|
continue;
|
||||||
return -1;
|
} else if (errno == EAGAIN) {
|
||||||
}
|
LOG_ERROR("Child process timed out for %s, killing and returning\n", exec_args[0]);
|
||||||
|
kill(p, SIGKILL);
|
||||||
return 0;
|
} else {
|
||||||
}
|
LOG_ERROR("sigtimedwait failed: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
/**
|
}
|
||||||
* Call an external process and get output
|
|
||||||
*/
|
|
||||||
int run_external_process_get_output(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX])
|
|
||||||
{
|
|
||||||
pid_t p;
|
|
||||||
int status = 0;
|
|
||||||
int pipes[2];
|
|
||||||
|
|
||||||
if (pipe(pipes) == -1) {
|
|
||||||
LOG_ERROR("Could not create pipe: %s!\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((p = fork()) < 0) {
|
|
||||||
LOG_ERROR("Failed to fork(): %s\n", strerror(errno));
|
|
||||||
return false;
|
|
||||||
} else if (p == 0) {
|
|
||||||
/* Send STDOUT to the pipe */
|
|
||||||
dup2(pipes[1], STDOUT_FILENO);
|
|
||||||
close(pipes[0]);
|
|
||||||
close(pipes[1]);
|
|
||||||
/* Launch the process */
|
|
||||||
if (execv(exec_args[0], (char *const *)exec_args) != 0) {
|
|
||||||
LOG_ERROR("Failed to execute external process %s: %s\n", exec_args[0], strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
_exit(EXIT_SUCCESS);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipes[1]);
|
close(pipes[1]);
|
||||||
if (read(pipes[0], buffer, EXTERNAL_BUFFER_MAX) < 0) {
|
if (read(pipes[0], internal, EXTERNAL_BUFFER_MAX) < 0) {
|
||||||
LOG_ERROR("Failed to read from process %s: %s\n", exec_args[0], strerror(errno));
|
LOG_ERROR("Failed to read from process %s: %s\n", exec_args[0], strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -126,9 +131,13 @@ int run_external_process_get_output(const char *const *exec_args, char buffer[EX
|
|||||||
if (!WIFEXITED(status)) {
|
if (!WIFEXITED(status)) {
|
||||||
LOG_ERROR("Child process '%s' exited abnormally\n", exec_args[0]);
|
LOG_ERROR("Child process '%s' exited abnormally\n", exec_args[0]);
|
||||||
} else if (WEXITSTATUS(status) != 0) {
|
} else if (WEXITSTATUS(status) != 0) {
|
||||||
LOG_ERROR("External process failed\n");
|
LOG_ERROR("External process failed with exit code %u\n", WEXITSTATUS(status));
|
||||||
|
LOG_ERROR("Output was: %s\n", buffer ? buffer : internal);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
memcpy(buffer, internal, EXTERNAL_BUFFER_MAX);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,4 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define EXTERNAL_BUFFER_MAX 1024
|
#define EXTERNAL_BUFFER_MAX 1024
|
||||||
|
|
||||||
/* Run an external process and capture the return value */
|
/* Run an external process and capture the return value */
|
||||||
int run_external_process(const char *const *exec_args);
|
int run_external_process(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX], int tsec);
|
||||||
|
|
||||||
/* Run an external process and capture the return value as well as output */
|
|
||||||
int run_external_process_get_output(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX]);
|
|
||||||
|
@ -229,7 +229,7 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply)
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (run_external_process(exec_args) != 0) {
|
if (run_external_process(exec_args, NULL, -1) != 0) {
|
||||||
LOG_ERROR("Failed to call gpuclockctl, could not apply optimisations!\n");
|
LOG_ERROR("Failed to call gpuclockctl, could not apply optimisations!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ int game_mode_get_gpu(GameModeGPUInfo *info)
|
|||||||
};
|
};
|
||||||
|
|
||||||
char buffer[EXTERNAL_BUFFER_MAX] = { 0 };
|
char buffer[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||||
if (run_external_process_get_output(exec_args, buffer) != 0) {
|
if (run_external_process(exec_args, buffer, -1) != 0) {
|
||||||
LOG_ERROR("Failed to call gpuclockctl, could get values!\n");
|
LOG_ERROR("Failed to call gpuclockctl, could get values!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -41,27 +41,45 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "daemon_config.h"
|
#include "daemon_config.h"
|
||||||
|
#include "external-helper.h"
|
||||||
#include "gamemode_client.h"
|
#include "gamemode_client.h"
|
||||||
#include "governors-query.h"
|
#include "governors-query.h"
|
||||||
#include "gpu-control.h"
|
#include "gpu-control.h"
|
||||||
|
|
||||||
/* Initial verify step to ensure gamemode isn't already active */
|
/* Initial verify step to ensure gamemode isn't already active */
|
||||||
static int verify_gamemode_initial(void)
|
static int verify_gamemode_initial(struct GameModeConfig *config)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if ((status = gamemode_query_status()) != 0 && status != -1) {
|
if ((status = gamemode_query_status()) != 0 && status != -1) {
|
||||||
LOG_ERROR("gamemode is currently active, tests require gamemode to start deactivated!\n");
|
long reaper = config_get_reaper_frequency(config);
|
||||||
status = -1;
|
LOG_MSG("GameMode was active, waiting for the reaper thread (%ld seconds)!\n", reaper);
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
/* Try again after waiting */
|
||||||
|
for (int i = 0; i < reaper; i++) {
|
||||||
|
if ((status = gamemode_query_status()) == 0) {
|
||||||
|
status = 0;
|
||||||
|
break;
|
||||||
|
} else if (status == -1) {
|
||||||
|
goto status_error;
|
||||||
|
}
|
||||||
|
LOG_MSG("Waiting...\n");
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
if (status == 1)
|
||||||
|
LOG_ERROR("GameMode still active, cannot run tests!\n");
|
||||||
} else if (status == -1) {
|
} else if (status == -1) {
|
||||||
LOG_ERROR("gamemode_query_status failed: %s!\n", gamemode_error_string());
|
goto status_error;
|
||||||
LOG_ERROR("is gamemode installed correctly?\n");
|
|
||||||
status = -1;
|
|
||||||
} else {
|
} else {
|
||||||
status = 0;
|
status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
status_error:
|
||||||
|
LOG_ERROR("gamemode_query_status failed: %s!\n", gamemode_error_string());
|
||||||
|
LOG_ERROR("is gamemode installed correctly?\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if gamemode is active and this client is registered */
|
/* Check if gamemode is active and this client is registered */
|
||||||
@ -183,8 +201,8 @@ static int run_dual_client_tests(void)
|
|||||||
/* Parent process */
|
/* Parent process */
|
||||||
/* None of these should early-out as we need to clean up the child */
|
/* None of these should early-out as we need to clean up the child */
|
||||||
|
|
||||||
/* Give the child a chance to reqeust gamemode */
|
/* Give the child a chance to request gamemode */
|
||||||
usleep(1000);
|
usleep(10000);
|
||||||
|
|
||||||
/* Check that when we request gamemode, it replies that the other client is connected */
|
/* Check that when we request gamemode, it replies that the other client is connected */
|
||||||
if (verify_other_client_connected() != 0)
|
if (verify_other_client_connected() != 0)
|
||||||
@ -301,12 +319,11 @@ static int run_cpu_governor_tests(struct GameModeConfig *config)
|
|||||||
strcpy(desiredgov, "performance");
|
strcpy(desiredgov, "performance");
|
||||||
|
|
||||||
char defaultgov[CONFIG_VALUE_MAX] = { 0 };
|
char defaultgov[CONFIG_VALUE_MAX] = { 0 };
|
||||||
config_get_default_governor(config, defaultgov);
|
|
||||||
|
|
||||||
if (desiredgov[0] == '\0') {
|
if (defaultgov[0] == '\0') {
|
||||||
const char *currentgov = get_gov_state();
|
const char *currentgov = get_gov_state();
|
||||||
if (currentgov) {
|
if (currentgov) {
|
||||||
strncpy(desiredgov, currentgov, CONFIG_VALUE_MAX);
|
strncpy(defaultgov, currentgov, CONFIG_VALUE_MAX);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
"Could not get current CPU governor state, this indicates an error! See rest "
|
"Could not get current CPU governor state, this indicates an error! See rest "
|
||||||
@ -342,6 +359,7 @@ static int run_cpu_governor_tests(struct GameModeConfig *config)
|
|||||||
static int run_custom_scripts_tests(struct GameModeConfig *config)
|
static int run_custom_scripts_tests(struct GameModeConfig *config)
|
||||||
{
|
{
|
||||||
int scriptstatus = 0;
|
int scriptstatus = 0;
|
||||||
|
long timeout = config_get_script_timeout(config);
|
||||||
|
|
||||||
/* Grab and test the start scripts */
|
/* Grab and test the start scripts */
|
||||||
char startscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
char startscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
@ -353,7 +371,8 @@ static int run_custom_scripts_tests(struct GameModeConfig *config)
|
|||||||
while (*startscripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
while (*startscripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||||
LOG_MSG(":::: Running start script [%s]\n", startscripts[i]);
|
LOG_MSG(":::: Running start script [%s]\n", startscripts[i]);
|
||||||
|
|
||||||
int ret = system(startscripts[i]);
|
const char *args[] = { "/bin/sh", "-c", startscripts[i], NULL };
|
||||||
|
int ret = run_external_process(args, NULL, (int)timeout);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
LOG_MSG(":::: Passed\n");
|
LOG_MSG(":::: Passed\n");
|
||||||
@ -375,7 +394,8 @@ static int run_custom_scripts_tests(struct GameModeConfig *config)
|
|||||||
while (*endscripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
while (*endscripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||||
LOG_MSG(":::: Running end script [%s]\n", endscripts[i]);
|
LOG_MSG(":::: Running end script [%s]\n", endscripts[i]);
|
||||||
|
|
||||||
int ret = system(endscripts[i]);
|
const char *args[] = { "/bin/sh", "-c", endscripts[i], NULL };
|
||||||
|
int ret = run_external_process(args, NULL, (int)timeout);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
LOG_MSG(":::: Passed\n");
|
LOG_MSG(":::: Passed\n");
|
||||||
@ -668,7 +688,7 @@ int game_mode_run_client_tests()
|
|||||||
/* First verify that gamemode is not currently active on the system
|
/* First verify that gamemode is not currently active on the system
|
||||||
* As well as it being currently installed and queryable
|
* As well as it being currently installed and queryable
|
||||||
*/
|
*/
|
||||||
if (verify_gamemode_initial() != 0)
|
if (verify_gamemode_initial(config) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Controls whether we require a supervisor to actually make requests */
|
/* Controls whether we require a supervisor to actually make requests */
|
||||||
|
@ -93,6 +93,7 @@ static void *game_mode_context_reaper(void *userdata);
|
|||||||
static void game_mode_context_enter(GameModeContext *self);
|
static void game_mode_context_enter(GameModeContext *self);
|
||||||
static void game_mode_context_leave(GameModeContext *self);
|
static void game_mode_context_leave(GameModeContext *self);
|
||||||
static char *game_mode_context_find_exe(pid_t pid);
|
static char *game_mode_context_find_exe(pid_t pid);
|
||||||
|
static void game_mode_execute_scripts(char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX], int timeout);
|
||||||
|
|
||||||
void game_mode_context_init(GameModeContext *self)
|
void game_mode_context_init(GameModeContext *self)
|
||||||
{
|
{
|
||||||
@ -170,21 +171,6 @@ static void game_mode_context_enter(GameModeContext *self)
|
|||||||
LOG_MSG("Entering Game Mode...\n");
|
LOG_MSG("Entering Game Mode...\n");
|
||||||
sd_notifyf(0, "STATUS=%sGameMode is now active.%s\n", "\x1B[1;32m", "\x1B[0m");
|
sd_notifyf(0, "STATUS=%sGameMode is now active.%s\n", "\x1B[1;32m", "\x1B[0m");
|
||||||
|
|
||||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
|
||||||
memset(scripts, 0, sizeof(scripts));
|
|
||||||
config_get_gamemode_start_scripts(self->config, scripts);
|
|
||||||
|
|
||||||
unsigned int i = 0;
|
|
||||||
while (*scripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
|
||||||
LOG_MSG("Executing script [%s]\n", scripts[i]);
|
|
||||||
int err;
|
|
||||||
if ((err = system(scripts[i])) != 0) {
|
|
||||||
/* Log the failure, but this is not fatal */
|
|
||||||
LOG_ERROR("Script [%s] failed with error %d\n", scripts[i], err);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the initial governor state so we can revert it correctly */
|
/* Read the initial governor state so we can revert it correctly */
|
||||||
const char *initial_state = get_gov_state();
|
const char *initial_state = get_gov_state();
|
||||||
if (initial_state) {
|
if (initial_state) {
|
||||||
@ -203,7 +189,7 @@ static void game_mode_context_enter(GameModeContext *self)
|
|||||||
};
|
};
|
||||||
|
|
||||||
LOG_MSG("Requesting update of governor policy to %s\n", desiredGov);
|
LOG_MSG("Requesting update of governor policy to %s\n", desiredGov);
|
||||||
if (run_external_process(exec_args) != 0) {
|
if (run_external_process(exec_args, NULL, -1) != 0) {
|
||||||
LOG_ERROR("Failed to update cpu governor policy\n");
|
LOG_ERROR("Failed to update cpu governor policy\n");
|
||||||
/* if the set fails, clear the initial mode so we don't try and reset it back and fail
|
/* if the set fails, clear the initial mode so we don't try and reset it back and fail
|
||||||
* again, presumably */
|
* again, presumably */
|
||||||
@ -217,6 +203,14 @@ static void game_mode_context_enter(GameModeContext *self)
|
|||||||
|
|
||||||
/* Apply GPU optimisations */
|
/* Apply GPU optimisations */
|
||||||
game_mode_apply_gpu(self->gpu_info, true);
|
game_mode_apply_gpu(self->gpu_info, true);
|
||||||
|
|
||||||
|
/* Run custom scripts last - ensures the above are applied first and these scripts can react to
|
||||||
|
* them if needed */
|
||||||
|
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
|
memset(scripts, 0, sizeof(scripts));
|
||||||
|
config_get_gamemode_start_scripts(self->config, scripts);
|
||||||
|
long timeout = config_get_script_timeout(self->config);
|
||||||
|
game_mode_execute_scripts(scripts, (int)timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -249,7 +243,7 @@ static void game_mode_context_leave(GameModeContext *self)
|
|||||||
};
|
};
|
||||||
|
|
||||||
LOG_MSG("Requesting update of governor policy to %s\n", gov_mode);
|
LOG_MSG("Requesting update of governor policy to %s\n", gov_mode);
|
||||||
if (run_external_process(exec_args) != 0) {
|
if (run_external_process(exec_args, NULL, -1) != 0) {
|
||||||
LOG_ERROR("Failed to update cpu governor policy\n");
|
LOG_ERROR("Failed to update cpu governor policy\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,17 +253,8 @@ static void game_mode_context_leave(GameModeContext *self)
|
|||||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||||
memset(scripts, 0, sizeof(scripts));
|
memset(scripts, 0, sizeof(scripts));
|
||||||
config_get_gamemode_end_scripts(self->config, scripts);
|
config_get_gamemode_end_scripts(self->config, scripts);
|
||||||
|
long timeout = config_get_script_timeout(self->config);
|
||||||
unsigned int i = 0;
|
game_mode_execute_scripts(scripts, (int)timeout);
|
||||||
while (*scripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
|
||||||
LOG_MSG("Executing script [%s]\n", scripts[i]);
|
|
||||||
int err;
|
|
||||||
if ((err = system(scripts[i])) != 0) {
|
|
||||||
/* Log the failure, but this is not fatal */
|
|
||||||
LOG_ERROR("Script [%s] failed with error %d\n", scripts[i], err);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -701,3 +686,19 @@ fail:
|
|||||||
LOG_ERROR("Unable to find executable for PID %d: %s\n", pid, strerror(errno));
|
LOG_ERROR("Unable to find executable for PID %d: %s\n", pid, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Executes a set of scripts */
|
||||||
|
static void game_mode_execute_scripts(char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX], int timeout)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (*scripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||||
|
LOG_MSG("Executing script [%s]\n", scripts[i]);
|
||||||
|
int err;
|
||||||
|
const char *args[] = { "/bin/sh", "-c", scripts[i], NULL };
|
||||||
|
if ((err = run_external_process(args, NULL, timeout)) != 0) {
|
||||||
|
/* Log the failure, but this is not fatal */
|
||||||
|
LOG_ERROR("Script [%s] failed with error %d\n", scripts[i], err);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -79,7 +79,7 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
|||||||
NV_CORE_OFFSET_ATTRIBUTE,
|
NV_CORE_OFFSET_ATTRIBUTE,
|
||||||
info->nv_perf_level);
|
info->nv_perf_level);
|
||||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||||
if (run_external_process_get_output(exec_args_core, buf) != 0) {
|
if (run_external_process(exec_args_core, buf, -1) != 0) {
|
||||||
LOG_ERROR("Failed to set %s!\n", arg);
|
LOG_ERROR("Failed to set %s!\n", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
|||||||
NV_MEM_OFFSET_ATTRIBUTE,
|
NV_MEM_OFFSET_ATTRIBUTE,
|
||||||
info->nv_perf_level);
|
info->nv_perf_level);
|
||||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||||
if (run_external_process_get_output(exec_args_mem, buf) != 0) {
|
if (run_external_process(exec_args_mem, buf, -1) != 0) {
|
||||||
LOG_ERROR("Failed to set %s!\n", arg);
|
LOG_ERROR("Failed to set %s!\n", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
|||||||
info->nv_perf_level,
|
info->nv_perf_level,
|
||||||
info->core);
|
info->core);
|
||||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-a", core_arg, NULL };
|
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-a", core_arg, NULL };
|
||||||
if (run_external_process(exec_args_core) != 0) {
|
if (run_external_process(exec_args_core, NULL, -1) != 0) {
|
||||||
LOG_ERROR("Failed to set %s!\n", core_arg);
|
LOG_ERROR("Failed to set %s!\n", core_arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
|||||||
info->nv_perf_level,
|
info->nv_perf_level,
|
||||||
info->mem);
|
info->mem);
|
||||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-a", mem_arg, NULL };
|
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-a", mem_arg, NULL };
|
||||||
if (run_external_process(exec_args_mem) != 0) {
|
if (run_external_process(exec_args_mem, NULL, -1) != 0) {
|
||||||
LOG_ERROR("Failed to set %s!\n", mem_arg);
|
LOG_ERROR("Failed to set %s!\n", mem_arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,8 @@ static int gamemode_request(const char *function, int arg)
|
|||||||
{
|
{
|
||||||
sd_bus_message *msg = NULL;
|
sd_bus_message *msg = NULL;
|
||||||
sd_bus *bus = NULL;
|
sd_bus *bus = NULL;
|
||||||
|
sd_bus_error err;
|
||||||
|
memset(&err, 0, sizeof(err));
|
||||||
|
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ static int gamemode_request(const char *function, int arg)
|
|||||||
"/com/feralinteractive/GameMode",
|
"/com/feralinteractive/GameMode",
|
||||||
"com.feralinteractive.GameMode",
|
"com.feralinteractive.GameMode",
|
||||||
function,
|
function,
|
||||||
NULL,
|
&err,
|
||||||
&msg,
|
&msg,
|
||||||
arg ? "ii" : "i",
|
arg ? "ii" : "i",
|
||||||
getpid(),
|
getpid(),
|
||||||
@ -72,7 +74,13 @@ static int gamemode_request(const char *function, int arg)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
snprintf(error_string,
|
snprintf(error_string,
|
||||||
sizeof(error_string),
|
sizeof(error_string),
|
||||||
"Could not call method on bus: %s",
|
"Could not call method %s on com.feralinteractive.GameMode\n"
|
||||||
|
"\t%s\n"
|
||||||
|
"\t%s\n"
|
||||||
|
"\t%s\n",
|
||||||
|
function,
|
||||||
|
err.name,
|
||||||
|
err.message,
|
||||||
strerror(-ret));
|
strerror(-ret));
|
||||||
} else {
|
} else {
|
||||||
// Read the reply
|
// Read the reply
|
||||||
|
Loading…
x
Reference in New Issue
Block a user