svn commit: r277569 - head/usr.bin/vmstat

Will Andrews will at FreeBSD.org
Fri Jan 23 16:15:56 UTC 2015


Author: will
Date: Fri Jan 23 16:15:55 2015
New Revision: 277569
URL: https://svnweb.freebsd.org/changeset/base/277569

Log:
  Make "vmstat -i" respect the -c <count> and -i <interval> options together.
  
  Submitted by:	asomers
  MFC after:	1 week
  Sponsored by:	Spectra Logic
  MFSpectraBSD:	1066735 on 2014/06/04

Modified:
  head/usr.bin/vmstat/vmstat.c

Modified: head/usr.bin/vmstat/vmstat.c
==============================================================================
--- head/usr.bin/vmstat/vmstat.c	Fri Jan 23 16:05:47 2015	(r277568)
+++ head/usr.bin/vmstat/vmstat.c	Fri Jan 23 16:15:55 2015	(r277569)
@@ -148,7 +148,7 @@ static void	cpustats(void);
 static void	pcpustats(int, u_long, int);
 static void	devstats(void);
 static void	doforkst(void);
-static void	dointr(void);
+static void	dointr(unsigned int, int);
 static void	dosum(void);
 static void	dovmstat(unsigned int, int);
 static void	domemstat_malloc(void);
@@ -325,7 +325,7 @@ retry_nlist:
 		dotimes();
 #endif
 	if (todo & INTRSTAT)
-		dointr();
+		dointr(interval, reps);
 	if (todo & VMSTAT)
 		dovmstat(interval, reps);
 	exit(0);
@@ -1165,61 +1165,132 @@ pcpustats(int ncpus, u_long cpumask, int
 	}
 }
 
-static void
-dointr(void)
+static unsigned int
+read_intrcnts(unsigned long **intrcnts)
 {
-	unsigned long *intrcnt, uptime;
-	uint64_t inttotal;
-	size_t clen, inamlen, intrcntlen, istrnamlen;
-	unsigned int i, nintr;
-	char *intrname, *tintrname;
+	size_t intrcntlen;
 
-	uptime = getuptime();
 	if (kd != NULL) {
 		kread(X_SINTRCNT, &intrcntlen, sizeof(intrcntlen));
-		kread(X_SINTRNAMES, &inamlen, sizeof(inamlen));
-		if ((intrcnt = malloc(intrcntlen)) == NULL ||
-		    (intrname = malloc(inamlen)) == NULL)
+		if ((*intrcnts = malloc(intrcntlen)) == NULL)
 			err(1, "malloc()");
-		kread(X_INTRCNT, intrcnt, intrcntlen);
-		kread(X_INTRNAMES, intrname, inamlen);
+		kread(X_INTRCNT, *intrcnts, intrcntlen);
 	} else {
-		for (intrcnt = NULL, intrcntlen = 1024; ; intrcntlen *= 2) {
-			if ((intrcnt = reallocf(intrcnt, intrcntlen)) == NULL)
+		for (*intrcnts = NULL, intrcntlen = 1024; ; intrcntlen *= 2) {
+			*intrcnts = reallocf(*intrcnts, intrcntlen);
+			if (*intrcnts == NULL)
 				err(1, "reallocf()");
 			if (mysysctl("hw.intrcnt",
-			    intrcnt, &intrcntlen, NULL, 0) == 0)
+			    *intrcnts, &intrcntlen, NULL, 0) == 0)
 				break;
 		}
-		for (intrname = NULL, inamlen = 1024; ; inamlen *= 2) {
-			if ((intrname = reallocf(intrname, inamlen)) == NULL)
+	}
+
+	return (intrcntlen / sizeof(unsigned long));
+}
+
+static void
+print_intrcnts(unsigned long *intrcnts, unsigned long *old_intrcnts,
+		char *intrnames, unsigned int nintr,
+		size_t istrnamlen, unsigned long long period)
+{
+	unsigned long *intrcnt, *old_intrcnt;
+	uint64_t inttotal, old_inttotal, total_count, total_rate;
+	char* intrname;
+	unsigned int i;
+
+	inttotal = 0;
+	old_inttotal = 0;
+	intrname = intrnames;
+	for (i = 0, intrcnt=intrcnts, old_intrcnt=old_intrcnts; i < nintr; i++) {
+		if (intrname[0] != '\0' && (*intrcnt != 0 || aflag)) {
+			unsigned long count, rate;
+
+			count = *intrcnt - *old_intrcnt;
+			rate = (count * 1000 + period/2) / period;
+			(void)printf("%-*s %20lu %10lu\n", (int)istrnamlen,
+			    intrname, count, rate);
+		}
+		intrname += strlen(intrname) + 1;
+		inttotal += *intrcnt++;
+		old_inttotal += *old_intrcnt++;
+	}
+	total_count = inttotal - old_inttotal;
+	total_rate = (total_count * 1000 + period/2) / period;
+	(void)printf("%-*s %20" PRIu64 " %10" PRIu64 "\n", (int)istrnamlen,
+	    "Total", total_count, total_rate);
+}
+
+static void
+dointr(unsigned int interval, int reps)
+{
+	unsigned long *intrcnts;
+	unsigned long long uptime, period;
+	unsigned long *old_intrcnts = NULL;
+	size_t clen, inamlen, istrnamlen;
+	unsigned int rep;
+	char *intrnames, *intrname;
+
+	uptime = getuptime();
+
+	/* Get the names of each interrupt source */
+	if (kd != NULL) {
+		kread(X_SINTRNAMES, &inamlen, sizeof(inamlen));
+		if ((intrnames = malloc(inamlen)) == NULL)
+			err(1, "malloc()");
+		kread(X_INTRNAMES, intrnames, inamlen);
+	} else {
+		for (intrnames = NULL, inamlen = 1024; ; inamlen *= 2) {
+			if ((intrnames = reallocf(intrnames, inamlen)) == NULL)
 				err(1, "reallocf()");
 			if (mysysctl("hw.intrnames",
-			    intrname, &inamlen, NULL, 0) == 0)
+			    intrnames, &inamlen, NULL, 0) == 0)
 				break;
 		}
 	}
