library: added important new functionality, <pids> api

This commit introduces some new capabilities available
in libproc-2 under the <PIDS> interface. Along the way
errors impacting some item values have been corrected.

The following summarizes the major changes being made.

1. The PIDS_TIME_START item was represented as seconds
since system boot but really held tics since boot. And
some programs properly divided it by Hertz to actually
yield seconds while others acted as if it already was.

So, now we have a new PIDS_TICS_BEGAN field and all of
the 'TIME' fields properly reflect seconds. With those
'TIME' fields, the type was changed to 'float/real' so
one could convert it back to tics without loss of some
centiseconds reflected in the Hertz guy (usually 100).

2. The boot_seconds was established in procps_pids_new
meaning it was fixed/unchanging. As a result, one item
(PIDS_TIME_ELAPSED) was rendered useless. So now, each
of the three retrieval functions establishes a current
boot_seconds well before the set functions are called.

3. Added a PIDS_UTILIZATION item that will provide the
CPU usage over the life of a process, as a percentage.

4. Added PIDS_TIME_ALL_C for symmetry with the similar
item called PIDS_TICS_ALL_C (which reflects raw tics).

5. That 'derived from' notation has been added to some
additional header items to reflect their true origins.

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2022-02-25 00:00:00 -06:00 committed by Craig Small
parent 854e85a50b
commit c69104b2b8
2 changed files with 49 additions and 21 deletions

View File

