components/top/patches/05.stolen_time.patch
author akshay.kale@oracle.com <akshay.kale@oracle.com>
Fri, 14 Oct 2016 13:13:27 -0700
changeset 7112 dab9beb5bc49
parent 2192 31cdcfd53b4b
permissions -rw-r--r--
24843178 Method of choosing ofports need to be improved in OVS

#
# This patch was included to address:
# 16988337 Stolen time should be visible in output of top(1)
#
# Upstream BugDB: https://sourceforge.net/p/unixtop/bugs/
# Upstream BugURL: https://sourceforge.net/p/unixtop/bugs/55/
#
--- a/machine/m_sunos5.c	Fri May 24 15:39:52 2013 +0200
+++ b/machine/m_sunos5.c	Wed Nov 05 13:48:21 2014 +0100
@@ -7,8 +7,7 @@
  * This is the machine-dependent module for SunOS 5.x (Solaris 2).
  * There is some support for MP architectures.
  * This makes top work on all revisions of SunOS 5 from 5.0
- * through 5.9 (otherwise known as Solaris 9).  It has not been
- * tested on SunOS 5.10.
+ * through 5.11 (otherwise known as Solaris 11).
  *
  * AUTHORS:      Torsten Kasch 		<[email protected]>
  *               Robert Boucher		<[email protected]>
@@ -18,6 +17,7 @@
  *               Petri Kutvonen         <[email protected]>
  *	         Casper Dik             <[email protected]>
  *               Tim Pugh               <[email protected]>
+ *               Stanislav Kozina       <[email protected]>
  */
 
 #define _KMEMUSER
@@ -112,6 +112,11 @@
 #define USE_KSTAT
 #endif
 #ifdef USE_KSTAT
+
+# if OSREV >= 510
+#  define USE_NAMED_CPU_KSTAT
+# endif
+
 #include <kstat.h>
 /*
  * Some kstats are fixed at 32 bits, these will be specified as ui32; some
@@ -235,18 +240,35 @@
  */
 struct cpustats
 {
-    unsigned int states[CPUSTATES];
-    uint_t pswitch;
-    uint_t trap;
-    uint_t intr;
-    uint_t syscall;
-    uint_t sysfork;
-    uint_t sysvfork;
-    uint_t pfault;
-    uint_t pgin;
-    uint_t pgout;
+    uint64_t states[CPUSTATES];
+    uint64_t pswitch;
+    uint64_t trap;
+    uint64_t intr;
+    uint64_t syscall;
+    uint64_t sysfork;
+    uint64_t sysvfork;
+    uint64_t pfault;
+    uint64_t pgin;
+    uint64_t pgout;
 };
 
+#ifdef USE_NAMED_CPU_KSTAT
+static int cpu_ticks_idle_index = -1;
+static int cpu_ticks_user_index = -1;
+static int cpu_ticks_kernel_index = -1;
+static int cpu_ticks_stolen_index = -1;
+static int pswitch_index = -1;
+static int trap_index = -1;
+static int intr_index = -1;
+static int syscall_index = -1;
+static int sysfork_index = -1;
+static int sysvfork_index = -1;
+static int hat_fault_index = -1;
+static int as_fault_index = -1;
+static int pgin_index = -1;
+static int pgout_index = -1;
+#endif
+
 /*
  * GCC assumes that all doubles are aligned.  Unfortunately it
  * doesn't round up the structure size to be a multiple of 8.
@@ -280,9 +302,12 @@
 
 int cpu_states[CPUSTATES];
 char *cpustatenames[] =
-{"idle", "user", "kernel", "iowait", "swap", NULL};
-#define CPUSTATE_IOWAIT 3
-#define CPUSTATE_SWAP   4
+{"idle", "user", "kernel", "stolen", "swap", NULL};
+#define CPUSTATE_IDLE     0
+#define CPUSTATE_USER     1
+#define CPUSTATE_KERNEL   2
+#define CPUSTATE_STOLEN   3
+#define CPUSTATE_SWAP     4
 
 
 /* these are for detailing the memory statistics */
