File:  [MW Coherent from dump] / coherent / d / PS2_KERNEL / coh.386 / pipe.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* $Header: /var/lib/cvsd/repos/coherent/coherent/d/PS2_KERNEL/coh.386/pipe.c,v 1.1.1.1 2019/05/29 04:56:39 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Pipes.
 *
 * $Log: pipe.c,v $
 * Revision 1.1.1.1  2019/05/29 04:56:39  root
 * coherent
 *
 * Revision 1.2  92/08/04  12:33:59  bin
 * changed for ker 59
 * 
 * Revision 1.2  92/01/06  11:59:52  hal
 * Compile with cc.mwc.
 * 
 * Revision 1.1	88/03/24  16:14:07	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/pipe.c
 * Added check for non-blocking read and write if (io_flag & IPNDLY) set.
 * Eliminated use of i_a inode field since now included in inode macros.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <signal.h>

/*
 * Create and return a locked pipe inode.  This is called from the
 * pipe system call.
 */
INODE *
pmake(mode)
{
	register INODE *ip;

	if ((ip=ialloc(pipedev, IFPIPE|mode)) != NULL) {
		iclear(ip);
		ip->i_pnc = 0;
		ip->i_prx = 0;
		ip->i_pwx = 0;
	}
	return (ip);
}

/*
 * Open a pipe given the inode pointer.
 */
popen(ip, mode)
{
	T_HAL(0x10, printf("popen(%x,%x) ", ip, mode));
}

/*
 * Close a pipe inode.
 */
pclose(ip)
register INODE *ip;
{
	if (ip->i_refc == 2) {
		pevent(ip);
		ip->i_flag |= IFEOF;
	}
}

/*
 * Only one end of the pipe is going to be left.
 */
pevent(ip)
register INODE *ip;
{
	if ((ip->i_flag&IFWFR) != 0) {
		ip->i_flag &= ~IFWFR;
		wakeup((char *)&ip->i_pwx);
	}
	if ((ip->i_flag&IFWFW) != 0) {
		ip->i_flag &= ~IFWFW;
		wakeup((char *)&ip->i_prx);
	}
}

/*
 * Read from a pipe.  The given inode is locked.
 */
pread(ip, iop)
register INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned ioc;
#ifdef TRACER
	int old_ioc = iop->io_ioc;
#endif /* TRACER */

	while (ip->i_pnc == 0) {

		/*
		 * Logical End of File.
		 */
		if ((ip->i_flag&IFEOF) != 0) {
			ip->i_flag &= ~IFEOF;
			break;
		}

		/*
		 * Nobody left to write.
		 */
		if (ip->i_nlink==0 && ip->i_refc<2)
			break;

		/*
		 * Non-blocking read.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			goto pread_done;
		}

		/*
		 * Wait for pipe data.
		 */
		ip->i_flag |= IFWFW;
		iunlock(ip);
		v_sleep((char *)&ip->i_prx, CVPIPE, IVPIPE, SVPIPE, "pipe data");
		/* Wait for pipe data.  */
		ilock(ip);
	}

	/*
	 * Clear EOF flag.
	 */
	if ((ip->i_flag&IFEOF)!=0 && ip->i_pnc==0)
		ip->i_flag &= ~IFEOF;

	ioc = iop->io_ioc;
	while (u.u_error==0 && ioc>0 && ip->i_pnc>0) {

		/*
		 * Calculate length of data to be read.
		 */
		if ((n=PIPSIZE-ip->i_prx) > ioc)
			n = ioc;
		if (n > ip->i_pnc)
			n = ip->i_pnc;

		/*
		 * Read data.
		 */
		iop->io_ioc = n;
		iop->io_seek = ip->i_prx;
		fread(ip, iop);
		n -= iop->io_ioc;
		if ((ip->i_prx+=n) == PIPSIZE)
			ip->i_prx = 0;
		ip->i_pnc -= n;
		ioc -= n;
	}
	iop->io_ioc = ioc;

	/*
	 * Wake processes waiting to write.
	 */
	if ((ip->i_flag&IFWFR)!=0 && ip->i_pnc<PIPSIZE) {
		ip->i_flag &= ~IFWFR;
		wakeup((char *)&ip->i_pwx);
	}

pread_done:
	T_HAL(0x10, printf("pread:%d ", old_ioc - iop->io_ioc));
	return;
}

/*
 * Write to a pipe.  The given inode is locked.
 */
pwrite(ip, iop)
register INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned ioc;
#ifdef TRACER
	int old_ioc = iop->io_ioc;
#endif /* TRACER */

	ioc = iop->io_ioc;
	while (u.u_error==0 && ioc>0) {

		/*
		 * Nobody left to read.
		 */
		if ( (ip->i_refc < 2) && (ip->i_nlink == 0) ) {
			u.u_error = EPIPE;
			sendsig(SIGPIPE, SELF);
			goto pwrite_done;
		}

		/*
		 * Calculate free space in pipe.
		 */
		if ( (n=PIPSIZE-ip->i_pwx) > ioc )
			n = ioc;
		if (n > PIPSIZE-ip->i_pnc)
			n = PIPSIZE - ip->i_pnc;

		/*
		 * Non-blocking write.
		 */
		if ( iop->io_flag & IONDLY ) {
			if ( (n != ioc) || (ip->i_flag & IFEOF) ) {
				u.u_error = EAGAIN;
				goto pwrite_done;
			}
		}

		/*
		 * Insufficent space or EOF still pending.
		 */
		if (n==0 || (ip->i_flag&IFEOF)!=0) {
			ip->i_flag |= IFWFR;
			iunlock(ip);
			v_sleep((char *)&ip->i_pwx, CVPIPE, IVPIPE, SVPIPE, "pwrite");
			/* Insufficent space or EOF still pending.  */
			ilock(ip);
			continue;
		}
		iop->io_ioc = n;
		iop->io_seek = ip->i_pwx;
		fwrite(ip, iop);
		n -= iop->io_ioc;
		if ((ip->i_pwx+=n) == PIPSIZE)
			ip->i_pwx = 0;
		ip->i_pnc += n;
		ioc -= n;

		/*
		 * Wait processes waiting to read.
		 */
		if ((ip->i_flag&IFWFW) && ip->i_pnc>0) {
			ip->i_flag &= ~IFWFW;
			wakeup((char *)&ip->i_prx);
		}
	}
	iop->io_ioc = ioc;

pwrite_done:
	T_HAL(0x10, printf("pwrite:%d ", old_ioc - iop->io_ioc));
	return;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.