home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / UTIL / buffer.c < prev    next >
C/C++ Source or Header  |  1993-01-16  |  5KB  |  253 lines

  1. /*
  2.  * $Header: H:/SRC.SSB/util/buffer.c,v 1.2 1992/02/14 19:00:39 ak Exp $
  3.  *
  4.  *    Pipe buffer.
  5.  *
  6.  * $Log: buffer.c,v $
  7.  * Revision 1.2  1992/02/14  19:00:39  ak
  8.  * *** empty log message ***
  9.  *
  10.  * Revision 1.1.1.1  1991/12/12  21:26:33  ak
  11.  * Initial checkin.
  12.  *
  13.  * Revision 1.1  1991/12/12  21:26:29  ak
  14.  * Initial revision
  15.  *
  16.  */
  17.  
  18. static char *rcsid = "$Id: buffer.c,v 1.2 1992/02/14 19:00:39 ak Exp $";
  19.  
  20. /*
  21.  * Pipe buffer.
  22.  * Needs large memory model and float.
  23.  */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <getopt.h>
  28. #define INCL_DOSCALLS
  29. #define INCL_DOSMEMMGR
  30. #define INCL_DOSPROCESS
  31. #define INCL_DOSSIGNALS
  32. #include <os2.h>
  33. #include <dos.h>
  34.  
  35.  
  36. #define BUFSIZE        32768U
  37. #define NBUFFERS    (unsigned)(4L * 1024L * 1024L / BUFSIZE)
  38. #define NBUFS20        (unsigned)(2L * 1024L * 1024L / BUFSIZE)
  39.  
  40. typedef struct Buffer {
  41.     BYTE *    buf;        /* 32KB buffer */
  42.     USHORT    nbytes;        /* number of bytes in buffer */
  43. } Buffer;
  44.  
  45. Buffer        buffers [NBUFFERS];    /* the buffers */
  46. int        nbuffers = NBUFFERS;    /* allocated buffers */
  47. int        rx = 0,            /* read index */
  48.         wx = 0;            /* write index */
  49. volatile int    nb = 0;            /* number of filled buffers */
  50.  
  51. int        r_stack [2048];
  52. volatile USHORT    r_tid;
  53. USHORT        w_tid;
  54.  
  55. USHORT        bufsize = BUFSIZE;    /* buffer size */
  56. USHORT        reblock = 0;        /* reblock size */
  57.  
  58. int        ilevel;
  59. int        olevel;
  60.  
  61. void _far
  62. r_thread(void)
  63. {
  64.     Buffer    *bp;
  65.     USHORT    nreq, nr, nbytes;
  66.     short    eof;
  67.  
  68.     for (eof = 0; !eof; ) {
  69.         if (nb >= ilevel) {
  70.             DosSuspendThread(r_tid);
  71.             continue;
  72.         }
  73.  
  74.         while (nb < nbuffers && !eof) {
  75.             bp = &buffers[rx];
  76.             nbytes = 0;
  77.             do {
  78.                 if (DosRead(0, bp->buf + nbytes, bufsize - nbytes, &nr)) {
  79.                     DosSuspendThread(w_tid);
  80.                     fprintf(stderr, "buffer: read error\n");
  81.                     exit(1);
  82.                 }
  83.                 nbytes += nr;
  84.             } while (nr && nbytes < bufsize);
  85.  
  86.             if (nbytes == 0) {
  87.                 eof = 1;
  88.                 break;
  89.             }
  90.  
  91.             if (reblock && (nr = nbytes % reblock) != 0) {
  92.                 memset(bp->buf + nbytes, 0, reblock - nr);
  93.                 nbytes += reblock - nr;
  94.                 eof = 1;
  95.             }
  96.             bp->nbytes = nbytes;
  97.  
  98.             rx = (rx + 1) % nbuffers;
  99.             ++nb;
  100.             DosResumeThread(w_tid);
  101.         }
  102.     }
  103.     r_tid = 0;
  104.     DosResumeThread(w_tid);
  105. }
  106.  
  107. void
  108. w_thread(void)
  109. {
  110.     Buffer    *bp;
  111.     USHORT    nw;
  112.  
  113.     while (r_tid || nb) {
  114.         if (r_tid && nb < olevel) {
  115.             DosSuspendThread(w_tid);
  116.             continue;
  117.         }
  118.         while (nb) {
  119.             bp = &buffers[wx];
  120.             if (DosWrite(1, bp->buf, bp->nbytes, &nw)) {
  121.                 DosSuspendThread(r_tid);
  122.                 fprintf(stderr, "buffer: write error\n");
  123.                 exit(1);
  124.             }
  125.             if (nw != bp->nbytes) {
  126.                 DosSuspendThread(r_tid);
  127.                 fprintf(stderr, "buffer: write short\n");
  128.                 exit(1);
  129.             }
  130.             wx = (wx + 1) % nbuffers;
  131.             --nb;
  132.             DosResumeThread(r_tid);
  133.         }
  134.     }
  135.     w_tid = 0;
  136. }
  137.  
  138. void
  139. setFail(int fd)
  140. {
  141.     USHORT state;
  142.     DosQFHandState(fd, &state);
  143.     state &=~OPEN_FLAGS_RANDOMSEQUENTIAL;
  144.     state |= OPEN_FLAGS_SEQUENTIAL | OPEN_FLAGS_NO_CACHE
  145.             | OPEN_FLAGS_FAIL_ON_ERROR;
  146.     DosSetFHandState(fd, state);
  147. }
  148.  
  149. main(int argc, char **argv)
  150. {
  151.     PFNSIGHANDLER    oldf;
  152.     USHORT        olda;
  153.     int        i;
  154.     ULONG        size;
  155.     double        it, ot;
  156.  
  157.     setFail(0);
  158.     setFail(1);
  159.  
  160.     DosSetSigHandler((PFNSIGHANDLER)0, &oldf, &olda, SIGA_KILL, SIG_CTRLC);
  161.     DosSetSigHandler((PFNSIGHANDLER)0, &oldf, &olda, SIGA_KILL, SIG_CTRLBREAK);
  162.  
  163. #ifdef __ZTC__
  164.     if (_osmajor == 10) {
  165. #else
  166.     if ((_osversion & 0xFF) == 10) {
  167. #endif
  168.         /* OS/2 1.x */
  169.         DosMemAvail(&size);
  170.         size -= 1024L * 1024L;
  171.         nbuffers = size / BUFSIZE;
  172.         if (nbuffers < 2)
  173.             nbuffers = 2;
  174.         else if (nbuffers > NBUFFERS)
  175.             nbuffers = NBUFFERS;
  176.     } else {
  177.         /* OS/2 2.x */
  178.         char *env = getenv("BUFFER");
  179.         nbuffers = env ? strtoul(env, NULL, 0) * 1024L / BUFSIZE
  180.                    : NBUFS20;
  181.     }
  182.  
  183.     it = ot = 1.0;
  184.  
  185.     while ((i = getopt(argc, argv, "s:b:i:o:")) != EOF) {
  186.         switch (i) {
  187.         case 's':
  188.             nbuffers = (strtoul(optarg, NULL, 0) * 1024L) / BUFSIZE;
  189.             if (nbuffers < 2)
  190.                 goto usage;
  191.             break;
  192.         case 'b':
  193.             reblock = strtoul(optarg, NULL, 0);
  194.             if (reblock < 1 || reblock > BUFSIZE)
  195.                 goto usage;
  196.             bufsize -= bufsize % reblock;
  197.             break;
  198.         case 'i':
  199.             it = atof(optarg) / 100.0;
  200.             break;
  201.         case 'o':
  202.             ot = atof(optarg) / 100.0;
  203.             break;
  204.         default:
  205.         usage:    fprintf(stderr, "buffer [options]\n"
  206.                     " -b<n>    buffer size in KB (%u..4096), default=%u\n"
  207.                     " -p<n>    blocking size (<= %u)\n"
  208.                     " -i<n>    read when buffer <n>%% free, default=100\n"
  209.                     " -o<n>    write when buffer <n>%% full, default=100\n",
  210.                     BUFSIZE / (1024 / 2),
  211.                     nbuffers * 32,
  212.                     BUFSIZE);
  213.             exit(2);
  214.         }
  215.     }
  216.  
  217.     ilevel = (1.0 - it) * nbuffers;
  218.     if (ilevel <= 0)
  219.         ilevel = 1;
  220.     else if (ilevel > nbuffers)
  221.         ilevel = nbuffers;
  222.  
  223.     olevel = ot * nbuffers;
  224.     if (olevel < 1)
  225.         olevel = 1;
  226.     else if (olevel > nbuffers)
  227.         olevel = nbuffers;
  228.  
  229.     for (i = 0; i < nbuffers; ++i) {
  230.         USHORT sel;
  231.         if (DosAllocSeg(bufsize, &sel, 0)) {
  232.             if (i < 2) {
  233.                 fprintf(stderr, "buffer: Not enough memory\n");
  234.                 exit(2);
  235.             }
  236.             nbuffers = i;
  237.             break;
  238.         }
  239.         buffers[i].buf = MAKEP(sel, 0);
  240.     }
  241.  
  242.     w_tid = 1;
  243.     if (DosCreateThread(r_thread, &r_tid, (PBYTE)&r_stack[2048])) {
  244.         fprintf(stderr, "buffer: No thread\n");
  245.         exit(2);
  246.     }
  247.  
  248.     w_thread();
  249.  
  250.     exit(0);
  251. }
  252.  
  253.