On 2011 Nov 17 (Thu) at 21:18:24 -0200 (-0200), Christiano F. Haesbaert wrote:
> Moving this to tech@
> 
> Hi,
> 
> I was studying the scheduler code after watching tedu's talk, I'd like
> to expose this statistics to userland so that I can try playing with
> cache affinity in the future:
> 
> gimli:src: sysctl kern.schedstat                                              
>                                                                               
>           
> kern.schedstat.nmigrations=23744
> kern.schedstat.noidle=0
> kern.schedstat.stolen=9170
> kern.schedstat.choose=834843
> kern.schedstat.wasidle=808711
> kern.schedstat.nomigrations=2388
> 
> Opinions ?

I see no point in exporting this out. They are essentially pointless
knobs that people _will_ fiddle with without a clue.

This belongs in a developers tree IMO.

> 
> Index: sys/sys//sched.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/sched.h,v
> retrieving revision 1.29
> diff -d -u -p -w -r1.29 sched.h
> --- sys/sys//sched.h  7 Jul 2011 18:00:33 -0000       1.29
> +++ sys/sys//sched.h  12 Nov 2011 13:51:04 -0000
> @@ -75,6 +75,34 @@
>   * Posix defines a <sched.h> which may want to include <sys/sched.h>
>   */
>  
> +struct schedstat {
> +     u_int64_t scs_nmigrations;
> +     u_int64_t scs_noidle;
> +     u_int64_t scs_stolen;
> +
> +     u_int64_t scs_choose;
> +     u_int64_t scs_wasidle;
> +     u_int64_t scs_nomigrations;
> +};
> +
> +/* These sysctl names are only really used by sysctl(8) */
> +#define KERN_SCHEDSTAT_NMIGRATIONS   1
> +#define KERN_SCHEDSTAT_NOIDLE                2
> +#define KERN_SCHEDSTAT_STOLEN                3
> +#define KERN_SCHEDSTAT_CHOOSE                4
> +#define KERN_SCHEDSTAT_WASIDLE               5
> +#define KERN_SCHEDSTAT_NOMIGRATIONS  6
> +#define KERN_SCHEDSTAT_MAXID         7
> +
> +#define CTL_KERN_SCHEDSTAT_NAMES {           \
> +     { 0, 0 },                               \
> +     { "nmigrations", CTLTYPE_QUAD },        \
> +     { "noidle", CTLTYPE_QUAD },             \
> +     { "stolen", CTLTYPE_QUAD },             \
> +     { "choose", CTLTYPE_QUAD },             \
> +     { "wasidle", CTLTYPE_QUAD },            \
> +     { "nomigrations", CTLTYPE_QUAD }        \
> +}
>  /*
>   * CPU states.
>   * XXX Not really scheduler state, but no other good place to put
> Index: sys/sys//sysctl.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/sysctl.h,v
> retrieving revision 1.117
> diff -d -u -p -w -r1.117 sysctl.h
> --- sys/sys//sysctl.h 30 Aug 2011 01:09:29 -0000      1.117
> +++ sys/sys//sysctl.h 12 Nov 2011 13:40:45 -0000
> @@ -189,7 +189,8 @@ struct ctlname {
>  #define      KERN_CONSDEV            75      /* dev_t: console terminal 
> device */
>  #define      KERN_NETLIVELOCKS       76      /* int: number of network 
> livelocks */
>  #define      KERN_POOL_DEBUG         77      /* int: enable pool_debug */
> -#define      KERN_MAXID              78      /* number of valid kern ids */
> +#define KERN_SCHEDSTAT               78      /* struct: sched statistics */
> +#define      KERN_MAXID              79      /* number of valid kern ids */
>  
>  #define      CTL_KERN_NAMES { \
>       { 0, 0 }, \
> @@ -270,6 +271,7 @@ struct ctlname {
>       { "consdev", CTLTYPE_STRUCT }, \
>       { "netlivelocks", CTLTYPE_INT }, \
>       { "pool_debug", CTLTYPE_INT }, \
> +     { "schedstat", CTLTYPE_STRUCT }, \
>  }
>  
>  /*
> Index: sys/kern//kern_sched.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_sched.c,v
> retrieving revision 1.24
> diff -d -u -p -w -r1.24 kern_sched.c
> --- sys/kern//kern_sched.c    12 Oct 2011 18:30:09 -0000      1.24
> +++ sys/kern//kern_sched.c    12 Nov 2011 14:41:59 -0000
> @@ -35,6 +35,8 @@ void sched_kthreads_create(void *);
>  int sched_proc_to_cpu_cost(struct cpu_info *ci, struct proc *p);
>  struct proc *sched_steal_proc(struct cpu_info *);
>  
> +struct schedstat schedstat;
> +
>  /*
>   * To help choosing which cpu should run which process we keep track
>   * of cpus which are currently idle and which cpus have processes
> @@ -301,14 +303,6 @@ again:
>       return (p);     
>  }
>  
> -uint64_t sched_nmigrations;
> -uint64_t sched_noidle;
> -uint64_t sched_stolen;
> -
> -uint64_t sched_choose;
> -uint64_t sched_wasidle;
> -uint64_t sched_nomigrations;
> -
>  struct cpu_info *
>  sched_choosecpu_fork(struct proc *parent, int flags)
>  {
> @@ -374,7 +368,7 @@ sched_choosecpu(struct proc *p)
>       if (p->p_flag & P_CPUPEG)
>               return (p->p_cpu);
>  
> -     sched_choose++;
> +     schedstat.scs_choose++;
>  
>       /*
>        * Look at all cpus that are currently idle and have nothing queued.
> @@ -393,7 +387,7 @@ sched_choosecpu(struct proc *p)
>       if (cpuset_isset(&set, p->p_cpu) ||
>           (p->p_cpu == curcpu() && p->p_cpu->ci_schedstate.spc_nrun == 0 &&
>           curproc == p)) {
> -             sched_wasidle++;
> +             schedstat.scs_wasidle++;
>               return (p->p_cpu);
>       }
>  
> @@ -411,9 +405,9 @@ sched_choosecpu(struct proc *p)
>       }
>  
>       if (p->p_cpu != choice)
> -             sched_nmigrations++;
> +             schedstat.scs_nmigrations++;
>       else
> -             sched_nomigrations++;
> +             schedstat.scs_nomigrations++;
>  
>       return (choice);
>  }
> @@ -461,7 +455,7 @@ sched_steal_proc(struct cpu_info *self)
>       remrunqueue(best);
>       best->p_cpu = self;
>  
> -     sched_stolen++;
> +     schedstat.scs_stolen++;
>  
>       return (best);
>  }
> Index: sys/kern//kern_sysctl.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
> retrieving revision 1.208
> diff -d -u -p -w -r1.208 kern_sysctl.c
> --- sys/kern//kern_sysctl.c   18 Sep 2011 13:23:38 -0000      1.208
> +++ sys/kern//kern_sysctl.c   12 Nov 2011 15:04:52 -0000
> @@ -112,6 +112,7 @@ extern struct disklist_head disklist;
>  extern fixpt_t ccpu;
>  extern  long numvnodes;
>  extern u_int mcllivelocks;
> +extern struct schedstat schedstat;
>  
>  extern void nmbclust_update(void);
>  
> @@ -602,6 +603,9 @@ kern_sysctl(int *name, u_int namelen, vo
>                       pool_reclaim_all();
>               return (error);
>       }
> +     case KERN_SCHEDSTAT:
> +             return (sysctl_rdstruct(oldp, oldlenp, newp, &schedstat,
> +                 sizeof(struct schedstat)));
>       default:
>               return (EOPNOTSUPP);
>       }
> Index: sbin/sysctl//sysctl.c
> ===================================================================
> RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
> retrieving revision 1.180
> diff -d -u -p -w -r1.180 sysctl.c
> --- sbin/sysctl//sysctl.c     16 Sep 2011 20:52:48 -0000      1.180
> +++ sbin/sysctl//sysctl.c     12 Nov 2011 14:22:19 -0000
> @@ -119,6 +119,7 @@ struct ctlname username[] = CTL_USER_NAM
>  struct ctlname debugname[CTL_DEBUG_MAXID];
>  struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
>  struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
> +struct ctlname schedstatname[] = CTL_KERN_SCHEDSTAT_NAMES;
>  struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
>  struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
>  struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
> @@ -198,6 +199,7 @@ static int sysctl_vfsgen(char *, char **
>  int sysctl_bios(char *, char **, int *, int, int *);
>  int sysctl_swpenc(char *, char **, int *, int, int *);
>  int sysctl_forkstat(char *, char **, int *, int, int *);
> +int sysctl_schedstat(char *, char **, int *, int, int *);
>  int sysctl_tty(char *, char **, int *, int, int *);
>  int sysctl_nchstats(char *, char **, int *, int, int *);
>  int sysctl_malloc(char *, char **, int *, int, int *);
> @@ -450,6 +452,9 @@ parse(char *string, int flags)
>               case KERN_NETLIVELOCKS:
>                       special |= UNSIGNED;
>                       break;
> +             case KERN_SCHEDSTAT:
> +                     sysctl_schedstat(string, &bufp, mib, flags, &type);
> +                     return;
>               }
>               break;
>  
> @@ -1622,6 +1627,7 @@ struct list pipexlist = { pipexname, PIP
>  
>  struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
>  struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
> +struct list schedstatlist = { schedstatname, KERN_SCHEDSTAT_MAXID };
>  struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
>  struct list ttylist = { ttysname, KERN_TTY_MAXID };
>  struct list semlist = { semname, KERN_SEMINFO_MAXID };
> @@ -1891,6 +1897,62 @@ sysctl_malloc(char *string, char **bufpp
>               *typep = CTLTYPE_STRING;
>               return (3);
>       }
> +     return (-1);
> +}
> +
> +/*
> + * handle scheduler statistics
> + */
> +int
> +sysctl_schedstat(char *string, char **bufpp, int mib[], int flags, int 
> *typep)
> +{
> +     static struct schedstat scs;
> +     static int keepvalue = 0;
> +     int indx;
> +     size_t size;
> +
> +     if (*bufpp == NULL) {
> +             bzero(&scs, sizeof(scs));
> +             listall(string, &schedstatlist);
> +             return (-1);
> +     }
> +     if ((indx = findname(string, "third", bufpp, &schedstatlist)) == -1)
> +             return (-1);
> +     if (*bufpp != NULL) {
> +             warnx("fourth level name in %s is invalid", string);
> +             return (-1);
> +     }
> +     if (keepvalue == 0) {
> +             size = sizeof(scs);
> +             if (sysctl(mib, 2, &scs, &size, NULL, 0) < 0)
> +                     return (-1);
> +             keepvalue = 1;
> +     }
> +     if (!nflag)
> +             (void)printf("%s%s", string, equ);
> +     switch (indx)   {
> +     case KERN_SCHEDSTAT_NMIGRATIONS:
> +             (void)printf("%llu\n", scs.scs_nmigrations);
> +             break;
> +     case KERN_SCHEDSTAT_NOIDLE:
> +             (void)printf("%llu\n", scs.scs_noidle);
> +             break;
> +     case KERN_SCHEDSTAT_STOLEN:
> +             (void)printf("%llu\n", scs.scs_stolen);
> +             break;
> +     case KERN_SCHEDSTAT_CHOOSE:
> +             (void)printf("%llu\n", scs.scs_choose);
> +             break;
> +     case KERN_SCHEDSTAT_WASIDLE:
> +             (void)printf("%llu\n", scs.scs_wasidle);
> +             break;
> +     case KERN_SCHEDSTAT_NOMIGRATIONS:
> +             (void)printf("%llu\n", scs.scs_nomigrations);
> +             break;
> +     default:
> +             break;
> +     }
> +     
>       return (-1);
>  }

Reply via email to