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: /* --------------------------- */