@@ -773,36 +798,33 @@
 }
 
 /*
- * int kstat_safe_namematch(int num, kstat_t *ksp, char *name, void *buf)
- *
- * Safe scan of kstat chain for names starting with "name".  Matches
- * are copied in to "ksp", and kstat_read is called on each match using
- * "buf" as a buffer of length "size".  The actual number of records
- * found is returned.  Up to "num" kstats are copied in to "ksp", but
- * no more.  If any kstat_read indicates that the chain has changed, then
- * the whole process is restarted.
+ * Safe scan of kstat chain for names starting with "module", "name" or
+ * "class". Every condition is ignored if set to empty string.
+ * kstat_read is called on each match. The actual number of records
+ * found is returned.  If any kstat_read indicates that the chain has changed,
+ * then the whole process is restarted.
  */
 
 int
-kstat_safe_namematch(int num, kstat_t **ksparg, char *name, void *buf, int size)
-
+kstat_safe_lookup(int num, kstat_t **ksparg, char *class, char *module,
+		     char *name)
 {
     kstat_t *ks;
     kstat_t **ksp;
     kid_t new_kcid;
-    int namelen;
+    int classlen, modlen, namelen;
     int count;
     int changed;
-    char *cbuf;
 
-    dprintf("kstat_safe_namematch(%d, %08x, %s, %08x, %d)\n",
-	    num, ksparg, name, buf, size);
+    dprintf("kstat_safe_lookup(%d, %08x, %s, %s, %s)\n",
+	num, ksparg, class, module, name);
 
+    classlen = strlen(class);
+    modlen = strlen(module);
     namelen = strlen(name);
 
     do {
 	/* initialize before the scan */
-	cbuf = (char *)buf;
 	ksp = ksparg;
 	count = 0;
 	changed = 0;
@@ -810,18 +832,23 @@
 	/* scan the chain for matching kstats */
 	for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next)
 	{
-	    if (strncmp(ks->ks_name, name, namelen) == 0)
+	    if ((strncmp(ks->ks_class, class, classlen) == 0) &&
+	        (strncmp(ks->ks_module, module, modlen) == 0) &&
+	        (strncmp(ks->ks_name, name, namelen) == 0))
 	    {
+		dprintf("kstat_safe_lookup found instance %d (%p)\n",
+			ks->ks_instance, ks);
+
 		/* this kstat matches: save it if there is room */
 		if (count++ < num)
 		{
 		    /* read the kstat */
-		    new_kcid = kstat_read(kc, ks, cbuf);
+		    new_kcid = kstat_read(kc, ks, NULL);
 
 		    /* if the chain changed, update it */
 		    if (new_kcid != kcid)
 		    {
-			dprintf("kstat_safe_namematch: chain changed to %d...updating\n",
+			dprintf("kstat_safe_lookup: chain changed to %d...updating\n",
 				new_kcid);
 			changed = 1;
 			kcid = kstat_chain_update(kc);
@@ -832,18 +859,64 @@
 		    }
 
 		    /* move to the next buffers */
-		    cbuf += size;
 		    *ksp++ = ks;
 		}
 	    }
 	}
     } while(changed);
 
-    dprintf("kstat_safe_namematch returns %d\n", count);
+    dprintf("kstat_safe_lookup returns %d\n", count);
 
     return count;
 }
 
+#ifdef USE_NAMED_CPU_KSTAT
+/*
+ * If index_ptr integer value is > -1 then the index points to the
+ * string entry in the ks_data that we are interested in. Otherwise
+ * we will need to walk the array.
+ */
+static uint64_t
+kstat_safe_datalookup(kstat_t *kstat, char *name, int *index_ptr)
+{
+    int i;
+    int size;
+    int index;
+    char *namep, *datap;
+    kstat_named_t *data;
+
+    if (kstat->ks_type != KSTAT_TYPE_NAMED)
+	    return (0);
+
+    size = sizeof (kstat_named_t);
+    namep = KSTAT_NAMED_PTR(kstat)->name;
+
+    index = *index_ptr;
+    if (index >= 0) {
+	    /* Short cut to the information. */
+	    datap = kstat->ks_data;
+	    data = (kstat_named_t *)&datap[size*index];
+	    if (data->data_type != KSTAT_DATA_UINT64)
+		    return (0);
+	    return (data->value.ui64);
+    }
+
+    /* Need to go find the string. */
+    data = kstat->ks_data;
+    for (i = 0; i < kstat->ks_ndata; i++) {
+	    if (strcmp(name, namep) == 0) {
+		    *index_ptr = i;
+		    if (data->data_type != KSTAT_DATA_UINT64)
+			    return (0);
+		    return (data->value.ui64);
+	    }
+	    namep += size;
+	    data++;
+    }
+    return (0);
+}
+#endif /* USE_NAMED_CPU_KSTAT */
+
 static kstat_t *ks_system_misc = NULL;
 
 #endif /* USE_KSTAT */
