/* @(#)pipe.c 1.4 */ #include "sys/param.h" #include "sys/types.h" #include "sys/systm.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/buf.h" #include "sys/filsys.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/inode.h" #include "sys/file.h" #include "sys/mount.h" #include "sys/var.h" /* * The sys-pipe entry. * Allocate an inode on the root device. * Allocate 2 file structures. * Put it all together with flags. */ pipe() { register struct inode *ip; register struct file *rf, *wf; int r; register struct user *up; up = &u; ip = ialloc(getpdev(), IFIFO, 0); if(ip == NULL) return; rf = falloc(ip, FREAD); if(rf == NULL) { iput(ip); return; } r = up->u_rval1; wf = falloc(ip, FWRITE); if(wf == NULL) { rf->f_count = 0; rf->f_next = ffreelist; ffreelist = rf; up->u_ofile[r] = NULL; iput(ip); return; } up->u_rval2 = up->u_rval1; up->u_rval1 = r; ip->i_count = 2; ip->i_frcnt = 1; ip->i_fwcnt = 1; prele(ip); } /* * Open a pipe * Check read and write counts, delay as necessary */ openp(ip, mode) register struct inode *ip; register mode; { if (mode&FREAD) { if (ip->i_frcnt++ == 0) wakeup((caddr_t)&ip->i_frcnt); } if (mode&FWRITE) { if (mode&FNDELAY && ip->i_frcnt == 0) { u.u_error = ENXIO; return; } if (ip->i_fwcnt++ == 0) wakeup((caddr_t)&ip->i_fwcnt); } if (mode&FREAD) { while (ip->i_fwcnt == 0) { if (mode&FNDELAY || ip->i_size) return; (void) sleep((caddr_t)&ip->i_fwcnt, PPIPE); } } if (mode&FWRITE) { while (ip->i_frcnt == 0) (void) sleep((caddr_t)&ip->i_frcnt, PPIPE); } } /* * Close a pipe * Update counts and cleanup */ closep(ip, mode) register struct inode *ip; register mode; { register i; daddr_t bn; if (mode&FREAD) { if ((--ip->i_frcnt == 0) && (ip->i_fflag&IFIW)) { ip->i_fflag &= ~IFIW; wakeup((caddr_t)&ip->i_fwcnt); } } if (mode&FWRITE) { if ((--ip->i_fwcnt == 0) && (ip->i_fflag&IFIR)) { ip->i_fflag &= ~IFIR; wakeup((caddr_t)&ip->i_frcnt); } } if ((ip->i_frcnt == 0) && (ip->i_fwcnt == 0)) { for (i=NFADDR-1; i>=0; i--) { bn = ip->i_faddr[i]; if (bn == (daddr_t)0) continue; ip->i_faddr[i] = (daddr_t)0; free(ip->i_dev, bn); } ip->i_size = 0; ip->i_frptr = 0; ip->i_fwptr = 0; ip->i_flag |= IUPD|ICHG; } } /* * Lock a pipe. * If its already locked, * set the WANT bit and sleep. */ plock(ip) register struct inode *ip; { while(ip->i_flag&ILOCK) { ip->i_flag |= IWANT; (void) sleep((caddr_t)ip, PINOD); } ip->i_flag |= ILOCK; } /* * Unlock a pipe. * If WANT bit is on, * wakeup. * This routine is also used * to unlock inodes in general. */ prele(ip) register struct inode *ip; { ip->i_flag &= ~ILOCK; if(ip->i_flag&IWANT) { ip->i_flag &= ~IWANT; wakeup((caddr_t)ip); } } /* * Return the mounted pipe device */ dev_t getpdev() { register struct mount *mp; register dev_t dev; dev = pipedev; for (mp = &mount[0]; mp < (struct mount *)v.ve_mount; mp++) if (mp->m_flags != MFREE && dev == mp->m_dev && mp->m_bufp->b_un.b_filsys->s_ronly==0) return(dev); return(rootdev); }