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;