home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / sys / ken / pipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-17  |  3.1 KB  |  223 lines

  1. #
  2. /*
  3.  */
  4.  
  5. #include "../param.h"
  6. #include "../systm.h"
  7. #include "../user.h"
  8. #include "../inode.h"
  9. #include "../file.h"
  10. #include "../reg.h"
  11.  
  12. /*
  13.  * Max allowable buffering per pipe.
  14.  * This is also the max size of the
  15.  * file created to implement the pipe.
  16.  * If this size is bigger than 4096,
  17.  * pipes will be implemented in LARG
  18.  * files, which is probably not good.
  19.  */
  20. #define    PIPSIZ    4096
  21.  
  22. /*
  23.  * The sys-pipe entry.
  24.  * Allocate an inode on the root device.
  25.  * Allocate 2 file structures.
  26.  * Put it all together with flags.
  27.  */
  28. pipe()
  29. {
  30.     register *ip, *rf, *wf;
  31.     int r;
  32.  
  33.     ip = ialloc(rootdev);
  34.     if(ip == NULL)
  35.         return;
  36.     rf = falloc();
  37.     if(rf == NULL) {
  38.         iput(ip);
  39.         return;
  40.     }
  41.     r = u.u_ar0[R0];
  42.     wf = falloc();
  43.     if(wf == NULL) {
  44.         rf->f_count = 0;
  45.         u.u_ofile[r] = NULL;
  46.         iput(ip);
  47.         return;
  48.     }
  49.     u.u_ar0[R1] = u.u_ar0[R0];
  50.     u.u_ar0[R0] = r;
  51.     wf->f_flag = FWRITE|FPIPE;
  52.     wf->f_inode = ip;
  53.     rf->f_flag = FREAD|FPIPE;
  54.     rf->f_inode = ip;
  55.     ip->i_count = 2;
  56.     ip->i_flag = IACC|IUPD;
  57.     ip->i_mode = IALLOC;
  58. }
  59.  
  60. /*
  61.  * Read call directed to a pipe.
  62.  */
  63. readp(fp)
  64. int *fp;
  65. {
  66.     register *rp, *ip;
  67.  
  68.     rp = fp;
  69.     ip = rp->f_inode;
  70.  
  71. loop:
  72.     /*
  73.      * Very conservative locking.
  74.      */
  75.  
  76.     plock(ip);
  77.  
  78.     /*
  79.      * If the head (read) has caught up with
  80.      * the tail (write), reset both to 0.
  81.      */
  82.  
  83.     if(rp->f_offset[1] == ip->i_size1) {
  84.         if(rp->f_offset[1] != 0) {
  85.             rp->f_offset[1] = 0;
  86.             ip->i_size1 = 0;
  87.             if(ip->i_mode&IWRITE) {
  88.                 ip->i_mode =& ~IWRITE;
  89.                 wakeup(ip+1);
  90.             }
  91.         }
  92.  
  93.         /*
  94.          * If there are not both reader and
  95.          * writer active, return without
  96.          * satisfying read.
  97.          */
  98.  
  99.         prele(ip);
  100.         if(ip->i_count < 2)
  101.             return;
  102.         ip->i_mode =| IREAD;
  103.         sleep(ip+2, PPIPE);
  104.         goto loop;
  105.     }
  106.  
  107.     /*
  108.      * Read and return
  109.      */
  110.  
  111.     u.u_offset[0] = 0;
  112.     u.u_offset[1] = rp->f_offset[1];
  113.     readi(ip);
  114.     rp->f_offset[1] = u.u_offset[1];
  115.     prele(ip);
  116. }
  117.  
  118. /*
  119.  * Write call directed to a pipe.
  120.  */
  121. writep(fp)
  122. {
  123.     register *rp, *ip, c;
  124.  
  125.     rp = fp;
  126.     ip = rp->f_inode;
  127.     c = u.u_count;
  128.  
  129. loop:
  130.  
  131.     /*
  132.      * If all done, return.
  133.      */
  134.  
  135.     plock(ip);
  136.     if(c == 0) {
  137.         prele(ip);
  138.         u.u_count = 0;
  139.         return;
  140.     }
  141.  
  142.     /*
  143.      * If there are not both read and
  144.      * write sides of the pipe active,
  145.      * return error and signal too.
  146.      */
  147.  
  148.     if(ip->i_count < 2) {
  149.         prele(ip);
  150.         u.u_error = EPIPE;
  151.         psignal(u.u_procp, SIGPIPE);
  152.         return;
  153.     }
  154.  
  155.     /*
  156.      * If the pipe is full,
  157.      * wait for reads to deplete
  158.      * and truncate it.
  159.      */
  160.  
  161.     if(ip->i_size1 == PIPSIZ) {
  162.         ip->i_mode =| IWRITE;
  163.         prele(ip);
  164.         sleep(ip+1, PPIPE);
  165.         goto loop;
  166.     }
  167.  
  168.     /*
  169.      * Write what is possible and
  170.      * loop back.
  171.      */
  172.  
  173.     u.u_offset[0] = 0;
  174.     u.u_offset[1] = ip->i_size1;
  175.     u.u_count = min(c, PIPSIZ-u.u_offset[1]);
  176.     c =- u.u_count;
  177.     writei(ip);
  178.     prele(ip);
  179.     if(ip->i_mode&IREAD) {
  180.         ip->i_mode =& ~IREAD;
  181.         wakeup(ip+2);
  182.     }
  183.     goto loop;
  184. }
  185.  
  186. /*
  187.  * Lock a pipe.
  188.  * If its already locked,
  189.  * set the WANT bit and sleep.
  190.  */
  191. plock(ip)
  192. int *ip;
  193. {
  194.     register *rp;
  195.  
  196.     rp = ip;
  197.     while(rp->i_flag&ILOCK) {
  198.         rp->i_flag =| IWANT;
  199.         sleep(rp, PPIPE);
  200.     }
  201.     rp->i_flag =| ILOCK;
  202. }
  203.  
  204. /*
  205.  * Unlock a pipe.
  206.  * If WANT bit is on,
  207.  * wakeup.
  208.  * This routine is also used
  209.  * to unlock inodes in general.
  210.  */
  211. prele(ip)
  212. int *ip;
  213. {
  214.     register *rp;
  215.  
  216.     rp = ip;
  217.     rp->i_flag =& ~ILOCK;
  218.     if(rp->i_flag&IWANT) {
  219.         rp->i_flag =& ~IWANT;
  220.         wakeup(rp);
  221.     }
  222. }
  223.