On 01/07/21(Thu) 13:53, Anindya Mukherjee wrote:
> 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!

I wonder if we shouldn't use uint64_t for those and embrace the ABI
break, that would at least simplify the kernel side and remove a
truncation.

Do you have an idea of the different consumers of the "struct uvmexp"
apart from systat(1)?  What is the impact in userland & ports of such
change?

> 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