home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / lmdd / lmdd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-12  |  6.1 KB  |  338 lines

  1. static char sccsid[] = "@(#)lmdd.c    1.7";
  2.  
  3. /*
  4.  * lmdd, lm@sun.com (Larry McVoy)
  5.  *
  6.  * Uncopyrighted, do whatever you want with it.
  7.  *
  8.  * defaults:
  9.  *    bs=8k
  10.  *    count=forever
  11.  *    if=stdin
  12.  *    of=stdout
  13.  *    ipat=0
  14.  *    opat=0
  15.  *    mismatch=0
  16.  *    rusage=0
  17.  *    flush=0
  18.  * shorthands:
  19.  *    recognizes 'k' or 'm' at the end of a number for 1024 & 1024^2
  20.  *    recognizes "internal" as an internal /dev/zero /dev/null file.
  21.  */
  22. #include <signal.h>
  23. #include <sys/types.h>
  24. #include <sys/time.h>
  25. #ifndef    SVR4
  26. #include <sys/resource.h>
  27. #endif
  28. #define    FLUSH
  29. #ifdef    FLUSH
  30. #include <unistd.h>
  31. #include <sys/mman.h>
  32. #include <sys/stat.h>
  33. #endif
  34. #define    STARTUP        (.11)    /* XXX - about how long before it starts
  35.                  * working.  So time matches w/ rusage. This is
  36.                  * close on a 20Mhz SS. */
  37. #define    uchar    unsigned char
  38.  
  39. int     out, Fsync, Sync, Flush, ru, c;/* done needs it */
  40. char   *cmds[] = {
  41.     "if",            /* input file */
  42.     "of",            /* output file */
  43.     "ipat",            /* check input for pattern */
  44.     "opat",            /* generate pattern on output */
  45.     "mismatch",        /* stop at first mismatch */
  46.     "bs",            /* block size */
  47.     "count",        /* number of blocks */
  48.     "skip",            /* skip this number of blocks on input */
  49.     "fsync",        /* fsync output before exit */
  50.     "sync",            /* sync output before exit */
  51.     "rusage",        /* dump rusage stats */
  52. #ifdef    FLUSH
  53.     "flush",        /* map in out and invalidate (flush) */
  54. #endif
  55.     0,
  56. };
  57.  
  58. main(ac, av)
  59.     char  **av;
  60. {
  61.     uint  *buf;
  62.     int     misses, mismatch, outpat, inpat, bs, in, gotcnt, count;
  63.     int     skip;
  64.     extern char *valloc();
  65.     void    done();
  66.     int     i;
  67.  
  68.     for (i = 1; i < ac; ++i) {
  69.         chkarg(av[i]);
  70.     }
  71.     misses = mismatch = getarg("mismatch=", ac, av);
  72.     inpat = getarg("ipat=", ac, av);
  73.     outpat = getarg("opat=", ac, av);
  74.     in = getfile("if=", ac, av);
  75.     if (in == -1)
  76.         in = 0;
  77.     out = getfile("of=", ac, av);
  78.     if (out == -1)
  79.         out = 1;
  80.     bs = getarg("bs=", ac, av);
  81.     if (bs < 0)
  82.         bs = 8192;
  83.     Fsync = getarg("fsync=", ac, av);
  84.     Sync = getarg("sync=", ac, av);
  85.     ru = getarg("rusage=", ac, av);
  86.     count = getarg("count=", ac, av);
  87.     Flush = getarg("flush=", ac, av);
  88.     if (count < 0)
  89.         gotcnt = 0;
  90.     else
  91.         gotcnt = 1;
  92.     c = 0;
  93.     skip = getarg("skip=", ac, av);
  94.  
  95.     if (inpat != -1 || outpat != -1 && (bs & 3)) {
  96.         printf("Block size must be word aligned\n");
  97.         exit(1);
  98.     }
  99.     if (!(buf = (uint *) valloc((unsigned) bs))) {
  100.         perror("valloc");
  101.         exit(1);
  102.     }
  103.     bzero((char *) buf, bs);
  104.  
  105.     signal(SIGINT, done);
  106.     if (skip > 0)
  107.         lseek(in, skip * bs, 0);
  108.     start();
  109.     for (;;) {
  110.         register x;
  111.  
  112.         if (gotcnt && count-- <= 0)
  113.             done();
  114.         if (in >= 0)
  115.             x = read(in, buf, bs);
  116.         else
  117.             x = bs;
  118.         if (x <= 0)
  119.             done();
  120.         if (inpat != -1) {
  121.             register foo, cnt;
  122.  
  123.             for (foo = 0, cnt = x >> 2; cnt--; foo++) {
  124.                 if (buf[foo] != (uint) (c + foo)) {
  125.                     printf("ERROR: off=%d want=%x got=%x\n",
  126.                         c + foo, c + foo, buf[foo]);
  127.                     if (mismatch != -1 && --misses == 0)
  128.                         done();
  129.                 }
  130.             }
  131.         }
  132.         if (outpat != -1) {
  133.             register foo, cnt;
  134.  
  135.             for (foo = 0, cnt = x >> 2; cnt--; foo++)
  136.                 buf[foo] = c + foo;
  137.         }
  138.         if (out >= 0)
  139.             if (write(out, buf, x) != x)
  140.                 done();
  141.         c += x >> 2;
  142.     }
  143. }
  144.  
  145. chkarg(arg)
  146.     char    *arg;
  147. {
  148.     int    i;
  149.     char    *a, *b;
  150.  
  151.     for (i = 0; cmds[i]; ++i) {
  152.         for (a = arg, b = cmds[i]; *a && *b && *a == *b; a++, b++)
  153.             ;
  154.         if (*a == '=')
  155.             return (0);
  156.     }
  157.     printf("Bad arg: %s\n", arg);
  158.     exit(1);
  159. }
  160.  
  161. void
  162. done()
  163. {
  164.     close(1);
  165.     open("/dev/tty", 1);
  166.     if (Sync > 0)
  167.         sync();
  168.     if (Fsync > 0)
  169.         fsync(out);
  170.     if (Flush > 0)
  171.         flush(out);
  172.     stop();
  173. #ifndef    SVR4
  174.     if (ru != -1)
  175.         rusage();
  176. #endif
  177.     ptime(c << 2);
  178.     exit(0);
  179. }
  180.  
  181. #define    secs(tv)    (tv.tv_sec + tv.tv_usec / 1000000.0)
  182.  
  183. #ifndef    SVR4
  184. rusage()
  185. {
  186.     struct rusage r;
  187.     double  timespent();
  188.     double  idle;
  189.  
  190.     getrusage(RUSAGE_SELF, &r);
  191.     idle = timespent() - (secs(r.ru_stime) + secs(r.ru_utime));
  192.     idle = idle / timespent() * 100;
  193.     printf("sys=%g user=%g stalled=%.0f%% rd=%d wr=%d min=%d maj=%d\n",
  194.         secs(r.ru_stime), secs(r.ru_utime),
  195.         idle, r.ru_inblock, r.ru_oublock,
  196.         r.ru_minflt, r.ru_majflt);
  197. }
  198.  
  199. #endif
  200.  
  201. getarg(s, ac, av)
  202.     char   *s;
  203.     char  **av;
  204. {
  205.     register len, i;
  206.  
  207.     len = strlen(s);
  208.  
  209.     for (i = 1; i < ac; ++i)
  210.         if (!strncmp(av[i], s, len)) {
  211.             register bs = atoi(&av[i][len]);
  212.  
  213.             if (rindex(&av[i][len], 'k'))
  214.                 bs *= 1024;
  215.             else if (rindex(&av[i][len], 'm'))
  216.                 bs *= (1024 * 1024);
  217.             return (bs);
  218.         }
  219.     return (-1);
  220. }
  221.  
  222. char    *output;
  223.  
  224. getfile(s, ac, av)
  225.     char   *s;
  226.     char  **av;
  227. {
  228.     register ret, len, i;
  229.  
  230.     len = strlen(s);
  231.  
  232.     for (i = 1; i < ac; ++i) {
  233.         if (!strncmp(av[i], s, len)) {
  234.             if (av[i][0] == 'o') {
  235.                 if (!strcmp("of=internal", av[i]))
  236.                     return (-2);
  237.                 ret = creat(&av[i][len], 0644);
  238.                 if (ret == -1)
  239.                     error(&av[i][len]);
  240.                 output = &av[i][len];
  241.                 return (ret);
  242.             } else {
  243.                 if (!strcmp("if=internal", av[i]))
  244.                     return (-2);
  245.                 ret = open(&av[i][len], 0);
  246.                 if (ret == -1)
  247.                     error(&av[i][len]);
  248.                 return (ret);
  249.             }
  250.         }
  251.     }
  252.     return (-1);
  253. }
  254.  
  255. #ifdef    FLUSH
  256. flush()
  257. {
  258.     int    fd;
  259.     struct    stat sb;
  260.     caddr_t    where;
  261.  
  262.     if (output == NULL || (fd = open(output, 2)) == -1) 
  263.         return (warning("No output file"));
  264.     if (fstat(fd, &sb) == -1 || sb.st_size == 0)
  265.         return (warning(output));
  266.     where = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  267.     msync(where, sb.st_size, MS_INVALIDATE);
  268.     /* XXX - didn't unmap */
  269. }
  270. #endif
  271.  
  272. /*
  273.  * utilities for timing
  274.  */
  275. #include "stdio.h"
  276. #include "sys/types.h"
  277. #include "sys/time.h"
  278.  
  279. static struct timeval t1, t2;
  280.  
  281. warning(s)
  282.     char   *s;
  283. {
  284.     perror(s);
  285.     return (-1);
  286. }
  287.  
  288. error(s)
  289.     char   *s;
  290. {
  291.     perror(s);
  292.     exit(1);
  293. }
  294.  
  295. start() {
  296.     gettimeofday(&t1, (struct timezone *) 0);
  297. }
  298.  
  299. stop() {
  300.     gettimeofday(&t2, (struct timezone *) 0);
  301. }
  302.  
  303. ptime(bytes) {
  304.     ptransfer(bytes, &t1, &t2);
  305. }
  306. double 
  307. timespent()
  308. {
  309.     struct timeval td;
  310.  
  311.     tvsub(&td, &t2, &t1);
  312.     return (td.tv_sec + (td.tv_usec / 1000000.) + STARTUP);
  313. }
  314.  
  315. ptransfer(bytes, t0, t1)
  316.     struct timeval *t0, *t1;
  317. {
  318.     struct timeval td;
  319.     float   s, bs;
  320.  
  321.     tvsub(&td, t1, t0);
  322.     s = td.tv_sec + (td.tv_usec / 1000000.);
  323. #define    nz(x)    ((x) == 0 ? 1 : (x))
  324. #define    MB    (1024*1024.0)
  325.     bs = bytes / nz(s);
  326.     printf("%.2f MB in %.2f seconds (%.4f MB/sec)\n", bytes / MB, s, bs / MB);
  327. }
  328.  
  329. tvsub(tdiff, t1, t0)
  330.     struct timeval *tdiff, *t1, *t0;
  331. {
  332.  
  333.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  334.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  335.     if (tdiff->tv_usec < 0)
  336.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  337. }
  338.