/* @(#)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);}