@@ -936,36 +1009,55 @@
 
 {
 #ifdef USE_KSTAT
+#ifdef USE_NAMED_CPU_KSTAT
+    static kstat_t **cpu_sys_ks = NULL, **cpu_vm_ks = NULL;
+    kstat_t *cpu_sys_stat_p, *cpu_vm_stat_p;
+#else
     static kstat_t **cpu_ks = NULL;
-    static cpu_stat_t *cpu_stat = NULL;
+    cpu_stat_t cpu_stat;
+#endif
+    static kid_t cpu_kcid = 0;
     static unsigned int nelems = 0;
-    cpu_stat_t *cpu_stat_p;
-    int i, cpu_num;
+    static int cpu_num = 0, cpu_vm_num = 0;
+    int i;
     struct cpustats *cpustats_p;
 
     dprintf("get_cpustats(%d -> %d, %08x)\n", cnt, *cnt, cpustats);
 
-    while (nelems > 0 ?
-	   (cpu_num = kstat_safe_namematch(nelems,
-					   cpu_ks,
-					   "cpu_stat",
-					   cpu_stat,
-					   sizeof(cpu_stat_t))) > nelems :
-	   (cpu_num = get_ncpus()) > 0)
+    /* Grab initial number of cpus */
+    if (nelems == 0) {
+	    cpu_vm_num = cpu_num = get_ncpus();
+	    if (cpu_num <= 0)
+		    return (cpustats);
+    }
+
+reload:
+    /* Make sure we have enough space for all cpus */
+    while (cpu_kcid != kcid || cpu_num != cpu_vm_num || cpu_num > nelems)
     {
 	/* reallocate the arrays */
 	dprintf("realloc from %d to %d\n", nelems, cpu_num);
 	nelems = cpu_num;
-	if (cpu_ks != NULL)
-	{
-	    free(cpu_ks);
+#ifdef USE_NAMED_CPU_KSTAT
+	free(cpu_sys_ks);
+	free(cpu_vm_ks);
+	cpu_sys_ks = (kstat_t **)calloc(nelems, sizeof(kstat_t *));
+	cpu_vm_ks = (kstat_t **)calloc(nelems, sizeof(kstat_t *));
+
+	if (cpu_sys_ks == NULL || cpu_vm_ks == NULL) {
+		puts("Allocation failed\n");
+		abort();
 	}
+
+	cpu_num = kstat_safe_lookup(nelems, cpu_sys_ks, "misc", "cpu", "sys");
+	cpu_vm_num = kstat_safe_lookup(nelems, cpu_vm_ks, "misc", "cpu", "vm");
+#else
+	free(cpu_ks);
 	cpu_ks = (kstat_t **)calloc(nelems, sizeof(kstat_t *));
-	if (cpu_stat != NULL)
-	{
-	    free(cpu_stat);
-	}
-	cpu_stat = (cpu_stat_t *)malloc(nelems * sizeof(cpu_stat_t));
+	cpu_num = cpu_vm_num =
+	    kstat_safe_lookup(nelems, cpu_ks, "misc", "cpu_stat", "");
+#endif
+	cpu_kcid = kcid;
     }
 
     /* do we have more cpus than our caller? */
@@ -975,36 +1067,96 @@
 	dprintf("realloc array from %d to %d\n", *cnt, cpu_num);
 	*cnt = cpu_num;
 	cpustats = (struct cpustats *)realloc(cpustats,
-					      cpu_num * sizeof(struct cpustats));
+		cpu_num * sizeof(struct cpustats));
     }
 
