82 lines
3.0 KiB
Diff
82 lines
3.0 KiB
Diff
From 22e658297494e11ef92a81069b49a40420b8d824 Mon Sep 17 00:00:00 2001
|
|
From: Jim Warner <james.warner@comcast.net>
|
|
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 <james.warner@comcast.net>
|
|
---
|
|
top/top.c | 13 +++++--------
|
|
1 file changed, 5 insertions(+), 8 deletions(-)
|
|
|
|
diff --git top/top.c top/top.c
|
|
index d767495..cbcb152 100644
|
|
--- top/top.c
|
|
+++ 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));
|
|
--
|
|
1.7.9.2
|
|
|