7700: #include "../param.h"
7701: #include "../systm.h"
7702: #include "../user.h"
7703: #include "../inode.h"
7704: #include "../file.h"
7705: #include "../reg.h"
7706:
7707: /*
7708: * Max allowable buffering per pipe.
7709: * This is also the max size of the
7710: * file created to implement the pipe.
7711: * If this size is bigger than 4096,
7712: * pipes will be implemented in LARG
7713: * files, which is probably not good.
7714: */
7715: #define PIPSIZ 4096
7716:
7717: /*
7718: * The sys-pipe entry.
7719: * Allocate an inode on the root device.
7720: * Allocate 2 file structures.
7721: * Put it all together with flags.
7722: */
7723: pipe()
7724: {
7725: register *ip, *rf, *wf;
7726: int r;
7727:
7728: ip = ialloc(rootdev);
7729: if(ip == NULL)
7730: return;
7731: rf = falloc();
7732: if(rf == NULL) {
7733: iput(ip);
7734: return;
7735: }
7736: r = u.u_ar0[R0];
7737: wf = falloc();
7738: if(wf == NULL) {
7739: rf->f_count = 0;
7740: u.u_ofile[r] = NULL;
7741: iput(ip);
7742: return;
7743: }
7744: u.u_ar0[R1] = u.u_ar0[R0];
7745: u.u_ar0[R0] = r;
7746: wf->f_flag = FWRITE|FPIPE;
7747: wf->f_inode = ip;
7748: rf->f_flag = FREAD|FPIPE;
7749: rf->f_inode = ip;
7750: ip->i_count = 2;
7751: ip->i_flag = IACC|IUPD;
7752: ip->i_mode = IALLOC;
7753: }
7754: /* --------------------------- */
7755:
7756: /* Read call directed to a pipe.
7757: */
7758: readp(fp)
7759: int *fp;
7760: {
7761: register *rp, *ip;
7762:
7763: rp = fp;
7764: ip = rp->f_inode;
7765: loop:
7766: /* Very conservative locking.
7767: */
7768: plock(ip);
7769: /* If the head (read) has caught up with
7770: * the tail (write), reset both to 0.
7771: */
7772: if(rp->f_offset[1] == ip->i_size1) {
7773: if(rp->f_offset[1] != 0) {
7774: rp->f_offset[1] = 0;
7775: ip->i_size1 = 0;
7776: if(ip->i_mode&IWRITE) {
7777: ip->i_mode =& ~IWRITE;
7778: wakeup(ip+1);
7779: }
7780: }
7781:
7782: /* If there are not both reader and
7783: * writer active, return without
7784: * satisfying read.
7785: */
7786: prele(ip);
7787: if(ip->i_count < 2)
7788: return;
7789: ip->i_mode =| IREAD;
7790: sleep(ip+2, PPIPE);
7791: goto loop;
7792: }
7793: /* Read and return
7794: */
7795: u.u_offset[0] = 0;
7796: u.u_offset[1] = rp->f_offset[1];
7797: readi(ip);
7798: rp->f_offset[1] = u.u_offset[1];
7799: prele(ip);
7800: }
7801: /* --------------------------- */
7802:
7803: /* Write call directed to a pipe.
7804: */
7805: writep(fp)
7806: {
7807: register *rp, *ip, c;
7808:
7809: rp = fp;
7810: ip = rp->f_inode;
7811: c = u.u_count;
7812: loop:
7813: /* If all done, return.
7814: */
7815: plock(ip);
7816: if(c == 0) {
7817: prele(ip);
7818: u.u_count = 0;
7819: return;
7820: }
7821: /* If there are not both read and
7822: * write sides of the pipe active,
7823: * return error and signal too.
7824: */
7825: if(ip->i_count < 2) {
7826: prele(ip);
7827: u.u_error = EPIPE;
7828: psignal(u.u_procp, SIGPIPE);
7829: return;
7830: }
7831: /* If the pipe is full,
7832: * wait for reads to deplete
7833: * and truncate it.
7834: */
7835: if(ip->i_size1 == PIPSIZ) {
7836: ip->i_mode =| IWRITE;
7837: prele(ip);
7838: sleep(ip+1, PPIPE);
7839: goto loop;
7840: }
7841: /* Write what is possible and
7842: * loop back.
7843: */
7844: u.u_offset[0] = 0;
7845: u.u_offset[1] = ip->i_size1;
7846: u.u_count = min(c, PIPSIZ-u.u_offset[1]);
7847: c =- u.u_count;
7848: writei(ip);
7849: prele(ip);
7850: if(ip->i_mode&IREAD) {
7851: ip->i_mode =& ~IREAD;
7852: wakeup(ip+2);
7853: }
7854: goto loop;
7855: }
7856: /* --------------------------- */
7857:
7858: /* Lock a pipe.
7859: * If its already locked,
7860: * set the WANT bit and sleep.
7861: */
7862: plock(ip)
7863: int *ip;
7864: {
7865: register *rp;
7866:
7867: rp = ip;
7868: while(rp->i_flag&ILOCK) {
7869: rp->i_flag =| IWANT;
7870: sleep(rp, PPIPE);
7871: }
7872: rp->i_flag =| ILOCK;
7873: }
7874: /* --------------------------- */
7875:
7876: /* Unlock a pipe.
7877: * If WANT bit is on,
7878: * wakeup.
7879: * This routine is also used
7880: * to unlock inodes in general.
7881: */
7882: prele(ip)
7883: int *ip;
7884: {
7885: register *rp;
7886:
7887: rp = ip;
7888: rp->i_flag =& ~ILOCK;
7889: if(rp->i_flag&IWANT) {
7890: rp->i_flag =& ~IWANT;
7891: wakeup(rp);
7892: }
7893: }
7894: /* --------------------------- */