@ -90,8 +90,8 @@ struct pids_info {
unsigned pgs2k_shift; // to convert some proc vaules
unsigned oldflags; // the old library PROC_FILL flagss
PROCTAB *fetch_PT; // oldlib interface for 'select' & 'reap'
unsigned long hertz; // for TIME_ALL & TIME_ELAPSED calculations
unsigned long long boot_seconds; // for TIME_ELAPSED calculation
unsigned long hertz; // for the 'TIME' & 'UTILIZATION' calculations
float boot_seconds; // for TIME_ELAPSED & 'UTILIZATION' calculations
PROCTAB *get_PT; // oldlib interface for active 'get'
struct stacks_extent *get_ext; // for active 'get' (also within 'extents')
enum pids_fetch_type get_type; // last known type of 'get' request
@ -271,6 +271,7 @@ STR_set(SUPGROUPS, supgrp)
setDECL(TICS_ALL) { (void)I; R->result.ull_int = P->utime + P->stime; }
setDECL(TICS_ALL_C) { (void)I; R->result.ull_int = P->utime + P->stime + P->cutime + P->cstime; }
REG_set(TICS_ALL_DELTA, u_int, pcpu)
REG_set(TICS_BEGAN, ull_int, start_time)
REG_set(TICS_BLKIO, ull_int, blkio_tics)
REG_set(TICS_GUEST, ull_int, gtime)
setDECL(TICS_GUEST_C) { (void)I; R->result.ull_int = P->gtime + P->cgtime; }
@ -278,12 +279,14 @@ REG_set(TICS_SYSTEM, ull_int, stime)
setDECL(TICS_SYSTEM_C) { (void)I; R->result.ull_int = P->stime + P->cstime; }
REG_set(TICS_USER, ull_int, utime)
setDECL(TICS_USER_C) { (void)I; R->result.ull_int = P->utime + P->cutime; }
setDECL(TIME_ALL) { R->result.ull_int = (P->utime + P->stime) / I->hertz; }
setDECL(TIME_ELAPSED) { unsigned long long t = P->start_time / I->hertz; R->result.ull_int = I->boot_seconds >= t ? (I->boot_seconds - t) : 0; }
REG_set(TIME_START, ull_int, start_time)
setDECL(TIME_ALL) { R->result.real = ((float)P->utime + P->stime) / I->hertz; }
setDECL(TIME_ALL_C) { R->result.real = ((float)P->utime + P->stime + P->cutime + P->cstime) / I->hertz; }
setDECL(TIME_ELAPSED) { float t = (float)P->start_time / I->hertz; R->result.real = I->boot_seconds > t ? I->boot_seconds - t : 0; }
setDECL(TIME_START) { R->result.real = (float)P->start_time / I->hertz; }
REG_set(TTY, s_int, tty)
setDECL(TTY_NAME) { char buf[64]; freNAME(str)(R); dev_to_tty(buf, sizeof(buf), P->tty, P->tid, ABBREV_DEV); if (!(R->result.str = strdup(buf))) I->seterr = 1; }
setDECL(TTY_NUMBER) { char buf[64]; freNAME(str)(R); dev_to_tty(buf, sizeof(buf), P->tty, P->tid, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS); if (!(R->result.str = strdup(buf))) I->seterr = 1; }
setDECL(UTILIZATION) { float t; if (I->boot_seconds > 0) { t = I->boot_seconds - ((float)P->start_time / I->hertz); R->result.real = (float)P->utime + P->stime; R->result.real *= (100.0f / ((float)I->hertz * t)); }}
REG_set(VM_DATA, ul_int, vm_data)
REG_set(VM_EXE, ul_int, vm_exe)
REG_set(VM_LIB, ul_int, vm_lib)
@ -337,6 +340,8 @@ REG_srt(u_int)
REG_srt(ul_int)
REG_srt(ull_int)
REG_srt(real)
srtDECL(str) {
const struct pids_result *a = (*A)->head + P->offset;
const struct pids_result *b = (*B)->head + P->offset;
@ -554,6 +559,7 @@ static struct {
{ RS(TICS_ALL), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_ALL_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_ALL_DELTA), f_stat, NULL, QS(u_int), +1, TS(u_int) },
{ RS(TICS_BEGAN), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_BLKIO), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_GUEST), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_GUEST_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
@ -561,12 +567,14 @@ static struct {
{ RS(TICS_SYSTEM_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_USER), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TICS_USER_C), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TIME_ALL), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TIME_ELAPSED), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TIME_START), f_stat, NULL, QS(ull_int), 0, TS(ull_int) },
{ RS(TIME_ALL), f_stat, NULL, QS(real), 0, TS(real) },
{ RS(TIME_ALL_C), f_stat, NULL, QS(real), 0, TS(real) },
{ RS(TIME_ELAPSED), f_stat, NULL, QS(real), 0, TS(real) },
{ RS(TIME_START), f_stat, NULL, QS(real), 0, TS(real) },
{ RS(TTY), f_stat, NULL, QS(s_int), 0, TS(s_int) },
{ RS(TTY_NAME), f_stat, FF(str), QS(strvers), 0, TS(str) },
{ RS(TTY_NUMBER), f_stat, FF(str), QS(strvers), 0, TS(str) },
{ RS(UTILIZATION), f_stat, NULL, QS(real), 0, TS(real) },
{ RS(VM_DATA), f_status, NULL, QS(ul_int), 0, TS(ul_int) },
{ RS(VM_EXE), f_status, NULL, QS(ul_int), 0, TS(ul_int) },
{ RS(VM_LIB), f_status, NULL, QS(ul_int), 0, TS(ul_int) },
@ -1198,7 +1206,6 @@ PROCPS_EXPORT int procps_pids_new (
int numitems)
{
struct pids_info *p;
double uptime_secs;
int pgsz;
#ifdef ITEMTABLE_DEBUG
@ -1282,10 +1289,6 @@ PROCPS_EXPORT int procps_pids_new (
while (pgsz > 1024) { pgsz >>= 1; p->pgs2k_shift++; }
p->hertz = procps_hertz_get();
// in case 'fatal_proc_unmounted' wasn't called and /proc isn't mounted
if (0 >= procps_uptime(&uptime_secs, NULL))
p->boot_seconds = uptime_secs;
numa_init();
p->fetch.results.counts = &p->fetch.counts;
@ -1405,6 +1408,7 @@ PROCPS_EXPORT struct pids_stack *procps_pids_get (
struct pids_info *info,
enum pids_fetch_type which)
{
double up_secs;
errno = EINVAL;
if (info == NULL)
@ -1432,6 +1436,12 @@ fresh_start:
}
errno = 0;
/* when in a namespace with proc mounted subset=pid,
we will be restricted to process information only */
info->boot_seconds = 0;
if (0 >= procps_uptime(&up_secs, NULL))
info->boot_seconds = up_secs;
if (NULL == info->read_something(info->get_PT, &info->get_proc))
return NULL;
if (!pids_assign_results(info, info->get_ext->stacks[0], &info->get_proc))
@ -1451,6 +1461,7 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_reap (
struct pids_info *info,
enum pids_fetch_type which)
{
double up_secs;
int rc;
errno = EINVAL;
@ -1468,6 +1479,12 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_reap (
return NULL;
info->read_something = which ? readeither : readproc;
/* when in a namespace with proc mounted subset=pid,
we will be restricted to process information only */
info->boot_seconds = 0;
if (0 >= procps_uptime(&up_secs, NULL))
info->boot_seconds = up_secs;
rc = pids_stacks_fetch(info);
pids_oldproc_close(&info->fetch_PT);
@ -1541,6 +1558,7 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_select (
int numthese,
enum pids_select_type which)
{
double up_secs;
unsigned ids[FILL_ID_MAX + 1];
int rc;
@ -1566,6 +1584,12 @@ PROCPS_EXPORT struct pids_fetch *procps_pids_select (
return NULL;
info->read_something = (which & PIDS_FETCH_THREADS_TOO) ? readeither : readproc;
/* when in a namespace with proc mounted subset=pid,
we will be restricted to process information only */
info->boot_seconds = 0;
if (0 >= procps_uptime(&up_secs, NULL))
info->boot_seconds = up_secs;
rc = pids_stacks_fetch(info);
pids_oldproc_close(&info->fetch_PT);

View File

@ -51,7 +51,7 @@ enum pids_item {
PIDS_EXIT_SIGNAL, // s_int stat: exit_signal
PIDS_FLAGS, // ul_int stat: flags
PIDS_FLT_MAJ, // ul_int stat: maj_flt
PIDS_FLT_MAJ_C, // ul_int stat: maj_flt + cmaj_flt
PIDS_FLT_MAJ_C, // ul_int derived from stat: maj_flt + cmaj_flt
PIDS_FLT_MAJ_DELTA, // s_int derived from FLT_MAJ
PIDS_FLT_MIN, // ul_int stat: min_flt
PIDS_FLT_MIN_C, // ul_int stat: min_flt + cmin_flt
@ -154,19 +154,22 @@ enum pids_item {
PIDS_TICS_ALL, // ull_int stat: stime + utime
PIDS_TICS_ALL_C, // ull_int stat: stime + utime + cstime + cutime
PIDS_TICS_ALL_DELTA, // u_int derived from TICS_ALL
PIDS_TICS_BEGAN, // ull_int stat: start_time
PIDS_TICS_BLKIO, // ull_int stat: blkio_ticks
PIDS_TICS_GUEST, // ull_int stat: gtime
PIDS_TICS_GUEST_C, // ull_int stat: gtime + cgtime
PIDS_TICS_GUEST_C, // ull_int derived from stat: gtime + cgtime
PIDS_TICS_SYSTEM, // ull_int stat: stime
PIDS_TICS_SYSTEM_C, // ull_int stat: stime + cstime
PIDS_TICS_SYSTEM_C, // ull_int derived from stat: stime + cstime
PIDS_TICS_USER, // ull_int stat: utime
PIDS_TICS_USER_C, // ull_int stat: utime + cutime
PIDS_TIME_ALL, // ull_int derived from (utime + stime) / hertz
PIDS_TIME_ELAPSED, // ull_int derived from /proc/uptime - (starttime / hertz)
PIDS_TIME_START, // ull_int stat: start_time
PIDS_TICS_USER_C, // ull_int derived from stat: utime + cutime
PIDS_TIME_ALL, // real derived from (utime + stime) / hertz
PIDS_TIME_ALL_C, // real derived from (utime + stime + cutime + cstime) / hertz
PIDS_TIME_ELAPSED, // real derived from /proc/uptime - (starttime / hertz)
PIDS_TIME_START, // real derived from stat: start_time / hertz
PIDS_TTY, // s_int stat: tty_nr
PIDS_TTY_NAME, // str derived from TTY
PIDS_TTY_NUMBER, // str derived from TTY as str
PIDS_UTILIZATION, // real derived from TIME_ALL / TIME_ELAPSED, as percentage
PIDS_VM_DATA, // ul_int status: VmData
PIDS_VM_EXE, // ul_int status: VmExe
PIDS_VM_LIB, // ul_int status: VmLib
@ -178,7 +181,7 @@ enum pids_item {
PIDS_VM_SIZE, // ul_int status: VmSize
PIDS_VM_STACK, // ul_int status: VmStk
PIDS_VM_SWAP, // ul_int status: VmSwap
PIDS_VM_USED, // ul_int status: VmRSS + VmSwap
PIDS_VM_USED, // ul_int derived from status: VmRSS + VmSwap
PIDS_VSIZE_PGS, // ul_int stat: vsize
PIDS_WCHAN_NAME // str wchan
};
@ -211,6 +214,7 @@ struct pids_result {
unsigned long long ull_int;
char *str;
char **strv;
float real;
} result;
};