mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-09-21 11:39:45 +02:00
add RestartGamemode command
This allows gamemode to leave the context and then enter it again, which re-applies all system optimizations. It is useful in cases where another program (like TLP) may override gamemode's optimizations. This is exposed to users by the -R or --restart flags to gamemoded.
This commit is contained in:

committed by
afayaz-feral

parent
af07e169d5
commit
ce6fe122f3
@@ -934,6 +934,49 @@ int game_mode_context_query_status(GameModeContext *self, pid_t client, pid_t re
|
||||
return ret;
|
||||
}
|
||||
|
||||
int game_mode_context_restart(GameModeContext *self, pid_t client, pid_t requester)
|
||||
{
|
||||
/* First check the requester settings */
|
||||
{
|
||||
char *executable = game_mode_context_find_exe(requester);
|
||||
if (!executable) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check our blacklist and whitelist */
|
||||
if (!config_get_supervisor_whitelisted(self->config, executable)) {
|
||||
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
|
||||
free(executable);
|
||||
return -2;
|
||||
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
|
||||
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
|
||||
free(executable);
|
||||
return -2;
|
||||
}
|
||||
|
||||
free(executable);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the current refcount on gamemode, this equates to whether gamemode is active or not,
|
||||
* see game_mode_context_register and game_mode_context_unregister
|
||||
*/
|
||||
if (!atomic_load_explicit(&self->refcount, memory_order_seq_cst)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Requires locking. */
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
|
||||
game_mode_context_leave(self);
|
||||
game_mode_context_enter(self);
|
||||
|
||||
/* Unlock here, potentially yielding */
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new GameModeClient for the given process ID
|
||||
*
|
||||
|
@@ -133,6 +133,26 @@ static int method_query_status(sd_bus_message *m, void *userdata,
|
||||
return sd_bus_reply_method_return(m, "i", status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the RestartGamemode D-BUS Method
|
||||
*/
|
||||
static int method_restart_gamemode(sd_bus_message *m, void *userdata,
|
||||
__attribute__((unused)) sd_bus_error *ret_error)
|
||||
{
|
||||
int pid = 0;
|
||||
GameModeContext *context = userdata;
|
||||
|
||||
int ret = sd_bus_message_read(m, "i", &pid);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("Failed to parse input parameters: %s\n", strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int status = game_mode_context_restart(context, (pid_t)pid, (pid_t)pid);
|
||||
|
||||
return sd_bus_reply_method_return(m, "i", status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the RegisterGameByPID D-BUS Method
|
||||
*/
|
||||
@@ -402,6 +422,7 @@ static const sd_bus_vtable gamemode_vtable[] = {
|
||||
SD_BUS_METHOD("RegisterGame", "i", "i", method_register_game, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("UnregisterGame", "i", "i", method_unregister_game, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("QueryStatus", "i", "i", method_query_status, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("RestartGamemode", "i", "i", method_restart_gamemode, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("RegisterGameByPID", "ii", "i", method_register_game_by_pid,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("UnregisterGameByPID", "ii", "i", method_unregister_game_by_pid,
|
||||
|
@@ -155,6 +155,16 @@ int game_mode_context_unregister(GameModeContext *self, pid_t pid, pid_t request
|
||||
*/
|
||||
int game_mode_context_query_status(GameModeContext *self, pid_t pid, pid_t requester);
|
||||
|
||||
/**
|
||||
* Restart gamemode if it is running
|
||||
*
|
||||
* @param pid Process ID for the remote client
|
||||
* @returns 0 if gamemode was restarted
|
||||
* 1 if gamemode was already deactivated
|
||||
* -2 if this request was rejected
|
||||
*/
|
||||
int game_mode_context_restart(GameModeContext *self, pid_t pid, pid_t requester);
|
||||
|
||||
/**
|
||||
* Query the config of a gamemode context
|
||||
*
|
||||
|
@@ -70,6 +70,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
" When no PID given, requests gamemode and pauses\n" \
|
||||
" -s[PID], --status=[PID] Query the status of gamemode for process\n" \
|
||||
" When no PID given, queries the status globally\n" \
|
||||
" -R, --reset If gamemode is currently running, stop it, then restart\n" \
|
||||
" -d, --daemonize Daemonize self after launch\n" \
|
||||
" -l, --log-to-syslog Log to syslog\n" \
|
||||
" -t, --test Run tests\n" \
|
||||
@@ -158,12 +159,17 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Options struct for getopt_long */
|
||||
static struct option long_options[] = {
|
||||
{ "daemonize", no_argument, 0, 'd' }, { "log-to-syslog", no_argument, 0, 'l' },
|
||||
{ "request", optional_argument, 0, 'r' }, { "test", no_argument, 0, 't' },
|
||||
{ "status", optional_argument, 0, 's' }, { "help", no_argument, 0, 'h' },
|
||||
{ "version", no_argument, 0, 'v' }, { NULL, 0, NULL, 0 },
|
||||
{ "daemonize", no_argument, 0, 'd' },
|
||||
{ "log-to-syslog", no_argument, 0, 'l' },
|
||||
{ "request", optional_argument, 0, 'r' },
|
||||
{ "test", no_argument, 0, 't' },
|
||||
{ "status", optional_argument, 0, 's' },
|
||||
{ "reset", no_argument, 0, 'R' },
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "version", no_argument, 0, 'v' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
static const char *short_options = "dls::r::tvh";
|
||||
static const char *short_options = "dls::r::tvhR";
|
||||
|
||||
while ((opt = getopt_long(argc, argv, short_options, long_options, 0)) != -1) {
|
||||
switch (opt) {
|
||||
@@ -289,6 +295,20 @@ int main(int argc, char *argv[])
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case 'R':
|
||||
switch (gamemode_request_restart()) {
|
||||
case 0: /* success */
|
||||
LOG_MSG("gamemode restart succeeded\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
case 1: /* already off */
|
||||
LOG_ERROR("gamemode was already deactivated\n");
|
||||
break;
|
||||
case -1: /* error */
|
||||
LOG_ERROR("gamemode_request_restart failed: %s\n", gamemode_error_string());
|
||||
break;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case 't': {
|
||||
int status = game_mode_run_client_tests();
|
||||
exit(status);
|
||||
|
Reference in New Issue
Block a user