From 5ad1680a7d1f1cbed970c501abab7746921b6b05 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 5 May 2022 13:50:25 +0100 Subject: [PATCH] e nice/pri change - centralise to util code also getrlimit to know if we can lower nice level, you will want something like: * - nice 0 in /etc/security/limits.conf to allow for users to both raise and lower nice level up until this limit (ie not negative nice levels). perhaps enlightenment_system needs to do this... --- src/bin/e_comp_wl.c | 52 +--------------- src/bin/e_comp_x.c | 66 +------------------- src/bin/e_utils.c | 148 ++++++++++++++++++++++++++++++++++++++++++++ src/bin/e_utils.h | 3 + 4 files changed, 155 insertions(+), 114 deletions(-) diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 0df8544fa..4e38d4820 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -534,59 +534,12 @@ _e_comp_wl_evas_cb_multi_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *o } } -static void -_e_comp_wl_client_priority_adjust(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_child, Eina_Bool do_child) -{ - Eina_List *files; - char *file, buff[PATH_MAX]; - FILE *f; - int pid2, ppid; - int num_read; - int n; - - if (use_adj) - n = (getpriority(PRIO_PROCESS, pid) + adj); - else - n = set; - - setpriority(PRIO_PROCESS, pid, n); - - if (adj_child) - use_adj = EINA_TRUE; - - if (!do_child) return; - - files = ecore_file_ls("/proc"); - EINA_LIST_FREE(files, file) - { - if (!isdigit(file[0])) - continue; - - snprintf(buff, sizeof(buff), "/proc/%s/stat", file); - if ((f = fopen(buff, "r"))) - { - pid2 = -1; - ppid = -1; - num_read = fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid); - fclose(f); - if (num_read == 2 && ppid == pid) - _e_comp_wl_client_priority_adjust(pid2, set, - adj, use_adj, - adj_child, do_child); - } - - free(file); - } -} - static void _e_comp_wl_client_priority_raise(E_Client *ec) { if (ec->netwm.pid <= 0) return; if (ec->netwm.pid == getpid()) return; - _e_comp_wl_client_priority_adjust(ec->netwm.pid, - e_config->priority - 1, -1, - EINA_FALSE, EINA_TRUE, EINA_FALSE); + e_pid_nice_priority_fg(ec->netwm.pid); } static void @@ -594,8 +547,7 @@ _e_comp_wl_client_priority_normal(E_Client *ec) { if (ec->netwm.pid <= 0) return; if (ec->netwm.pid == getpid()) return; - _e_comp_wl_client_priority_adjust(ec->netwm.pid, e_config->priority, 1, - EINA_FALSE, EINA_TRUE, EINA_FALSE); + e_pid_nice_priority_bg(ec->netwm.pid); } static Eina_Bool diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index ed00d553b..5139bc5ad 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -657,58 +657,6 @@ _e_comp_x_add_fail_job(void *d EINA_UNUSED) "GPU to use OpenGL with compositing.")); } -static void -_pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children) -{ - int newpri = set; - - if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj; - setpriority(PRIO_PROCESS, pid, newpri); -// shouldn't need to do this as default ionice class is "none" (0), and -// this inherits io priority FROM nice level -// ioprio_set(IOPRIO_WHO_PROCESS, pid, -// IOPRIO_PRIO_VALUE(2, 5)); - if (do_children) - { - Eina_List *files; - char *file, buf[PATH_MAX]; - FILE *f; - int pid2, ppid; - - // yes - this is /proc specific... so this may not work on some - // os's - works on linux. too bad for others. - files = ecore_file_ls("/proc"); - EINA_LIST_FREE(files, file) - { - if (isdigit(file[0])) - { - snprintf(buf, sizeof(buf), "/proc/%s/stat", file); - f = fopen(buf, "r"); - if (f) - { - pid2 = -1; - ppid = -1; - if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2) - { - fclose(f); - if (ppid == pid) - { - if (adj_children) - _pri_adj(pid2, set, adj, EINA_TRUE, - adj_children, do_children); - else - _pri_adj(pid2, set, adj, use_adj, - adj_children, do_children); - } - } - else fclose(f); - } - } - free(file); - } - } -} - static E_Client * _e_comp_x_client_find_by_alarm(Ecore_X_Sync_Alarm al) { @@ -953,12 +901,7 @@ _e_comp_x_client_pri_raise(E_Client *ec) { if (ec->netwm.pid <= 0) return; if (ec->netwm.pid == getpid()) return; - _pri_adj(ec->netwm.pid, - e_config->priority - 1, -1, EINA_FALSE, -// EINA_TRUE, EINA_TRUE); - EINA_TRUE, EINA_FALSE); -// printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n", -// ec->netwm.pid, e_client_util_name_get(ec)); + e_pid_nice_priority_fg(ec->netwm.pid); } static void @@ -966,12 +909,7 @@ _e_comp_x_client_pri_norm(E_Client *ec) { if (ec->netwm.pid <= 0) return; if (ec->netwm.pid == getpid()) return; - _pri_adj(ec->netwm.pid, - e_config->priority, 1, EINA_FALSE, -// EINA_TRUE, EINA_TRUE); - EINA_TRUE, EINA_FALSE); -// printf("WIN: pid %i, title %s (NORMAL)\n", -// ec->netwm.pid, e_client_util_name_get(ec)); + e_pid_nice_priority_bg(ec->netwm.pid); } static void diff --git a/src/bin/e_utils.c b/src/bin/e_utils.c index f2c983dee..7f5c650ee 100644 --- a/src/bin/e_utils.c +++ b/src/bin/e_utils.c @@ -1591,3 +1591,151 @@ e_username_get(void) if (pw) return pw->pw_name; return ""; } + +typedef struct +{ + int pid; + int pri_set, pri_adj; + int pri_only_filter; + Eina_Bool do_adj : 1; + Eina_Bool do_adj_children : 1; + Eina_Bool do_children : 1; +} E_Pri_Set_Adj_Data; + +static void +_pri_adj(int pid, int pri_set, int pri_adj, int pri_only_filter, + Eina_Bool do_adj, Eina_Bool do_adj_children, Eina_Bool do_children) +{ + Eina_List *files; + char *file, buf[PATH_MAX]; + int pid2, ppid, newpri, ret; + FILE *f; + + newpri = getpriority(PRIO_PROCESS, pid) + pri_adj; + if ((pri_only_filter == -99) || (pri_only_filter != newpri)) + { + if (do_adj) newpri += pri_adj; + else newpri = pri_set; + if (newpri > 19) newpri = 19; +// printf("PRI: %i -> %i (adj=%i, adj_ch=%i ch=%i)\n", pid, newpri, do_adj, do_adj_children, do_children); + ret = setpriority(PRIO_PROCESS, pid, newpri); +// if (ret < 0) printf("PRI: ret = %i | %s\n", ret, strerror(errno)); + } +// shouldn't need to do this as default ionice class is "none" (0), and +// this inherits io priority FROM nice level +// ioprio_set(IOPRIO_WHO_PROCESS, pid, +// IOPRIO_PRIO_VALUE(2, 5)); + if (do_children) + { +// yes - this is /proc specific... so this may not work on some +// os's - works on linux. too bad for others. + files = ecore_file_ls("/proc"); + EINA_LIST_FREE(files, file) + { + if (isdigit(file[0])) + { + snprintf(buf, sizeof(buf), "/proc/%s/stat", file); + f = fopen(buf, "r"); + if (f) + { + pid2 = ppid = -1; + ret = fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid); + fclose(f); + if (ret == 2) + { + if (ppid == pid) + { + if (do_adj_children) + _pri_adj(pid2, pri_set, pri_adj, + pri_only_filter, + EINA_TRUE, + do_adj_children, + do_children); + else + _pri_adj(pid2, pri_set, pri_adj, + pri_only_filter, + do_adj, + do_adj_children, + do_children); + } + } + } + } + free(file); + } + } +} + +static void +_e_pid_nice_priority_set_adjust_thread(void *data, + Ecore_Thread *eth EINA_UNUSED) +{ + E_Pri_Set_Adj_Data *dat = data; + +// printf("PRI: --------\n"); + _pri_adj(dat->pid, dat->pri_set, dat->pri_adj, dat->pri_only_filter, + dat->do_adj, dat->do_adj_children, dat->do_children); + free(dat); +} + +static void +_e_pid_nice_priority_set_adjust(int pid, int pri_set, int pri_adj, + int pri_only_filter, + Eina_Bool do_adj, Eina_Bool do_adj_children, + Eina_Bool do_children) +{ + E_Pri_Set_Adj_Data *dat = calloc(1, sizeof(E_Pri_Set_Adj_Data)); + + if (!dat) return; + dat->pid = pid; + dat->pri_set = pri_set; + dat->pri_adj = pri_adj; + dat->pri_only_filter = pri_only_filter; + dat->do_adj = do_adj; + dat->do_adj_children = do_adj_children; + dat->do_children = do_children; + ecore_thread_run(_e_pid_nice_priority_set_adjust_thread, NULL, NULL, dat); +} + +static Eina_Bool +_e_pid_nice_priority_lower_can(void) +{ +#ifdef RLIMIT_NICE + static int checked = -1; + struct rlimit rlim; + +again: + if (checked == 0) return EINA_FALSE; + else if (checked == 1) return EINA_TRUE; + + checked = 1; + if (getrlimit(RLIMIT_NICE, &rlim) == 0) + { + // if we can't lower pri to at least 20 (nice 0 ...) then assume + // we can only raise nice level never lower it + if (rlim.rlim_cur < 20) checked = 0; + } + goto again; // set checked now - try again +#endif + return EINA_TRUE; +} + +E_API void +e_pid_nice_priority_fg(int pid) +{ + int pri = e_config->priority - 1; + + if (!_e_pid_nice_priority_lower_can()) pri = e_config->priority; + _e_pid_nice_priority_set_adjust(pid, pri, -1, -99, // only these procs + EINA_FALSE, EINA_FALSE, EINA_FALSE); +} + +E_API void +e_pid_nice_priority_bg(int pid) +{ + int pri = e_config->priority; + + if (!_e_pid_nice_priority_lower_can()) pri = e_config->priority; + _e_pid_nice_priority_set_adjust(pid, pri, 1, -99, // only these procs + EINA_FALSE, EINA_FALSE, EINA_FALSE); +} diff --git a/src/bin/e_utils.h b/src/bin/e_utils.h index 8884ede03..3cca72159 100644 --- a/src/bin/e_utils.h +++ b/src/bin/e_utils.h @@ -72,6 +72,9 @@ E_API Ecore_Exe *e_util_exe_safe_run(const char *cmd, void *data); E_API const char *e_username_get(void); +E_API void e_pid_nice_priority_fg(int pid); +E_API void e_pid_nice_priority_bg(int pid); + typedef enum { E_UTIL_ACTION_NONE,