library: add provision for displaying autogroup values

In the link referenced below there's an explanation of
the linux autogroup feature which has been around ever
since linux-2.6.38. With that explanation there's also
surprising (maybe shocking) revelations about the nice
and renice commands if CONFIG_SCHED_AUTOGROUP was set.

When autogroups are active, such programs are rendered
mostly useless because the nice value will only affect
scheduling priority relative to other processes in the
same autogroup. In order to accomplish what we thought
of as renice, that nice value in /proc/<pid>/autogroup
must be changed. Altering any single member of a group
will also affect every other member of that autogroup.

So, this commit will set the stage for users of newlib
to display autogroup identifiers plus their associated
nice values (now that their importance is understood).

Reference(s):
https://github.com/nlburgin/reallynice

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2021-08-05 00:00:00 -05:00 committed by Craig Small
parent 93c0a6cedf
commit 631e5d91f3
4 changed files with 43 additions and 1 deletions

View File

@ -152,6 +152,8 @@ REG_set(ADDR_CODE_START, ul_int, start_code)
REG_set(ADDR_CURR_EIP, ul_int, kstk_eip)
REG_set(ADDR_CURR_ESP, ul_int, kstk_esp)
REG_set(ADDR_STACK_START, ul_int, start_stack)
REG_set(AUTOGRP_ID, s_int, autogrp_id)
REG_set(AUTOGRP_NICE, s_int, autogrp_nice)
STR_set(CGNAME, cgname)
STR_set(CGROUP, cgroup)
VEC_set(CGROUP_V, cgroup_v)
@ -390,6 +392,8 @@ srtDECL(noop) {
#define x_ogroup PROC_FILL_OGROUPS
#define x_ouser PROC_FILL_OUSERS
#define x_supgrp PROC_FILL_SUPGRP
// placed here so an 'f' prefix wouldn't make 'em first
#define z_autogrp PROC_FILLAUTOGRP
typedef void (*SET_t)(struct pids_info *, struct pids_result *, proc_t *);
typedef void (*FRE_t)(struct pids_result *);
@ -431,6 +435,8 @@ static struct {
{ RS(ADDR_CURR_EIP), f_stat, NULL, QS(ul_int), 0, TS(ul_int) },
{ RS(ADDR_CURR_ESP), f_stat, NULL, QS(ul_int), 0, TS(ul_int) },
{ RS(ADDR_STACK_START), f_stat, NULL, QS(ul_int), 0, TS(ul_int) },
{ RS(AUTOGRP_ID), z_autogrp, NULL, QS(s_int), 0, TS(s_int) },
{ RS(AUTOGRP_NICE), z_autogrp, NULL, QS(s_int), 0, TS(s_int) },
{ RS(CGNAME), x_cgroup, FF(str), QS(str), 0, TS(str) },
{ RS(CGROUP), x_cgroup, FF(str), QS(str), 0, TS(str) },
{ RS(CGROUP_V), v_cgroup, FF(strv), QS(strv), 0, TS(strv) },
@ -609,6 +615,7 @@ enum pids_item PIDS_logical_end = MAXTABLE(Item_table);
#undef x_ogroup
#undef x_ouser
#undef x_supgrp
#undef z_autogrp
// ___ History Support Private Functions ||||||||||||||||||||||||||||||||||||||

View File

@ -37,6 +37,8 @@ enum pids_item {
PIDS_ADDR_CURR_EIP, // ul_int stat: eip
PIDS_ADDR_CURR_ESP, // ul_int stat: esp
PIDS_ADDR_STACK_START, // ul_int stat: start_stack
PIDS_AUTOGRP_ID, // s_int autogroup
PIDS_AUTOGRP_NICE, // s_int autogroup
PIDS_CGNAME, // str derived from CGROUP ':name='
PIDS_CGROUP, // str cgroup
PIDS_CGROUP_V, // strv cgroup, as *str[]

View File

@ -1066,6 +1066,28 @@ static char *readlink_exe (const char *path){
}
// Provide the autogroup fields (or -1 if not available)
static void autogroup_fill (const char *path, proc_t *p) {
char buf[PROCPATHLEN], *str;
int fd, in;
p->autogrp_id = -1;
snprintf(buf, sizeof(buf), "%s/autogroup", path);
if ((fd = open(buf, O_RDONLY, 0)) != -1) {
in = read(fd, buf, sizeof(buf) - 1);
close(fd);
if (in > 0) {
buf[in] = '\0';
if ((str = strstr(buf, "-")))
p->autogrp_id = atoi(++str);
if ((str = strstr(buf, "nice")))
p->autogrp_nice = atoi(str + sizeof("nice"));
// above sizeof includes null, skips space ahead of #
}
}
}
///////////////////////////////////////////////////////////////////////
/* These are some nice GNU C expression subscope "inline" functions.
@ -1203,6 +1225,9 @@ static proc_t *simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
rc += 1;
}
if (flags & PROC_FILLAUTOGRP) // value the 2 autogroup fields
autogroup_fill(path, p);
if (rc == 0) return p;
errno = ENOMEM;
next_proc:
@ -1322,6 +1347,9 @@ static proc_t *simple_readtask(PROCTAB *restrict const PT, proc_t *restrict cons
if (flags & PROC_FILL_LUID)
t->luid = login_uid(path);
if (flags & PROC_FILLAUTOGRP) // value the 2 autogroup fields
autogroup_fill(path, t);
if (rc == 0) return t;
errno = ENOMEM;
next_task:

View File

@ -177,7 +177,9 @@ typedef struct proc_t {
*lxcname, // n/a lxc container name
*exe; // exe executable path + name
int
luid; // loginuid user id at login
luid, // loginuid user id at login
autogrp_id, // autogroup autogroup number (id)
autogrp_nice; // autogroup autogroup nice value
} proc_t;
// PROCTAB: data structure holding the persistent information readproc needs
@ -253,6 +255,9 @@ typedef struct PROCTAB {
#define PROC_FILL_OGROUPS ( 0x00400000 | PROC_FILLSTATUS ) // obtain other group names
#define PROC_FILL_SUPGRP ( 0x00800000 | PROC_FILLSTATUS ) // obtain supplementary group names
// and let's put new flags here ...
#define PROC_FILLAUTOGRP 0x01000000 // fill in proc_t autogroup stuff
// it helps to give app code a few spare bits
#define PROC_SPARE_1 0x10000000
#define PROC_SPARE_2 0x20000000