-    cpu_stat_p = cpu_stat;
     cpustats_p = cpustats;
     for (i = 0; i < cpu_num; i++)
     {
-	dprintf("cpu %d %08x: idle %u, user %u, syscall %u\n", i, cpu_stat_p,
-		cpu_stat_p->cpu_sysinfo.cpu[0],
-		cpu_stat_p->cpu_sysinfo.cpu[1],
-		cpu_stat_p->cpu_sysinfo.syscall);
+#ifdef USE_NAMED_CPU_KSTAT
+	cpu_sys_stat_p = cpu_sys_ks[i];
+	cpu_vm_stat_p = cpu_vm_ks[i];
 
-	cpustats_p->states[CPU_IDLE] = cpu_stat_p->cpu_sysinfo.cpu[CPU_IDLE];
-	cpustats_p->states[CPU_USER] = cpu_stat_p->cpu_sysinfo.cpu[CPU_USER];
-	cpustats_p->states[CPU_KERNEL] = cpu_stat_p->cpu_sysinfo.cpu[CPU_KERNEL];
-	cpustats_p->states[CPUSTATE_IOWAIT] = cpu_stat_p->cpu_sysinfo.wait[W_IO] +
-	    cpu_stat_p->cpu_sysinfo.wait[W_PIO];
-	cpustats_p->states[CPUSTATE_SWAP] = cpu_stat_p->cpu_sysinfo.wait[W_SWAP];
-	cpustats_p->pswitch = cpu_stat_p->cpu_sysinfo.pswitch;
-	cpustats_p->trap = cpu_stat_p->cpu_sysinfo.trap;
-	cpustats_p->intr = cpu_stat_p->cpu_sysinfo.intr;
-	cpustats_p->syscall = cpu_stat_p->cpu_sysinfo.syscall;
-	cpustats_p->sysfork = cpu_stat_p->cpu_sysinfo.sysfork;
-	cpustats_p->sysvfork = cpu_stat_p->cpu_sysinfo.sysvfork;
-	cpustats_p->pfault = cpu_stat_p->cpu_vminfo.hat_fault +
-	    cpu_stat_p->cpu_vminfo.as_fault;
-	cpustats_p->pgin = cpu_stat_p->cpu_vminfo.pgin;
-	cpustats_p->pgout = cpu_stat_p->cpu_vminfo.pgout;
+	/*
+	 * If kstat id has changed, update the kstat headers and re-allocate
+	 * the arrays accordingly.
+	 */
+	if (((cpu_kcid = kstat_read(kc, cpu_sys_stat_p, NULL)) != kcid) ||
+		((cpu_kcid = kstat_read(kc, cpu_vm_stat_p, NULL)) != kcid))
+	    goto reload;
+
+	dprintf("cpu %d %08x: idle %llu, user %llu, syscall %llu\n",
+		i, cpu_sys_stat_p,
+		kstat_safe_datalookup(cpu_sys_stat_p, "cpu_ticks_idle",
+		&cpu_ticks_idle_index),
+		kstat_safe_datalookup(cpu_sys_stat_p, "cpu_ticks_user",
+		&cpu_ticks_user_index),
+		kstat_safe_datalookup(cpu_sys_stat_p, "syscall",
+		&syscall_index));
+
+	cpustats_p->states[CPUSTATE_IDLE] =
+		kstat_safe_datalookup(cpu_sys_stat_p, "cpu_ticks_idle",
+		&cpu_ticks_idle_index);
+	cpustats_p->states[CPUSTATE_USER] =
+		kstat_safe_datalookup(cpu_sys_stat_p, "cpu_ticks_user",
+		&cpu_ticks_user_index);
+	cpustats_p->states[CPUSTATE_KERNEL] =
+		kstat_safe_datalookup(cpu_sys_stat_p, "cpu_ticks_kernel",
+		&cpu_ticks_kernel_index);
+	cpustats_p->states[CPUSTATE_STOLEN] =
+		kstat_safe_datalookup(cpu_sys_stat_p, "cpu_ticks_stolen",
+		&cpu_ticks_stolen_index);
+	cpustats_p->states[CPUSTATE_SWAP] = 0;
+	cpustats_p->pswitch = kstat_safe_datalookup(cpu_sys_stat_p, "pswitch",
+		&pswitch_index);
+	cpustats_p->trap = kstat_safe_datalookup(cpu_sys_stat_p, "trap",
+		&trap_index);
+	cpustats_p->intr = kstat_safe_datalookup(cpu_sys_stat_p, "intr",
+		&intr_index);
+	cpustats_p->syscall = kstat_safe_datalookup(cpu_sys_stat_p, "syscall",
+		&syscall_index);
+	cpustats_p->sysfork = kstat_safe_datalookup(cpu_sys_stat_p, "sysfork",
+		&sysfork_index);
+	cpustats_p->sysvfork = kstat_safe_datalookup(cpu_sys_stat_p, "sysvfork",
+		&sysvfork_index);
+	cpustats_p->pfault = kstat_safe_datalookup(cpu_vm_stat_p, "hat_fault",
+		&hat_fault_index) +
+		kstat_safe_datalookup(cpu_vm_stat_p, "as_fault",
+		&as_fault_index);
+	cpustats_p->pgin = kstat_safe_datalookup(cpu_vm_stat_p, "pgin",
+		&pgin_index);
+	cpustats_p->pgout = kstat_safe_datalookup(cpu_vm_stat_p, "pgout",
+		&pgout_index);
+#else
+	if ((cpu_kcid = kstat_read(kc, cpu_ks[i], &cpu_stat)) != kcid)
+	    goto reload;
+
+	dprintf("cpu %d %08x: idle %u, user %u, syscall %u\n", i, cpu_stat,
+		cpu_stat.cpu_sysinfo.cpu[CPUSTATE_IDLE],
+		cpu_stat.cpu_sysinfo.cpu[CPUSTATE_USER],
+		cpu_stat.cpu_sysinfo.syscall);
+
+	cpustats_p->states[CPUSTATE_IDLE] =
+		(uint64_t)cpu_stat.cpu_sysinfo.cpu[CPU_IDLE];
+	cpustats_p->states[CPUSTATE_USER] =
+		(uint64_t)cpu_stat.cpu_sysinfo.cpu[CPU_USER];
+	cpustats_p->states[CPUSTATE_KERNEL] =
+		(uint64_t)cpu_stat.cpu_sysinfo.cpu[CPU_KERNEL];
+	cpustats_p->states[CPUSTATE_STOLEN] = 0;
+	cpustats_p->states[CPUSTATE_SWAP] =
+		(uint64_t)cpu_stat.cpu_sysinfo.wait[W_SWAP];
+	cpustats_p->pswitch = (uint64_t)cpu_stat.cpu_sysinfo.pswitch;
+	cpustats_p->trap = (uint64_t)cpu_stat.cpu_sysinfo.trap;
+	cpustats_p->intr = (uint64_t)cpu_stat.cpu_sysinfo.intr;
+	cpustats_p->syscall = (uint64_t)cpu_stat.cpu_sysinfo.syscall;
+	cpustats_p->sysfork = (uint64_t)cpu_stat.cpu_sysinfo.sysfork;
+	cpustats_p->sysvfork = (uint64_t)cpu_stat.cpu_sysinfo.sysvfork;
+	cpustats_p->pfault = (uint64_t)cpu_stat.cpu_vminfo.hat_fault +
+		(uint64_t)cpu_stat.cpu_vminfo.as_fault;
+	cpustats_p->pgin = (uint64_t)cpu_stat.cpu_vminfo.pgin;
+	cpustats_p->pgout = (uint64_t)cpu_stat.cpu_vminfo.pgout;
+#endif
 	cpustats_p++;
-	cpu_stat_p++;
     }
 
     cpucount = cpu_num;
