#include /* for atoi, malloc */ #include #include /* for sqrt() */ #include /* for read, write, getpid */ #include /* for errno */ #include /* for ctime() */ #include /* for gettimeofday() */ #include /* for times() */ #include /* for socket(), getpid, etc */ #include /* for socket(), etc */ #include /* for sockaddr_in, in_addr */ #define MYBUFLEN 937 typedef struct { struct sockaddr_in remaddr; int sock; char *cbuf; char *wbuf; } ConnData; typedef struct { double ss_min, ss_max, ss_sum1, ss_sum2; } StatSum; typedef struct { long unsigned psc_user, psc_nice, psc_syst, psc_idle, psc_total; } ProcStatCpu; typedef struct { int ps_utime; int ps_stime; int ps_ttime; } ProcsStat; #define ZSS {10*1000*1000, 0, 0, 0.0} static StatSum zss = ZSS; void updateSSd(StatSum *ss, double x) { ss->ss_sum1 += x; ss->ss_sum2 += x*x; if (x < ss->ss_min) ss->ss_min = x; if (x > ss->ss_max) ss->ss_max = x; return; } void updateSS(StatSum *ss, long x) {updateSSd(ss, (double)x);} char *sfmtSS(char *buf, StatSum ss, long nIter, int fmti) { double n = nIter; double avg = ((double)ss.ss_sum1) / n; double devsq = 0; if (nIter > 1) devsq = ((ss.ss_sum2 + n*avg*avg - 2*avg*ss.ss_sum1) / (n-1)); if (devsq >= 0) sprintf(buf, (fmti ?"[%3.1f, %8.6f += %8.6f, %3.1f, %6.1f]" :"[%6.1f, %7.2f += %7.2f, %7.1f, %10.1f]"), ss.ss_min, avg, (double) sqrt(devsq), ss.ss_max, ss.ss_sum1); else sprintf(buf, (fmti ?"[%3.1f, %8.6f += sqrt(%8.6f), %3.1f, %6.1f]" :"[%6.1f, %7.2f += sqrt(%7.2f), %7.1f, %10.1f]"), ss.ss_min, avg, devsq, ss.ss_max, ss.ss_sum1); return buf; } char *sfmtTime(char *buf, struct timeval tv) { char *tstr; tstr = ctime(&tv.tv_sec); if (tstr != NULL) { int tslen; tslen = strlen(tstr); if (tstr[tslen-1] == '\n') tstr[tslen-1] = 0; sprintf(buf, "%s + %06ldus", tstr, (long) tv.tv_usec); } else sprintf(buf, "%ld + %06ldus (ctime failed)", (long) tv.tv_sec, (long) tv.tv_usec); return buf; } char *sfmtNow(char *buf) { struct timeval now; int res; res = gettimeofday(&now, NULL); if (res) sprintf(buf, "(getttimeofday() failed!)"); else sfmtTime(buf, now); return buf; } long dtv(struct timeval tva, struct timeval tvb) { long ds = tva.tv_sec - tvb.tv_sec ; long dus = tva.tv_usec - tvb.tv_usec; return (dus + (1000000*ds)); } long ReportPeriod_S = 60; int fusum; struct timeval lastRept = {0}; StatSum dBytes = ZSS, dusIn = ZSS, dusMid = ZSS, dusOut = ZSS; StatSum dut = ZSS, dst = ZSS, dbt = ZSS; ProcStatCpu curPsc; ProcsStat curPs; FILE *procStat = NULL, *procsStat = NULL; int pid; ProcStatCpu readProcStat() { int ns; ProcStatCpu ans; rewind(procStat); ns = fscanf(procStat, "cpu %lu %lu %lu %lu\n", &ans.psc_user, &ans.psc_nice, &ans.psc_syst, &ans.psc_idle); if (ns != 4) { fprintf(stderr, "Read of /proc/stat failed!\n"); exit(1); } ans.psc_total = (ans.psc_user + ans.psc_nice + ans.psc_syst + ans.psc_idle); return ans; } ProcsStat readProcsStat() { int ns; ProcsStat ans; rewind(procsStat); ns = fscanf(procsStat, "%*d (%*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %d %d ", &ans.ps_utime, &ans.ps_stime); if (ns < 2) { fprintf(stderr, "proc's stat scanf failed!\n"); exit(1); } ans.ps_ttime = ans.ps_utime + ans.ps_stime; return ans; } ProcStatCpu psc_diff(ProcStatCpu *pa, ProcStatCpu *pb) { ProcStatCpu ans; ans.psc_user = pa->psc_user - pb->psc_user; ans.psc_nice = pa->psc_nice - pb->psc_nice; ans.psc_syst = pa->psc_syst - pb->psc_syst; ans.psc_idle = pa->psc_idle - pb->psc_idle; ans.psc_total = pa->psc_total - pb->psc_total; return ans; } void psc_printStep(char *what, ProcStatCpu *pCur, ProcStatCpu *pNxt) { ProcStatCpu dltPsc; float tot, pct_user, pct_nice, pct_syst, pct_idle; dltPsc = psc_diff(pNxt, pCur); tot = dltPsc.psc_total; pct_user = 100 * dltPsc.psc_user / tot; pct_nice = 100 * dltPsc.psc_nice / tot; pct_syst = 100 * dltPsc.psc_syst / tot; pct_idle = 100 * dltPsc.psc_idle / tot; printf("%s\tuser cs\tnice cs\tsyst cs\t idle cs\t total cs\n" "cum\t%7lu\t%7lu\t%7lu\t%10lu\t%10lu\n" "diff\t%7lu\t%7lu\t%7lu\t%10lu\t%10lu\n" "%%age\t%7.1f\t%7.1f\t%7.1f\t%10.1f\n\n", what , pNxt->psc_user, pNxt->psc_nice , pNxt->psc_syst, pNxt->psc_idle , pNxt->psc_total , dltPsc.psc_user, dltPsc.psc_nice , dltPsc.psc_syst, dltPsc.psc_idle , dltPsc.psc_total , pct_user, pct_nice, pct_syst, pct_idle ); } void ps_printStep(int pid, ProcsStat *pCur, ProcsStat *pNxt, float dt) { int dutime = pNxt->ps_utime - pCur->ps_utime; int dstime = pNxt->ps_stime - pCur->ps_stime; int dttime = pNxt->ps_ttime - pCur->ps_ttime; float pct_u = 1.0 * dutime / dt; float pct_s = 1.0 * dstime / dt; float pct_t = 1.0 * dttime / dt; printf("p%d\tuser\tkern\tboth\n" "new\t%d\t%d\t%d\n" "diff\t%d\t%d\t%d\n" "%%age\t%04.1f\t%04.1f\t%04.1f\n", pid , pNxt->ps_utime, pNxt->ps_stime, pNxt->ps_ttime , dutime, dstime, dttime , pct_u, pct_s, pct_t ); } void *runConn(void *arg, int nsub) { ConnData *cdp = (ConnData*) arg; char *wbuf; size_t i; int j, res; long sinceRept, dIter = 0, ReportPeriod_US = ReportPeriod_S*1000*1000; struct timeval tvb, tva; struct tms tmsa, tmsb; int first; char bufb[100], bufi[100], bufm [100], bufo[100]; char bufu[100], bufs[100], bufus[100], buft[100]; if (times(&tmsa) == (clock_t) -1) { fprintf(stderr, "times() A failed.\n"); exit(13); } if (procStat) curPsc = readProcStat(); if (procsStat) curPs = readProcsStat(); res = gettimeofday(&tva, NULL); if (res != 0) exit(22); lastRept = tva; for (;1;) { ssize_t nb, nbw; res = gettimeofday(&tvb, NULL); if (res != 0) exit(21); nb = read(cdp->sock, cdp->cbuf, MYBUFLEN); if (nb < 0) { int theErr = errno; fprintf(stderr, "At %s, aborting conn at read, errno=%d.\n", sfmtNow(buft), theErr); return; } if (nb == 0) { fprintf(stderr, "got EOF.\n"); exit(0); /* so gprof writes its stats */ } res = gettimeofday(&tva, NULL); if (res != 0) exit(22); updateSS(&dusIn, dtv(tva, tvb)); updateSS(&dBytes, (long) nb); cdp->cbuf[MYBUFLEN] = 0; for (i = 0; i <= MYBUFLEN; i++) { cdp->wbuf[i] = cdp->cbuf[i]; } for (j = 0; j < nsub; j++) { for (i=0; i < MYBUFLEN; i++) { int dm, n, q; dm = cdp->wbuf[MYBUFLEN-i]; n = cdp->cbuf[(i+400*j)%MYBUFLEN]; q = n / (dm + 1); fusum += q; } } if (fusum == 123456789) fprintf(stdout, "Bingo!\n"); res = gettimeofday(&tvb, NULL); if (res != 0) exit(23); updateSS(&dusMid, dtv(tvb, tva)); for (wbuf = cdp->wbuf; nb > 0; ) { nbw = write(cdp->sock, wbuf, nb); if (nbw < 0) { int theErr = errno; fprintf(stderr, "At %s, aborting conn at write, errno=%d.\n", sfmtNow(buft), theErr); return; } nb -= nbw; wbuf += nbw; } res = gettimeofday(&tva, NULL); if (res != 0) exit(24); if (times(&tmsb) == (clock_t) -1) { fprintf(stderr, "times() B failed.\n"); exit(25); } updateSS (&dusOut, dtv(tva, tvb)); /* updateSSd(&dut, ((double) (tmsb.tms_utime - tmsa.tms_utime))/CLOCKS_PER_SEC); updateSSd(&dst, ((double) (tmsb.tms_stime - tmsa.tms_stime))/CLOCKS_PER_SEC); */ updateSS(&dut, (tmsb.tms_utime - tmsa.tms_utime) ); updateSS(&dst, (tmsb.tms_stime - tmsa.tms_stime) ); updateSS(&dbt, ((tmsb.tms_utime - tmsa.tms_utime) + (tmsb.tms_stime - tmsa.tms_stime))); tmsa = tmsb; sinceRept = dtv(tva, lastRept); dIter++; if (sinceRept >= ReportPeriod_US) { ProcStatCpu nxtPsc, dltPsc; ProcsStat nxtPs; float pct_u = dut.ss_sum1*1.0e6/sinceRept; float pct_s = dst.ss_sum1*1.0e6/sinceRept; float pct_b = dbt.ss_sum1*1.0e6/sinceRept; if (procStat) { nxtPsc = readProcStat(); } if (procsStat) { nxtPs = readProcsStat(); } printf("\n\nAt %s, dIter=%ld, dt=%ld us\n" "db=%s,\n" "I=%s us,\nM=%s us,\nO=%s us,\n" "chg-user-t=%s cs, %4.1f%%\n" "chg-syst-t=%s cs, %4.1f%%\n" "chg-both-t=%s cs, %4.1f%%\n" "cum-user-t=%ld cs, cum-syst-t=%ld cs, cum-both-t=%ld cs.\n" "\n", sfmtTime(buft, tva), dIter, sinceRept, sfmtSS(bufb, dBytes, dIter, 0), sfmtSS(bufi, dusIn , dIter, 0), sfmtSS(bufm, dusMid, dIter, 0), sfmtSS(bufo, dusOut, dIter, 0), sfmtSS(bufu , dut , dIter, 1), pct_u, sfmtSS(bufs , dst , dIter, 1), pct_s, sfmtSS(bufus, dbt , dIter, 1), pct_b, (long) tmsb.tms_utime, (long) tmsb.tms_stime, (long) tmsb.tms_utime + tmsb.tms_stime ); dBytes = dusIn = dusMid = dusOut = dut = dst = dbt = zss; dIter = 0; lastRept = tva; if (procStat) { psc_printStep("mach", &curPsc, &nxtPsc); curPsc = nxtPsc; } if (procsStat) { ps_printStep(pid, &curPs, &nxtPs, sinceRept/1.0e6); curPs = nxtPs ; } } } } int main(int argc, char **argv) { int ss; int port; union { struct sockaddr mysa; struct sockaddr_in mysain; } mysau; int salen = sizeof(mysau.mysa); int res; int nsub = 1; pid_t tpid; if (argc != 3) { fprintf(stderr, "Usage: %s report-period n-sub\n", argv[0]); return 1; } ReportPeriod_S = atoi(argv[1]); nsub = atoi(argv[2]); fprintf(stdout, "Report Period = %ld seconds\n", ReportPeriod_S); fprintf(stdout, "Sub loop count = %d\n", nsub); fprintf(stdout, "CLOCKS_PER_SEC = %g\n", (double) CLOCKS_PER_SEC); fusum = 0; tpid = getpid(); pid = tpid; ss = socket(AF_INET, SOCK_STREAM, 0); if (ss < 0) { int theErr = errno; fprintf(stderr, "socket() failed, errno=%d.\n", theErr); exit(2); } res = listen(ss, 100); if (res < 0) { int theErr = errno; fprintf(stderr, "listen() failed, errno=%d.\n", theErr); exit(4); } res = getsockname(ss, &mysau.mysa, &salen); if (res < 0) { int theErr = errno; fprintf(stderr, "getsockname() failed, errno=%d.\n", theErr); exit(6); } if (salen != sizeof(mysau.mysain)) { fprintf(stderr, "getsockname() returned len=%d rather than %d.\n", salen, sizeof(mysau.mysain)); exit(8); } port = ntohs(mysau.mysain.sin_port); fprintf(stdout, "listening on port %d.\n", port); procStat = fopen("/proc/stat", "r"); if (!procStat){ fprintf(stderr, "Failed to open /proc/stat!\n"); } else { setvbuf(procStat , NULL, _IONBF, 0); } if (0) { char psname[100]; sprintf(psname, "/proc/%d/stat", pid); procsStat = fopen(psname, "r"); if (!procsStat) { fprintf(stderr, "Failed to open proc %d's stat!\n", pid); } else { setvbuf(procsStat, NULL, _IONBF, 0); } } for (;;) { int newsock; ConnData *cdp; salen = sizeof(mysau.mysa); newsock = accept(ss, &mysau.mysa, &salen); if (newsock < 0) { int theErr = errno; fprintf(stderr, "accept() failed, errno=%d.\n", theErr); exit(10); } if (salen != sizeof(mysau.mysain)) { fprintf(stderr, "accept claimed remote address of length %d, rather than %d.\n", salen, sizeof(mysau.mysain)); exit(12); } cdp = (ConnData*) malloc(sizeof(ConnData)); if (cdp != NULL) { cdp->cbuf = malloc(MYBUFLEN+1); cdp->wbuf = malloc(MYBUFLEN+1); } if (cdp == NULL || cdp->cbuf==NULL || cdp->wbuf==NULL) { fprintf(stderr, "malloc failed!\n"); exit(14); } cdp->remaddr = mysau.mysain; cdp->sock = newsock; runConn(cdp, nsub); } }