From be5c9bf8edd6e653dc889b59d54f26a9013a6965 Mon Sep 17 00:00:00 2001 From: cheloha Date: Sun, 4 Dec 2022 18:01:57 +0000 Subject: [PATCH] systat(1): vmstat: measure elapsed time with clock_gettime(2) instead of ticks The vmstat view in systat(1) should not use statclock() ticks to count elapsed time. First, ticks are low resolution. Second, the statclock is sometimes randomized, so each tick is not necessarily of equal length. Third, we're counting ticks from every CPU on the system, so every rate in the view is divided by the number of CPUs. For example, on an amd64 system with 8 CPUs you currently see: 200 clock ... when the true clock interrupt rate on that system is 1600. Instead, measure elapsed time with clock_gettime(2). Use CLOCK_UPTIME here so we exclude time when the system is suspended. With this change we no longer need "stathz" or "hertz". We can also get rid of the anachronistic secondary clock failure test. Prompted by dlg@ and jmatthew@. deraadt@ says this has been in snaps since 2022-11-21; no complaints. Link: https://marc.info/?l=openbsd-tech&m=166898960831136&w=2 ok dlg@ deraadt@ --- usr.bin/systat/main.c | 5 ++--- usr.bin/systat/systat.h | 4 ++-- usr.bin/systat/vmstat.c | 27 +++++++++------------------ 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index 7a4225cc490..ce7851d8bd2 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.76 2021/07/12 15:09:20 beck Exp $ */ +/* $OpenBSD: main.c,v 1.77 2022/12/04 18:01:57 cheloha Exp $ */ /* * Copyright (c) 2001, 2007 Can Erkin Acar * Copyright (c) 2001 Daniel Hartmeier @@ -65,7 +65,7 @@ double avenrun[3]; double naptime = 5.0; int verbose = 1; /* to report kvm read errs */ int nflag = 1; -int ut, hz, stathz; +int ut, hz; char hostname[HOST_NAME_MAX+1]; WINDOW *wnd; int CMDLINE; @@ -414,7 +414,6 @@ gethz(void) mib[1] = KERN_CLOCKRATE; if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) return; - stathz = cinf.stathz; hz = cinf.hz; } diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h index e7d20070541..776be5a2d51 100644 --- a/usr.bin/systat/systat.h +++ b/usr.bin/systat/systat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systat.h,v 1.24 2021/01/18 00:49:09 mortimer Exp $ */ +/* $OpenBSD: systat.h,v 1.25 2022/12/04 18:01:57 cheloha Exp $ */ /* $NetBSD: systat.h,v 1.2 1995/01/20 08:52:14 jtc Exp $ */ /*- @@ -58,7 +58,7 @@ extern kvm_t *kd; extern long ntext; extern int *dk_select; extern int dk_ndrive; -extern int hz, stathz; +extern int hz; extern double naptime; extern size_t nhosts; extern size_t nports; diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c index ce22f73d9c8..9cb43279199 100644 --- a/usr.bin/systat/vmstat.c +++ b/usr.bin/systat/vmstat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmstat.c,v 1.94 2022/02/22 17:35:01 deraadt Exp $ */ +/* $OpenBSD: vmstat.c,v 1.95 2022/12/04 18:01:57 cheloha Exp $ */ /* $NetBSD: vmstat.c,v 1.5 1996/05/10 23:16:40 thorpej Exp $ */ /*- @@ -98,7 +98,6 @@ int select_vm(void); int vm_keyboard_callback(int); static time_t t; -static float hertz; static int nintr; static long *intrloc; static char **intrname; @@ -170,7 +169,6 @@ initvmstat(void) int mib[4], i; size_t size; - hertz = stathz; if (!dkinit(1)) return(0); @@ -323,7 +321,6 @@ labelkre(void) Y(fld); \ putint((int)((float)s.fld/etime + 0.5), l, c, w); \ } while (0) -#define MAXFAIL 5 static char cpuchar[] = { '|', '@', '=', '>', ' ' }; static char cpuorder[] = { CP_INTR, CP_SPIN, CP_SYS, CP_USER, CP_IDLE }; @@ -331,33 +328,27 @@ static char cpuorder[] = { CP_INTR, CP_SPIN, CP_SYS, CP_USER, CP_IDLE }; void showkre(void) { + static struct timespec prev; + struct timespec elapsed, now; float f1, f2; int psiz; u_int64_t inttotal, intcnt; int i, l, c; - static int failcnt = 0, first_run = 0; + static int first_run = 0; double etime; + clock_gettime(CLOCK_UPTIME, &now); + timespecsub(&now, &prev, &elapsed); + prev = now; if (state == TIME) { if (!first_run) { first_run = 1; return; } } - etime = 0; - for (i = 0; i < CPUSTATES; i++) { + etime = elapsed.tv_sec + elapsed.tv_nsec / 1000000000.0; + for (i = 0; i < CPUSTATES; i++) X(cpustats.cs_time); - etime += s.cpustats.cs_time[i]; - } - if (etime < 5.0) { /* < 5 ticks - ignore this trash */ - if (failcnt++ >= MAXFAIL) { - error("The alternate system clock has died!"); - failcnt = 0; - } - return; - } - failcnt = 0; - etime /= hertz; inttotal = 0; for (i = 0; i < nintr; i++) { t = intcnt = s.intrcnt[i]; -- 2.20.1