@@ -1035,11 +1187,10 @@
 	    /* get struct cpu for this processor */
 	    (void) getkval (cpu_offset[i], (int *)(&cpu), sizeof (struct cpu), "cpu");
 
-	    (*cp_stats_p)[CPU_IDLE] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_IDLE];
-	    (*cp_stats_p)[CPU_USER] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_USER];
-	    (*cp_stats_p)[CPU_KERNEL] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_KERNEL];
-	    (*cp_stats_p)[CPUSTATE_IOWAIT] = cpu.cpu_stat.cpu_sysinfo.wait[W_IO] +
-		cpu.cpu_stat.cpu_sysinfo.wait[W_PIO];
+	    (*cp_stats_p)[CPUSTATE_IDLE] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_IDLE];
+	    (*cp_stats_p)[CPUSTATE_USER] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_USER];
+	    (*cp_stats_p)[CPUSTATE_KERNEL] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_KERNEL];
+	    (*cp_stats_p)[CPUSTATE_STOLEN] = 0;
 	    (*cp_stats_p)[CPUSTATE_SWAP] = cpu.cpu_stat.cpu_sysinfo.wait[W_SWAP];
 	    cp_stats_p++;
 	}
@@ -1394,14 +1545,55 @@
     return (0);
 }
 
+static void
+percentages64(int cnt, int *out, uint64_t *new, uint64_t *old, uint64_t *diffs)
+{
+	int i;
+	uint64_t change;
+	uint64_t total_change;
+	uint64_t *dp;
+	uint64_t half_total;
+
+	/* initialization */
+	total_change = 0;
+	dp = diffs;
+
+	/* calculate changes for each state and the overall change */
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * Don't worry about wrapping - even at hz=1GHz, a
+		 * u_int64_t will last at least 544 years.
+		 */
+		change = *new - *old;
+		total_change += (*dp++ = change);
+		*old++ = *new++;
+	}
+
+	/* avoid divide by zero potential */
+	if (total_change == 0)
+		total_change = 1;
+
+	/* calculate percentages based on overall change, rounding up */
+	half_total = total_change / 2;
+	for (i = 0; i < cnt; i++)
+		*out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+}
+
+static uint_t
+diff_per_second64(uint64_t x, uint64_t y)
+{
+	uint64_t diff = y > x ? UINT64_MAX - y + x + 1 : x - y;
+	return ((uint_t)(diff * 1000 / time_elapsed()));
+}
+
 void
 get_system_info (struct system_info *si)
 {
     int avenrun[3];
 
-    static long cp_time[CPUSTATES];
-    static long cp_old[CPUSTATES];
-    static long cp_diff[CPUSTATES];
+    static uint64_t cp_time[CPUSTATES];
+    static uint64_t cp_old[CPUSTATES];
+    static uint64_t cp_diff[CPUSTATES];
     static struct cpustats *cpustats = NULL;
     static struct cpustats sum_current;
     static struct cpustats sum_old;
@@ -1440,7 +1632,7 @@
     }
 
     /* convert cp_time counts to percentages */
