From 22e658297494e11ef92a81069b49a40420b8d824 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Fri, 25 Apr 2014 00:00:00 -0500 Subject: [PATCH] top: protect against distortion when system time reset If a system's time is adjusted backwards, then elapsed time could appear as negative. This yielded a negative %CPU value. Alternately if zeros were suppressed ('0') the result was a blank %CPU column. In both cases that distortion would last for one display cycle or until a user forced a display refresh via some keyboard input. The original recommendation was trading gettimeofday() for clock_gettime() using CLOCK_MONOTONIC. But on some systems that might not be possible, forcing the use of CLOCK_REALTIME instead. Not only would that complicate the build system, but it may leave us with minus %CPU. Another approach was to ensure that elapsed time could never be negative. Of course, this produced distortion of %CPU values but it would be proportionally correct. This wasn't dissimilar to a distortion already present should the time be adjusted forward or backward within any 'remaining' top delay intervals. These aberrations would be avoided with clock_gettime & CLOCK_MONOTONIC, but that is a less than ideal solution as noted above. This final solution, which originated down under, will simply rely on the /proc/uptime seconds, which will be immune to *any* tampering with the system clock. Thus, we now have a fix for the distortion we didn't know we suffered plus a negative %CPU that began this odyssey. Thanks to: sk.alvin.x@gmail.com, for the original effort jcapik@redhat.com, for a heads up on CLOCK_MONOTONIC csmall-procps@enc.com.au, for the best suggestion of all Reference(s): . original post/patch http://www.freelists.org/post/procps/PATCH-top-use-clock-gettime-instead-of-gettimeofday . heads up on CLOCK_MONOTONIC http://www.freelists.org/post/procps/PATCH-top-use-clock-gettime-instead-of-gettimeofday,2 . the final solution http://www.freelists.org/post/procps/PATCH-top-use-clock-gettime-instead-of-gettimeofday,11 Signed-off-by: Jim Warner --- top/top.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/top/top.c b/top/top.c index d7674956..cbcb1523 100644 --- a/top/top.c +++ b/top/top.c @@ -2518,17 +2518,14 @@ static void procs_hlp (proc_t *this) { HST_t *h; if (!this) { - static struct timeval oldtimev; - struct timeval timev; - struct timezone timez; + static double uptime_sav; + double uptime_cur; float et; void *v; - gettimeofday(&timev, &timez); - et = (timev.tv_sec - oldtimev.tv_sec) - + (float)(timev.tv_usec - oldtimev.tv_usec) / 1000000.0; - oldtimev.tv_sec = timev.tv_sec; - oldtimev.tv_usec = timev.tv_usec; + uptime(&uptime_cur, NULL); + et = uptime_cur - uptime_sav; + uptime_sav = uptime_cur; // if in Solaris mode, adjust our scaling for all cpus Frame_etscale = 100.0f / ((float)Hertz * (float)et * (Rc.mode_irixps ? 1 : smp_num_cpus));