library: improve/standardize one interface, <STAT> api

This commit represents a complete redesign of the stat
interface. Gone are the confusing 8 separate accessors
along with their 2 additional read functions. In their
place we have just 3 accessors, with no read required.

That old interface also suffered an inflexibility with
respect to structures.  Now we deal with an unchanging
standard 'result' struct enabling future changes where
the binary interface will no longer need to be broken.

And gone is that former unnecessary typedef, used when
dealing with jiffies. Now the standard C type is used.

Our new API also adds some brand new functionality. If
a caller plans to employ successive 'select' or 'reap'
invocations, then delta values are available (which is
actually only what that top program is interested in).

At some future point a 'sort' function could be easily
introduced to complement the 'reap' function. However,
I saw no need for it at present and so it was omitted.

There were several design decisions which everyone may
not agree with. In support I'll offer these rationals:

. The 'get' function returns a signed long long result
which means a potential loss of some significance. But
I felt the ability to distinguish actual errors (minus
values) from true zero results were worth such a risk.

. The DELTA item enumerators were also made signed and
smaller than their parents. And they are intentionally
grouped as last so as to emphasize those distinctions.

. The SYS type items were excluded from the new 'reap'
function. It would not make sense to duplicate them in
each results stack. They're limited to 'get'/'select'.

. By the same token, some items (DELTA, etc.) will not
be allowed under that 'get' routine. That function was
already open to significant internal overhead (through
subsequent calls like in vmstat.c). That is why it has
been limited via 1 second between reads of /proc/stat.

Lastly, when we finally get around to documenting this
interface there's a real potential toe stubber when it
comes to the numa node portion. The libnuma.so doesn't
really provide any means to retrieve the active nodes.
Thus, any total reported by <stat> is just the highest
node number plus one, as reported by the numa library.

Any unused/inactive nodes are identified through these
. PROCPS_STAT_TIC_ID shows as PROCPS_STAT_NODE_INVALID

By the same token after the STAT_REAP_CPUS_ONLY 'reap'
. PROCPS_STAT_TIC_NUMA_NODE = PROCPS_STAT_NODE_INVALID

Reference(s):
http://www.freelists.org/post/procps/newlib-stat-interface

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2016-05-06 00:00:00 -05:00 committed by Craig Small
parent 5854f2d956
commit abc71a46ad
3 changed files with 959 additions and 535 deletions

View File

@ -53,18 +53,11 @@ global:
procps_slabnode_stacks_sort; procps_slabnode_stacks_sort;
procps_slabnode_stacks_alloc; procps_slabnode_stacks_alloc;
procps_stat_new; procps_stat_new;
procps_stat_read;
procps_stat_read_jiffs;
procps_stat_ref; procps_stat_ref;
procps_stat_unref; procps_stat_unref;
procps_stat_cpu_get; procps_stat_get;
procps_stat_cpu_getstack; procps_stat_reap;
procps_stat_jiffs_get; procps_stat_select;
procps_stat_jiffs_hist_get;
procps_stat_jiffs_fill;
procps_stat_jiffs_hist_fill;
procps_stat_sys_get;
procps_stat_sys_getstack;
procps_uptime; procps_uptime;
procps_uptime_sprint; procps_uptime_sprint;
procps_uptime_sprint_short; procps_uptime_sprint_short;

File diff suppressed because it is too large Load Diff

View File

