library: improve <STAT> cpus offline/online management

When those standardized 'derived' TIC enumerators were
introduced, a problem with potential DELTA distortions
was also introduced when toggling cpus offline/online.

It has always been true that the 1st (summary) line in
/proc/stat will experience a decrease in total tics if
a new cpu is brought online. Such decreases are mostly
due to reductions in 'idle' and 'iowait' tics. Exactly
why such a counterintuitive phenomenon should occur is
a mystery, but this has been acknowledged in proc.txt.

A separate potential distortion arises with individual
cpus. And, here it extends to both bringing processors
online plus taking them offline too. When that happens
the order of the cpus array tracking is upset, placing
the 'new' values in some other processor's array slot.
But even if we were to occupy the same slot, the issue
regarding reductions in 'idle' & 'iowait' still apply.

In all cases, when a DELTA field was found to be minus
it was forced to zero via the 'TICsetH' macro. However
the 'derived' calculations are subject to new forms of
distortion with their own DELTA values. For example we
could find DELTA_SUM_USER + DELTA_SUM_SYSTEM exceeding
DELTA_SUM_TOTAL, an illogical/inappropriate condition.

So this commit moves former protections for individual
cpus to the stat_derive_unique() function and modifies
it to also extend protections to the 'derived' values.
In the process we now protect the cpu 'summary' counts
which were unfortunately previously overlooked (oops).

Reference(s):
. 'derived' types introduced
commit 2c86c4984a
This commit is contained in:
Jim Warner 2017-03-22 00:00:00 -05:00 committed by Craig Small
parent 3e5c950a5e
commit 253ac7f709

View File

@ -77,7 +77,6 @@ struct hist_sys {
struct hist_tic {
int id;
int id_sav;
int numa_node;
int count;
struct stat_jifs new;
@ -440,6 +439,14 @@ static inline int stat_derive_unique (
this->new.xidl = this->new.idle + this->new.iowait + this->new.stolen;
this->new.xbsy = this->new.xtot - this->new.xidl;
this->new.xsys = this->new.xbsy - this->new.xusr;
// don't distort deltas when cpus are taken offline or brought online
if (this->new.xtot < this->old.xtot
|| (this->new.xusr < this->old.xusr)
|| (this->new.xidl < this->old.xidl)
|| (this->new.xbsy < this->old.xbsy)
|| (this->new.xsys < this->old.xsys))
memcpy(&this->old, &this->new, sizeof(struct stat_jifs));
} // end: stat_derive_unique
@ -651,14 +658,9 @@ reap_em_again:
, &cpu_ptr->new.idle, &cpu_ptr->new.iowait, &cpu_ptr->new.irq
, &cpu_ptr->new.sirq, &cpu_ptr->new.stolen
, &cpu_ptr->new.guest, &cpu_ptr->new.gnice))) {
cpu_ptr->id_sav = -1;
break; // we must tolerate cpus taken offline
}
stat_derive_unique(cpu_ptr);
// don't distort deltas when a cpu is taken offline or brought online
if (cpu_ptr->id != cpu_ptr->id_sav)
memcpy(&cpu_ptr->old, &cpu_ptr->new, sizeof(struct stat_jifs));
cpu_ptr->id_sav = cpu_ptr->id;
++cpu_ptr;
++i;
} while (i < info->cpus.hist.n_alloc);