-    (void) percentages (CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+    (void) percentages64 (CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
 
     /* get mpid -- process id of last process */
     if (kd)
@@ -1467,15 +1659,15 @@
     }
 
     /* get kernel data */
-    kernel_stats[KERNEL_CSWITCH] = diff_per_second(sum_current.pswitch, sum_old.pswitch);
-    kernel_stats[KERNEL_TRAP] = diff_per_second(sum_current.trap, sum_old.trap);
-    kernel_stats[KERNEL_INTR] = diff_per_second(sum_current.intr, sum_old.intr);
-    kernel_stats[KERNEL_SYSCALL] = diff_per_second(sum_current.syscall, sum_old.syscall);
-    kernel_stats[KERNEL_FORK] = diff_per_second(sum_current.sysfork + sum_current.sysvfork,
+    kernel_stats[KERNEL_CSWITCH] = diff_per_second64(sum_current.pswitch, sum_old.pswitch);
+    kernel_stats[KERNEL_TRAP] = diff_per_second64(sum_current.trap, sum_old.trap);
+    kernel_stats[KERNEL_INTR] = diff_per_second64(sum_current.intr, sum_old.intr);
+    kernel_stats[KERNEL_SYSCALL] = diff_per_second64(sum_current.syscall, sum_old.syscall);
+    kernel_stats[KERNEL_FORK] = diff_per_second64(sum_current.sysfork + sum_current.sysvfork,
 						sum_old.sysfork + sum_old.sysvfork);
-    kernel_stats[KERNEL_PFAULT] = diff_per_second(sum_current.pfault, sum_old.pfault);
-    kernel_stats[KERNEL_PGIN] = pagetok(diff_per_second(sum_current.pgin, sum_old.pgin));
-    kernel_stats[KERNEL_PGOUT] = pagetok(diff_per_second(sum_current.pgout, sum_old.pgout));
+    kernel_stats[KERNEL_PFAULT] = diff_per_second64(sum_current.pfault, sum_old.pfault);
+    kernel_stats[KERNEL_PGIN] = pagetok(diff_per_second64(sum_current.pgin, sum_old.pgin));
+    kernel_stats[KERNEL_PGOUT] = pagetok(diff_per_second64(sum_current.pgout, sum_old.pgout));
 
 
     /* set arrays and strings */