@ -22,96 +22,105 @@
__BEGIN_DECLS __BEGIN_DECLS
enum procps_cpu_item { enum stat_item {
PROCPS_CPU_USER, // jiff PROCPS_STAT_noop, // ( never altered )
PROCPS_CPU_NICE, // jiff PROCPS_STAT_extra, // ( reset to zero )
PROCPS_CPU_SYSTEM, // jiff
PROCPS_CPU_IDLE, // jiff PROCPS_STAT_TIC_ID, // s_int
PROCPS_CPU_IOWAIT, // jiff PROCPS_STAT_TIC_NUMA_NODE, // s_int
PROCPS_CPU_IRQ, // jiff PROCPS_STAT_TIC_USER, // ull_int
PROCPS_CPU_SIRQ, // jiff PROCPS_STAT_TIC_NICE, // ull_int
PROCPS_CPU_STOLEN, // jiff PROCPS_STAT_TIC_SYSTEM, // ull_int
PROCPS_CPU_GUEST, // jiff PROCPS_STAT_TIC_IDLE, // ull_int
PROCPS_CPU_GNICE, // jiff PROCPS_STAT_TIC_IOWAIT, // ull_int
PROCPS_CPU_noop, // n/a PROCPS_STAT_TIC_IRQ, // ull_int
PROCPS_CPU_stack_end // n/a PROCPS_STAT_TIC_SOFTIRQ, // ull_int
PROCPS_STAT_TIC_STOLEN, // ull_int
PROCPS_STAT_TIC_GUEST, // ull_int
PROCPS_STAT_TIC_GUEST_NICE, // ull_int
PROCPS_STAT_TIC_DELTA_USER, // sl_int
PROCPS_STAT_TIC_DELTA_NICE, // sl_int
PROCPS_STAT_TIC_DELTA_SYSTEM, // sl_int
PROCPS_STAT_TIC_DELTA_IDLE, // sl_int
PROCPS_STAT_TIC_DELTA_IOWAIT, // sl_int
PROCPS_STAT_TIC_DELTA_IRQ, // sl_int
PROCPS_STAT_TIC_DELTA_SOFTIRQ, // sl_int
PROCPS_STAT_TIC_DELTA_STOLEN, // sl_int
PROCPS_STAT_TIC_DELTA_GUEST, // sl_int
PROCPS_STAT_TIC_DELTA_GUEST_NICE, // sl_int
PROCPS_STAT_SYS_CTX_SWITCHES, // ul_int
PROCPS_STAT_SYS_INTERRUPTS, // ul_int
PROCPS_STAT_SYS_PROC_BLOCKED, // ul_int
PROCPS_STAT_SYS_PROC_CREATED, // ul_int
PROCPS_STAT_SYS_PROC_RUNNING, // ul_int
PROCPS_STAT_SYS_TIME_OF_BOOT, // ul_int
PROCPS_STAT_SYS_DELTA_CTX_SWITCHES, // s_int
PROCPS_STAT_SYS_DELTA_INTERRUPTS, // s_int
PROCPS_STAT_SYS_DELTA_PROC_BLOCKED, // s_int
PROCPS_STAT_SYS_DELTA_PROC_CREATED, // s_int
PROCPS_STAT_SYS_DELTA_PROC_RUNNING, // s_int
}; };
enum procps_stat_item { enum stat_reap_type {
PROCPS_STAT_INTR, // u_int STAT_REAP_CPUS_ONLY,
PROCPS_STAT_CTXT, // u_int STAT_REAP_CPUS_AND_NODES
PROCPS_STAT_BTIME, // u_int
PROCPS_STAT_PROCS, // u_int
PROCPS_STAT_PROCS_BLK, // u_int
PROCPS_STAT_PROCS_RUN, // u_int
PROCPS_STAT_noop, // n/a
PROCPS_STAT_stack_end // n/a
};
typedef unsigned long long jiff;
struct procps_jiffs {
jiff user, nice, system, idle, iowait, irq, sirq, stolen, guest, gnice;
};
struct procps_jiffs_hist {
struct procps_jiffs new;
struct procps_jiffs old;
int id;
}; };
struct stat_result { struct stat_result {
int item; enum stat_item item;
union { union {
unsigned int u_int; int s_int;
jiff jiff; long sl_int;
unsigned long ul_int;
unsigned long long ull_int;
} result; } result;
}; };
struct procps_stat; struct stat_stack {
struct stat_result *head;
};
int procps_stat_new (struct procps_stat **info); struct stat_reap {
int procps_stat_read (struct procps_stat *info, const int cpu_only); int total;
int procps_stat_read_jiffs (struct procps_stat *info); struct stat_stack **stacks;
};
int procps_stat_ref (struct procps_stat *info); struct stat_reaped {
int procps_stat_unref (struct procps_stat **info); struct stat_stack *summary;
struct stat_reap *cpus;
struct stat_reap *nodes;
};
jiff procps_stat_cpu_get (
struct procps_stat *info,
enum procps_cpu_item item);
int procps_stat_cpu_getstack ( #define PROCPS_STAT_SUMMARY_ID -11111
struct procps_stat *info, #define PROCPS_STAT_NODE_INVALID -22222
struct stat_result *these);
int procps_stat_jiffs_get ( #define PROCPS_STAT_VAL(rel_enum,type,stack) \
struct procps_stat *info, stack -> head [ rel_enum ] . result . type
struct procps_jiffs *dest,
int which);
int procps_stat_jiffs_hist_get (
struct procps_stat *info,
struct procps_jiffs_hist *dest,
int which);
int procps_stat_jiffs_fill ( struct procps_statinfo;
struct procps_stat *info,
struct procps_jiffs *dests,
int maxdests);
int procps_stat_jiffs_hist_fill ( int procps_stat_new (struct procps_statinfo **info);
struct procps_stat *info, int procps_stat_ref (struct procps_statinfo *info);
struct procps_jiffs_hist *dests, int procps_stat_unref (struct procps_statinfo **info);
int maxdests);
unsigned int procps_stat_sys_get ( signed long long procps_stat_get (
struct procps_stat *info, struct procps_statinfo *info,
enum procps_stat_item item); enum stat_item item);
int procps_stat_sys_getstack ( struct stat_stack *procps_stat_select (
struct procps_stat *info, struct procps_statinfo *info,
struct stat_result *these); enum stat_item *items,
int numitems);
struct stat_reaped *procps_stat_reap (
struct procps_statinfo *info,
enum stat_reap_type what,
enum stat_item *items,
int numitems);
__END_DECLS __END_DECLS
#endif #endif