⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fifo_gnodeops.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)fifo_gnodeops.c	4.2	(ULTRIX)	2/28/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1988,89 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Copyright (c) 1986 by Sun Microsystems, Inc. *//************************************************************************ *			Modification History * * 27 Feb 91 -- chet *	Fix filesystem timestamping * * 15-Feb-90 -- prs *	Added an smp primitive workaround to fifo_rele(). * * 12-Jan-90 -- prs *	Modified to use internal ref counters for allocation and *	deallocation of fifo structures. * * 24-Jul-89 -- prs *	Fixed setjmp case in fifo_open(). * * 04-Jan-89 -- prs *	Fixed an ordering bug in fifo_rele that attempted to unlock *	a gnode after its memory segment was released. * * 28-Sep-88 -- jaw *	add locks to fifo_select * * 14-Sep-88 -- prs *	Added fifo_gupdat() and support to update time fields for *	fifo gnodes. This change was required by POSIX. * * 06-Sep-88 -- prs *	SMP changes to fifo_open(), fifo_close() and fifo_rele(). * * 11-Jul-88 -- prs *	Added FIOGETOWN, FIOSETOWN, and FIOASYNC cases to fifo_ioctl(). *	Added the routine fifo_wakeup() to send a SIGIO signal, *	when ASYNC is enabled on a fifo. Also, added calls to fifo_wakeup *	from fifo_close(), when either side of a pipe is shutting down. * * 27-Apr-88 -- prs *	Fixed fifo_select code. * * 08-Apr-88 -- prs *	Fixed fifo_stat to bzero stat structure if type is GFPIPE. * * 02-Mar-88 -- prs *      Fixed fifo_lock and fifo_unlock routines to handle locking *      a GFPIPE. * * 10-Feb-88 -- prs *	New fifo code. * ************************************************************************/#include "fifonode.h"#include "fifo.h"#include "../net/rpc/types.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/mount.h"#include "../h/kernel.h"#include "../h/gnode_common.h"#include "../h/gnode.h"#include "../h/ioctl.h"#include "../h/proc.h"#include "../h/uio.h"#include "../h/devio.h"#include "../h/conf.h"#include "../h/file.h"#include "../h/stat.h"#include "../h/cmap.h"#include "../h/exec.h"/* SystemV-compatible FIFO implementation */static struct fifo_bufhdr *fifo_bufalloc();static struct fifo_bufhdr *fifo_buffree();struct gnode * spec_namei();int fifo_open();int fifo_close();int fifo_rwgp();int fifo_ioctl();int fifo_select();int spec_access();int spec_link();int spec_unlink();int fifo_lock();int fifo_unlock();int fifo_rele();int spec_inactive();int spec_badop();int spec_rename();int spec_noop();int spec_trunc();int spec_syncgp();int ufs_seek();int fifo_stat();int fifo_gupdat();int spec_getval();struct gnode_ops FIFO_gnode_ops = {	spec_namei,	/* namei */	spec_link,	/* link */	spec_unlink,	/* unlink */	0,		/* mkdir */	spec_noop,	/* rmdir */	0,		/* maknode */	spec_rename,	/* rename */	spec_noop,	/* getdirents */	fifo_rele,	/* rele */	spec_syncgp,	/* syncgp */	0,		/* trunc */	0,		/* getval */	fifo_rwgp,	/* read, write */	0,		/* rlock */	ufs_seek,	/* seek */	fifo_stat,	/* stat */	fifo_lock,	/* lock */	fifo_unlock,	/* unlock */	fifo_gupdat,	/* update */	fifo_open,	/* open */	fifo_close,	/* close */	fifo_select,	/* select */	0,		/* readlink */	0,		/* symlink */	fifo_ioctl,	/* fcntl */	0,		/* freegn */	0		/* bmap */};struct gnode_ops *fifo_gnodeops = &FIFO_gnode_ops;/* * open a fifo -- sleep until there are at least one reader & one writer *//*ARGSUSED*/intfifo_open(gp, flag)	struct gnode *gp;	int flag;{	register struct fifonode *fp;	gfs_lock(gp);	if (gp->g_fifo == NULL) {                KM_ALLOC(gp->g_fifo, struct fifonode *,                         sizeof(struct fifonode), KM_TEMP, KM_CLEAR);                if (gp->g_fifo == NULL) {                        printf("fifo_open: Couldn't alloc %d bytes\n",                                sizeof(struct fifonode));                        panic("fifo_open: KM_ALLOC");                }	}	/*	 * Setjmp in case open is interrupted.	 * If it is, close and return error.	 */	if (setjmp(&u.u_qsave)) {		(void) fifo_close(gp, flag & FMASK);		return (EINTR);	}	fp = GTOF(gp);	if (flag & FREAD) {		if (fp->fn_rcnt++ == 0)			/* if any writers waiting, wake them up */			wakeup((caddr_t) &fp->fn_rcnt);	}	if (flag & FWRITE) {		if ((flag & (FNDELAY|FNBLOCK)) && (fp->fn_rcnt == 0)) {			gfs_unlock(gp);			return (ENXIO);		}		if (fp->fn_wcnt++ == 0)			/* if any readers waiting, wake them up */			wakeup((caddr_t) &fp->fn_wcnt);	}	if (flag & FREAD) {		while (fp->fn_wcnt == 0) {			/* if no delay, or data in fifo, open is complete */			if ((flag & (FNDELAY|FNBLOCK)) || fp->fn_size) {				gfs_unlock(gp);				return (0);			}			(void) sleep_unlock((caddr_t) &fp->fn_wcnt, PPIPE, 					    &gp->g_lk);			gfs_lock(gp);		}	}	if (flag & FWRITE) {		while (fp->fn_rcnt == 0) {			(void) sleep_unlock((caddr_t) &fp->fn_rcnt, PPIPE,				     &gp->g_lk);			gfs_lock(gp);		}	}	gfs_unlock(gp);	return (0);}/* * close a fifo * On final close, all buffered data goes away *//*ARGSUSED*/intfifo_close(gp, flag)	struct gnode *gp;	int flag;{	register struct fifonode *fp;	register struct fifo_bufhdr *bp;	register struct	ucred *cred = u.u_cred;	gfs_lock(gp);	fp = GTOF(gp);	if (flag & FREAD) {		if (--fp->fn_rcnt == 0) {			if (fp->fn_flag & IFIW) {				fp->fn_flag &= ~IFIW;				wakeup((caddr_t) &fp->fn_wcnt);			}			if (fp->fn_wselp) {				selwakeup(fp->fn_wselp, fp->fn_flag & IF_WCOLL);				fp->fn_flag &= ~IF_WCOLL;				fp->fn_wselp = 0;			}			if ((fp->fn_flag & IF_RASYNC) || 			    (fp->fn_flag & IF_WASYNC)) {				fifo_wakeup(fp);				fp->fn_flag &= ~IF_RASYNC;				fp->fn_rpgrp = 0;			}		}	}	if (flag & FWRITE) {		if (--fp->fn_wcnt == 0) {			if (fp->fn_flag & IFIR) {				fp->fn_flag &= ~IFIR;				wakeup((caddr_t) &fp->fn_rcnt);			}			if (fp->fn_rselp) {				selwakeup(fp->fn_rselp, fp->fn_flag & IF_RCOLL);				fp->fn_flag &= ~IF_RCOLL;				fp->fn_rselp = 0;			}			if ((fp->fn_flag & IF_RASYNC) || 			    (fp->fn_flag & IF_WASYNC)) {				fifo_wakeup(fp);				fp->fn_flag &= ~IF_WASYNC;				fp->fn_wpgrp = 0;			}		}	}	if ((fp->fn_rcnt == 0) && (fp->fn_wcnt == 0)) {		/* free all buffers associated with this fifo */		for (bp = fp->fn_buf; bp != NULL; ) {			bp = fifo_buffree(bp, fp);		}		/* update times only if there were bytes flushed from fifo */		if (fp->fn_size != 0) {			gp->g_size = 0;			gp->g_flag |= GUPD|GCHG;			(void) fifo_gupdat(gp, timepick, timepick, 0, cred);		}		/* free fifo structure */		kmem_free((caddr_t)GTOF(gp), KM_TEMP);		gp->g_fifo = NULL;	}	gfs_unlock(gp);	return (0);}/* * read/write a fifo *//*ARGSUSED*/intfifo_rwgp(gp, uiop, rw, ioflag, cred)	struct gnode *gp;	struct uio *uiop;	enum uio_rw rw;	int ioflag;	struct ucred *cred;{	register struct fifonode *fp;	register struct fifo_bufhdr *bp;	register u_int count;	register int off;	register unsigned i;	register int rval = 0;	int first_pass = 1;#ifdef SANITY	if ((ioflag & IO_APPEND) == 0)		printf("fifo_rdwr: no append flag\n");	if (uiop->uio_offset != 0)		printf("fifo_rdwr: non-zero offset: %d\n", uiop->uio_offset);#endif SANITY	fp = GTOF(gp);	gfs_lock(gp);	if (rw == UIO_WRITE) {				/* UIO_WRITE */		/*		 * PIPE_BUF: max number of bytes buffered per open pipe		 * PIPE_MAX: max size of single write to a pipe		 *		 * If the count is less than PIPE_BUF, it must occur		 * atomically.  If it does not currently fit in the		 * kernel pipe buffer, either sleep or return 0 bytes		 * written, depending on FNDELAY  (*** EAGAIN? ***).		 *		 * If the count is greater than PIPE_BUF, it will be		 * non-atomic (FNDELAY clear).  If FNDELAY is set,		 * write as much as will fit into the kernel pipe buffer		 * and return the number of bytes written.		 *		 * If the count is greater than PIPE_MAX, return EINVAL.		 */		if ((unsigned)uiop->uio_resid > PIPE_MAX) {			rval = EINVAL;			goto rdwrdone;		}		while (count = uiop->uio_resid) {			if (fp->fn_rcnt == 0) {				/* no readers anymore! */				psignal(u.u_procp, SIGPIPE);				rval = EPIPE;				goto rdwrdone;			}			if ((count + fp->fn_size) > PIPE_BUF) {				if (ioflag & (FNDELAY|FNBLOCK)) { /* NO DELAY */					if (count <= PIPE_BUF) {						/*						 * Write will be satisfied						 * atomically.						 * Scholars Differ ::						 * P1003 may require EAGAIN						 */						if (first_pass)							if (u.u_procp->p_progenv == A_POSIX)								rval = EAGAIN;							else								rval = EWOULDBLOCK;						goto rdwrdone;					} else if (fp->fn_size >= PIPE_BUF) {					    /*					     * Write will never be atomic.					     * At this point, it cannot even be					     * partial.   However, some portion					     * of the write may already have					     * succeeded.  If so, uio_resid					     * reflects this.   If not, we will					     * have to keep track of this fact					     * in order to return EAGAIN.					     */						if (first_pass)							if (u.u_procp->p_progenv == A_POSIX)								rval = EAGAIN;							else								rval = EWOULDBLOCK;						goto rdwrdone;					}				} else {			/* DELAY */					if ( (count <= PIPE_BUF) ||					    (fp->fn_size >= PIPE_BUF) ) {				/*				 * Sleep until there is room for this request.				 * On wakeup, go back to the top of the loop.				 */						fp->fn_flag |= IFIW;						(void) sleep_unlock((caddr_t)						    &fp->fn_wcnt, PPIPE, 						    &gp->g_lk);						gfs_lock(gp);						goto wrloop;					}				}				/* at this point, can do a partial write */				count = PIPE_BUF - fp->fn_size;			}			/*			 * Can write 'count' bytes to pipe now.   Make sure			 * there is enough space in the allocated buffer list.			 * If not, try to allocate more.			 * If allocation does not succeed immediately, go back			 * to the  top of the loop to make sure everything is			 * still cool.			 */#ifdef SANITY			if ((fp->fn_wptr - fp->fn_rptr) != fp->fn_size)			    printf("fifo_write: ptr mismatch...size:%d  wptr:%d  rptr:%d\n",				fp->fn_size, fp->fn_wptr, fp->fn_rptr);			if (fp->fn_rptr > PIPE_BSZ)			    printf("fifo_write: rptr too big...rptr:%d\n",				fp->fn_rptr);			if (fp->fn_wptr > (fp->fn_nbuf * PIPE_BSZ))			    printf("fifo_write: wptr too big...wptr:%d  nbuf:%d\n",				fp->fn_wptr, fp->fn_nbuf);#endif SANITY			while (((fp->fn_nbuf * PIPE_BSZ) - fp->fn_wptr)			    < count) {				if ((bp = fifo_bufalloc(gp, fp)) == NULL) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -