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

📄 fifo_gnodeops.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
					goto wrloop;	/* fifonode unlocked */				}				/* new buffer...tack it on the of the list */				bp->fb_next = (struct fifo_bufhdr *) NULL;				if (fp->fn_buf == (struct fifo_bufhdr *) NULL) {					fp->fn_buf = bp;				} else {					fp->fn_bufend->fb_next = bp;				}				fp->fn_bufend = bp;			}			/*			 * There is now enough space to write 'count' bytes.			 * Find append point and copy new data.			 */			bp = fp->fn_buf;			for (off = fp->fn_wptr; off >= PIPE_BSZ;			    off -= PIPE_BSZ)				bp = bp->fb_next;					while (count) {				i = PIPE_BSZ - off;				i = MIN(count, i);				if (rval =				    uiomove(&bp->fb_data[off], (int) i,				    UIO_WRITE, uiop)){					/* error during copy from user space */					/* NOTE:LEAVE ALLOCATED BUFS FOR NOW */					goto rdwrdone;				}				fp->fn_size += i;				fp->fn_wptr += i;				count -= i;				off = 0;				bp = bp->fb_next;			}			gp->g_flag |= GUPD|GCHG;			(void) fifo_gupdat(gp, timepick, timepick, 0, cred);			/* wake up any sleeping readers */			if (fp->fn_flag & IFIR) {				fp->fn_flag &= ~IFIR;				wakeup((caddr_t) &fp->fn_rcnt);			}			/* wake up any procs sleeping on select */			if (fp->fn_rselp) {				selwakeup(fp->fn_rselp, fp->fn_flag & IF_RCOLL);				fp->fn_flag &= ~IF_RCOLL;				fp->fn_rselp = 0;			}wrloop: 		/* bottom of write 'while' loop */			first_pass = 0;			continue;		}	} else {					/* UIO_READ */		/*		 * Handle zero-length reads specially here		 */		if ((count = uiop->uio_resid) == 0) {			goto rdwrdone;		}		while ((i = fp->fn_size) == 0) {			if (fp->fn_wcnt == 0) {				/* no data in pipe and no writers...(EOF) */				goto rdwrdone;			}			/* no data in pipe, but writer is there */			if (ioflag & (FNDELAY|FNBLOCK)) {				rval = EAGAIN;				goto rdwrdone;			}			fp->fn_flag |= IFIR;			(void) sleep_unlock((caddr_t) &fp->fn_rcnt, PPIPE, 					    &gp->g_lk);			gfs_lock(gp);			/* loop to make sure there is still a writer */		}#ifdef SANITY		if ((fp->fn_wptr - fp->fn_rptr) != fp->fn_size)			printf("fifo_read: 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_read: rptr too big...rptr:%d\n",			    fp->fn_rptr);		if (fp->fn_wptr > (fp->fn_nbuf * PIPE_BSZ))			printf("fifo_read: wptr too big...wptr:%d  nbuf:%d\n",			    fp->fn_wptr, fp->fn_nbuf);#endif SANITY		/*		 * Get offset into first buffer at which to start getting data.		 * Truncate read, if necessary, to amount of data available.		 */		off = fp->fn_rptr;		bp = fp->fn_buf;		count = MIN(count, i);	/* smaller of pipe size and read size */		while (count) {			i = PIPE_BSZ - off;			i = MIN(count, i);			if (rval =			    uiomove(&bp->fb_data[off], (int)i, UIO_READ, uiop)){				goto rdwrdone;			}			fp->fn_size -= i;			fp->fn_rptr += i;			count -= i;			off = 0;#ifdef SANITY			if (fp->fn_rptr > PIPE_BSZ)				printf("fifo_read: rptr after uiomove too big...rptr:%d\n",				    fp->fn_rptr);#endif SANITY			if (fp->fn_rptr == PIPE_BSZ) {				fp->fn_rptr = 0;				bp = fifo_buffree(bp, fp);				fp->fn_buf = bp;				fp->fn_wptr -= PIPE_BSZ;			}			/*			 * At this point, if fp->fn_size is zero, there may be			 * an allocated, but unused, buffer.  [In this case,			 * fp->fn_rptr == fp->fn_wptr != 0.]			 * NOTE: FOR NOW, LEAVE THIS EXTRA BUFFER ALLOCATED.			 * NOTE: fifo_buffree() CAN'T HANDLE A BUFFER NOT 1ST.			 */		}		gp->g_flag |= GACC;                    (void) fifo_gupdat(gp, timepick, timepick, 0, cred);		/* wake up any sleeping writers */		if (fp->fn_flag & IFIW) {			fp->fn_flag &= ~IFIW;			wakeup((caddr_t) &fp->fn_wcnt);		}		/* wake up any procs sleeping on select */		if (fp->fn_wselp) {			selwakeup(fp->fn_wselp, fp->fn_flag & IF_WCOLL);			fp->fn_flag &= ~IF_WCOLL;			fp->fn_wselp = 0;		}	}		/* end of UIO_READ code */rdwrdone:	gfs_unlock(gp);	uiop->uio_offset = 0;		/* guarantee that f_offset stays 0 */	return (rval);}/* * test for fifo selections *//*ARGSUSED*/intfifo_select(gp, flag, cred)	struct gnode *gp;	int flag;	struct ucred *cred;{	register struct fifonode *fp;	int ret_val=0;	fp = GTOF(gp);	gfs_lock(gp);	switch (flag) {	case FREAD:		if ((fp->fn_size != 0) || (fp->fn_wcnt == 0))			ret_val = 1;		else  {			if (fp->fn_rselp)				fp->fn_flag |= IF_RCOLL;			else				fp->fn_rselp = u.u_procp;		}		break;	case FWRITE:		if ((fp->fn_size < PIPE_BUF) || (fp->fn_rcnt == 0))			ret_val=1;		else {			if (fp->fn_wselp)				fp->fn_flag |= IF_WCOLL;			else				fp->fn_wselp = u.u_procp;		}				break;	}	gfs_unlock(gp);	return (ret_val);}intfifo_rele(gp)	struct gnode *gp;{	extern struct lock_t lk_gnode;	gfs_lock(gp);	if ((gp->g_mode & GFMT) == GFPIPE) {		/*		 * We have to take out a spin lock here to workaround an		 * smp lock primitive problem. When a sleep lock resides		 * in km_alloc space a race condition can exist between		 * km_freeing the memory, and checking the wakeup bit in the		 * lock. Its ugly, but it works... prs		 */		smp_lock(&lk_gnode, LK_RETRY);		if (gp->g_count == 1) {			gfs_unlock(gp);			smp_unlock(&lk_gnode);			kmem_free((caddr_t)gp, KM_TEMP);		}		else {			gp->g_count--;			gfs_unlock(gp);			smp_unlock(&lk_gnode);		}		return (0);	}	gfs_unlock(gp);}intfifo_gupdat(gp, ta, tm, waitfor, cred)	struct gnode *gp;	struct timeval *ta, *tm;	int waitfor;	struct ucred *cred;{	if ((gp->g_mode & GFMT) == GFPIPE) {		if (gp->g_flag & GACC)			gp->g_atime = *ta;		if (gp->g_flag & GUPD)			gp->g_mtime = *tm;		if (gp->g_flag & GCHG)			gp->g_ctime = *timepick;				gp->g_flag &= ~(GUPD|GACC|GCHG|GMOD);		return (0);	}	return (gp->g_altops->go_gupdat(gp, ta, tm, waitfor, cred));}		fifo_wakeup(fp)	register struct fifonode *fp;{	register struct proc *p;	/*	 * If ASYNC is set on fifo, send SIGIO signal to	 * procs in process group.	 */	if (fp->fn_flag & IF_RASYNC) {	        if (fp->fn_rpgrp < 0)			gsignal(-fp->fn_rpgrp, SIGIO);		else if ((fp->fn_rpgrp > 0) &&		    (p = pfind(fp->fn_rpgrp)) != 0)			psignal(p, SIGIO);	}	if (fp->fn_flag & IF_WASYNC) {	        if (fp->fn_wpgrp < 0)			gsignal(-fp->fn_wpgrp, SIGIO);		else if ((fp->fn_wpgrp > 0) &&		    (p = pfind(fp->fn_wpgrp)) != 0)			psignal(p, SIGIO);	}}/* * allocate a buffer for a fifo * return NULL if had to sleep */static struct fifo_bufhdr *fifo_bufalloc(gp, fp)	register struct gnode *gp;	register struct fifonode *fp;{	register struct fifo_bufhdr *bp;	if (fifo_alloc >= PIPE_MNB) {		/*		 * Impose a system-wide maximum on buffered data in pipes.		 * NOTE: This could lead to deadlock!		 */		(void) sleep_unlock((caddr_t) &fifo_alloc, PPIPE, &gp->g_lk);		gfs_lock(gp);		return ((struct fifo_bufhdr *)NULL);	}	/* the call to kmem_alloc() might sleep, so leave fifonode locked */	fifo_alloc += FIFO_BUFFER_SIZE;	kmem_alloc(bp, struct fifo_bufhdr *, (u_int)FIFO_BUFFER_SIZE, KM_TEMP);	fp->fn_nbuf++;	return ((struct fifo_bufhdr *) bp);}/* * deallocate a fifo buffer */static struct fifo_bufhdr *fifo_buffree(bp, fp)	struct fifo_bufhdr *bp;	struct fifonode *fp;{	register struct fifo_bufhdr *nbp;	fp->fn_nbuf--;	/*	 * NOTE: THE FOLLOWING ONLY WORKS IF THE FREED BUFFER WAS THE 1ST ONE.	 */	if (fp->fn_bufend == bp)		fp->fn_bufend = (struct fifo_bufhdr *) NULL;	nbp = bp->fb_next;	kmem_free((caddr_t)bp, KM_TEMP);	if (fifo_alloc >= PIPE_MNB) {		wakeup((caddr_t) &fifo_alloc);	}	fifo_alloc -= FIFO_BUFFER_SIZE;	return (nbp);}intfifo_lock(gp)	struct gnode *gp;{	if ((gp->g_mode & GFMT) == GFPIPE) {	        while (glocked(gp)) {		       gp->g_flag |= GWANT;		       sleep((caddr_t)gp, PINOD);		}		gfs_lock(gp);		return (0);	}	return (gp->g_altops->go_lock (gp));}intfifo_unlock(gp)	struct gnode *gp;{	if ((gp->g_mode & GFMT) == GFPIPE) {		gfs_unlock(gp);		if (gp->g_flag&GWANT) {		       gp->g_flag &= ~GWANT;		       wakeup((caddr_t)gp);		}		return (0);	}	return (gp->g_altops->go_unlock (gp));}intfifo_stat(gp, sb)	struct gnode *gp;	struct stat *sb;{	register struct fifonode *fp;	fp = GTOF(gp);	if ((gp->g_mode & GFMT) == GFPORT)	/* Named pipe */		gp->g_altops->go_stat (gp, sb);	else {		bzero((caddr_t)sb, sizeof(*sb));		sb->st_atime = gp->g_atime.tv_sec;		sb->st_spare1 = gp->g_atime.tv_usec;		sb->st_mtime = gp->g_mtime.tv_sec;		sb->st_spare2 = gp->g_mtime.tv_usec;		sb->st_ctime = gp->g_ctime.tv_sec;		sb->st_spare3 = gp->g_ctime.tv_usec;	}	if (fp)		sb->st_size = fp->fn_size;	sb->st_blksize = PIPE_BUF;	return (0);}/*ARGSUSED*/intfifo_ioctl(gp, com, data, flag, cred)	struct gnode *gp;	int com;	caddr_t data;	int flag;	struct ucred *cred;{	register struct fifonode *fp;	int error = 0;	switch (com) {		case FIONREAD:			fp = GTOF(gp);			*(off_t *)data = fp->fn_size;			break;		case FIOGETOWN:			fp = GTOF(gp);			if (flag & FREAD)			      *(int *)data = fp->fn_rpgrp;			else			      *(int *)data = fp->fn_wpgrp;			break;		case FIOSETOWN:			fp = GTOF(gp);			if (flag & FREAD)			      fp->fn_rpgrp = *(int *)data;			else			      fp->fn_wpgrp = *(int *)data;			break;		case FIOASYNC:			fp = GTOF(gp);			if (*(int *)data) {			      if (flag & FREAD)			            fp->fn_flag |= IF_RASYNC;			      else			            fp->fn_flag |= IF_WASYNC;			}			else {			      if (flag & FREAD)				    fp->fn_flag &= ~IF_RASYNC;			      else				    fp->fn_flag &= ~IF_WASYNC;			}			break;		case FIONBIO:			break;		default:			error = ENOTTY;			break;	}	return (error);}

⌨️ 快捷键说明

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