Hi, Using nanosleep(2) to print the stats periodically causes the period to drift. If you use setitimer(2) it won't drift.
ok? Index: kstat.c =================================================================== RCS file: /cvs/src/usr.bin/kstat/kstat.c,v retrieving revision 1.6 diff -u -p -r1.6 kstat.c --- kstat.c 13 Aug 2020 12:37:16 -0000 1.6 +++ kstat.c 17 Sep 2020 23:24:36 -0000 @@ -15,6 +15,7 @@ */ #include <ctype.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -27,6 +28,7 @@ #include <err.h> #include <vis.h> +#include <sys/time.h> #include <sys/tree.h> #include <sys/ioctl.h> #include <sys/time.h> @@ -104,6 +106,7 @@ kstat_cmp(const struct kstat_entry *ea, RBT_PROTOTYPE(kstat_tree, kstat_entry, entry, kstat_cmp); RBT_GENERATE(kstat_tree, kstat_entry, entry, kstat_cmp); +static void handle_alrm(int); static struct kstat_filter * kstat_filter_parse(char *); static int kstat_filter_entry(struct kstat_filters *, @@ -130,20 +133,23 @@ main(int argc, char *argv[]) { struct kstat_filters kfs = TAILQ_HEAD_INITIALIZER(kfs); struct kstat_tree kt = RBT_INITIALIZER(); + struct itimerval itv; + time_t interval; unsigned int version; + sigset_t empty; int fd; const char *errstr; int ch; - struct timespec interval = { 0, 0 }; int i; + interval = 0; + while ((ch = getopt(argc, argv, "w:")) != -1) { switch (ch) { case 'w': - interval.tv_sec = strtonum(optarg, 1, 100000000, - &errstr); + interval = strtonum(optarg, 1, 100000000, &errstr); if (errstr != NULL) - errx(1, "wait %s: %s", optarg, errstr); + errx(1, "wait is %s: %s", optarg, errstr); break; default: usage(); @@ -168,17 +174,31 @@ main(int argc, char *argv[]) kstat_list(&kt, fd, version, &kfs); kstat_print(&kt); - if (interval.tv_sec == 0) + if (interval == 0) return (0); - for (;;) { - nanosleep(&interval, NULL); + signal(SIGALRM, handle_alrm); + sigemptyset(&empty); + + itv.it_value.tv_sec = interval; + itv.it_value.tv_usec = 0; + itv.it_interval = itv.it_value; + if (setitimer(ITIMER_REAL, &itv, NULL) == -1) + err(1, "setitimer"); + for (;;) { + sigsuspend(&empty); kstat_read(&kt, fd); kstat_print(&kt); } return (0); +} + +static void +handle_alrm(int signo) +{ + return; } static struct kstat_filter *