From owner-svn-src-all@FreeBSD.ORG Fri Jan 23 16:15:56 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CD604A34; Fri, 23 Jan 2015 16:15:56 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id AE0A8C03; Fri, 23 Jan 2015 16:15:56 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0NGFuAn057627; Fri, 23 Jan 2015 16:15:56 GMT (envelope-from will@FreeBSD.org) Received: (from will@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0NGFuQW057626; Fri, 23 Jan 2015 16:15:56 GMT (envelope-from will@FreeBSD.org) Message-Id: <201501231615.t0NGFuQW057626@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: will set sender to will@FreeBSD.org using -f From: Will Andrews Date: Fri, 23 Jan 2015 16:15:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r277569 - head/usr.bin/vmstat X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Jan 2015 16:15:56 -0000 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 and -i 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