-	nintr = intrcntlen / sizeof(unsigned long);
-	tintrname = intrname;
+
+	/* Determine the length of the longest interrupt name */
+	intrname = intrnames;
 	istrnamlen = strlen("interrupt");
-	for (i = 0; i < nintr; i++) {
-		clen = strlen(tintrname);
+	while(*intrname != '\0') {
+		clen = strlen(intrname);
 		if (clen > istrnamlen)
 			istrnamlen = clen;
-		tintrname += clen + 1;
+		intrname += strlen(intrname) + 1;
 	}
 	(void)printf("%-*s %20s %10s\n", (int)istrnamlen, "interrupt", "total",
 	    "rate");
-	inttotal = 0;
-	for (i = 0; i < nintr; i++) {
-		if (intrname[0] != '\0' && (*intrcnt != 0 || aflag))
-			(void)printf("%-*s %20lu %10lu\n", (int)istrnamlen,
-			    intrname, *intrcnt, *intrcnt / uptime);
-		intrname += strlen(intrname) + 1;
-		inttotal += *intrcnt++;
+
+	/* 
+	 * Loop reps times printing differential interrupt counts.  If reps is
+	 * zero, then run just once, printing total counts
+	 */
+	period = uptime * 1000;
+	while(1) {
+		char *intrname;
+		unsigned int nintr;
+
+		nintr = read_intrcnts(&intrcnts);
+		/* 
+		 * Initialize old_intrcnts to 0 for the first pass, so
+		 * print_intrcnts will print total interrupts since boot
+		 */
+		if (old_intrcnts == NULL) {
+			old_intrcnts = calloc(nintr, sizeof(unsigned long));
+			if (old_intrcnts == NULL)
+				err(1, "calloc()");
+		}
+
+		print_intrcnts(intrcnts, old_intrcnts, intrnames, nintr,
+		    istrnamlen, period);
+
+		free(old_intrcnts);
+		old_intrcnts = intrcnts;
+		if (reps >= 0 && --reps <= 0)
+			break;
+		usleep(interval * 1000);
+		period = interval;
 	}
-	(void)printf("%-*s %20" PRIu64 " %10" PRIu64 "\n", (int)istrnamlen,
-	    "Total", inttotal, inttotal / uptime);
 }
 
 static void


More information about the svn-src-head mailing list