From 253ac7f709412a8699767bd70faeaf98e19614f0 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Wed, 22 Mar 2017 00:00:00 -0500 Subject: [PATCH] library: improve 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 2c86c4984a15c9ab912402838c6651f466a3d2ed --- proc/stat.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/proc/stat.c b/proc/stat.c index 6460c865..84ce7c5e 100644 --- a/proc/stat.c +++ b/proc/stat.c @@ -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);