Hi,

I noticed that if I leave the system running for more than about a month, some
of the counters in the uvm view of systat(1) overflow and become negative. This
is because the members of struct uvmexp in sys/uvm/uvmexp.h are ints. The
kernel's internal counters are of course uint64_t so they don't overflow. It
only happens during the uvm_sysctl(9) call which casts the numbers to integers.
The function is uvmexp_read.

In the attached diff I took the path of least resistance and promoted some of
the counters to unsigned int. Ideally I would have liked to use int64_t or even
uint64_t, but I hit an issue in some of the architecture dependent code. An
example is:
/usr/src/sys/arch/alpha/alpha/trap.c:536 atomic_add_int(&uvmexp.syscalls, 1);
In other places the ++ operator is used to increment the counters and the 64 bit
types can be used.

I am not completely sure this is the best way to proceed, but even if this diff
is horrifying, I'd appreciate some feedback and advice, thanks!

Anindya

Index: sys/uvm/uvm_meter.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_meter.c,v
retrieving revision 1.42
diff -u -p -r1.42 uvm_meter.c
--- sys/uvm/uvm_meter.c 28 Dec 2020 14:01:23 -0000      1.42
+++ sys/uvm/uvm_meter.c 28 Jun 2021 05:24:56 -0000
@@ -329,7 +329,7 @@ uvmexp_read(struct uvmexp *uexp)
                counters_read(uvmexp_counters, counters, exp_ncounters);
 
                /* stat counters */
-               uexp->faults = (int)counters[faults];
+               uexp->faults = (unsigned int)counters[faults];
                uexp->pageins = (int)counters[pageins];
 
                /* fault subcounters */
@@ -379,10 +379,10 @@ uvmexp_print(int (*pr)(const char *, ...
        (*pr)("  freemin=%d, free-target=%d, inactive-target=%d, "
            "wired-max=%d\n", uexp.freemin, uexp.freetarg, uexp.inactarg,
            uexp.wiredmax);
-       (*pr)("  faults=%d, traps=%d, intrs=%d, ctxswitch=%d fpuswitch=%d\n",
+       (*pr)("  faults=%u, traps=%u, intrs=%u, ctxswitch=%u fpuswitch=%d\n",
            uexp.faults, uexp.traps, uexp.intrs, uexp.swtch,
            uexp.fpswtch);
-       (*pr)("  softint=%d, syscalls=%d, kmapent=%d\n",
+       (*pr)("  softint=%u, syscalls=%u, kmapent=%d\n",
            uexp.softs, uexp.syscalls, uexp.kmapent);
 
        (*pr)("  fault counts:\n");
Index: sys/uvm/uvmexp.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvmexp.h,v
retrieving revision 1.9
diff -u -p -r1.9 uvmexp.h
--- sys/uvm/uvmexp.h    4 Mar 2021 09:00:03 -0000       1.9
+++ sys/uvm/uvmexp.h    28 Jun 2021 05:24:56 -0000
@@ -90,12 +90,12 @@ struct uvmexp {
        int unused06;   /* formerly nfreeanon */
 
        /* stat counters */
-       int faults;             /* page fault count */
-       int traps;              /* trap count */
-       int intrs;              /* interrupt count */
-       int swtch;              /* context switch count */
-       int softs;              /* software interrupt count */
-       int syscalls;           /* system calls */
+       unsigned int faults;    /* page fault count */
+       unsigned int traps;     /* trap count */
+       unsigned int intrs;     /* interrupt count */
+       unsigned int swtch;     /* context switch count */
+       unsigned int softs;     /* software interrupt count */
+       unsigned int syscalls;  /* system calls */
        int pageins;            /* pagein operation count */
                                /* pageouts are in pdpageouts below */
        int unused07;           /* formerly obsolete_swapins */
Index: usr.bin/systat/uvm.c
===================================================================
RCS file: /cvs/src/usr.bin/systat/uvm.c,v
retrieving revision 1.5
diff -u -p -r1.5 uvm.c
--- usr.bin/systat/uvm.c        28 Jun 2019 13:35:04 -0000      1.5
+++ usr.bin/systat/uvm.c        28 Jun 2021 05:24:57 -0000
@@ -37,22 +37,23 @@ void print_uvm(void);
 int  read_uvm(void);
 int  select_uvm(void);
 
-void print_uvmexp_field(field_def *, field_def *, int *, int *, const char *);
+void print_uvmexp_field(field_def *, field_def *, unsigned int *,
+    unsigned int *, const char *);
 void print_uvmexp_line(int);
 
 struct uvmexp uvmexp;
 struct uvmexp last_uvmexp;
 
 struct uvmline {
-       int     *v1;
-       int     *ov1;
-       char    *n1;
-       int     *v2;
-       int     *ov2;
-       char    *n2;
-       int     *v3;
-       int     *ov3;
-       char    *n3;
+       unsigned int    *v1;
+       unsigned int    *ov1;
+       char            *n1;
+       unsigned int    *v2;
+       unsigned int    *ov2;
+       char            *n2;
+       unsigned int    *v3;
+       unsigned int    *ov3;
+       char            *n3;
 };
 
 struct uvmline uvmline[] = {
@@ -214,8 +215,8 @@ read_uvm(void)
 }
 
 void
-print_uvmexp_field(field_def *fvalue, field_def *fname, int *new, int *old,
-    const char *name)
+print_uvmexp_field(field_def *fvalue, field_def *fname, unsigned int *new,
+    unsigned int *old, const char *name)
 {
        char *uppername;
        size_t len, i;

Reply via email to