From 631e5d91f3c34374a095b8351235627545617de7 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Thu, 5 Aug 2021 00:00:00 -0500 Subject: [PATCH] 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//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 --- proc/pids.c | 7 +++++++ proc/pids.h | 2 ++ proc/readproc.c | 28 ++++++++++++++++++++++++++++ proc/readproc.h | 7 ++++++- 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/proc/pids.c b/proc/pids.c index 54fd3a37..fae340e0 100644 --- a/proc/pids.c +++ b/proc/pids.c @@ -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 |||||||||||||||||||||||||||||||||||||| diff --git a/proc/pids.h b/proc/pids.h index 529da137..a14a28d4 100644 --- a/proc/pids.h +++ b/proc/pids.h @@ -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[] diff --git a/proc/readproc.c b/proc/readproc.c index 84080036..03971c2f 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -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: diff --git a/proc/readproc.h b/proc/readproc.h index 2a8b1c0b..77db6967 100644 --- a/proc/readproc.h +++ b/proc/readproc.h @@ -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