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...
This commit is contained in:
Carsten Haitzler 2022-05-05 13:50:25 +01:00
parent e0ccb08d0a
commit 5ad1680a7d
4 changed files with 155 additions and 114 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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,