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

📄 vm_swp.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(bp->b_flags&B_RAWASYNC) {			/* Transfer has not started */			if(bp->b_flags&B_ERROR)				return(geterror(bp));			/* else transfer has started */			iov->iov_len -= c;			uio->uio_resid -= c;			uio->uio_offset += c;			return(0);		}#ifdef vax		(void) spl6();#endif vax#ifdef mips		(void) splbio();#endif mips		vsunlock(a, c, rw);		u.u_procp->p_flag &= ~SPHYSIO;		if (bp->b_flags&B_WANTED)			wakeup((caddr_t)bp);		splx(s);		c -= bp->b_resid;		bp->b_un.b_addr += c;		iov->iov_len -= c;		uio->uio_resid -= c;		uio->uio_offset += c;		/* temp kludge for tape drives */		if (bp->b_resid || (bp->b_flags&B_ERROR))			break;	}	bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);	error = geterror(bp);	/* temp kludge for tape drives */	if (bp->b_resid || error)		return (error);	uio->uio_iov++;	uio->uio_iovcnt--;	goto nextiov;}#define MAXPHYS (64 * 1024)unsignedminphys(bp)	register struct buf *bp;{#ifdef mips	XPRINTF(XPR_VM,"enter minphys",0,0,0,0);#endif mips	if (bp->b_bcount > MAXPHYS)		bp->b_bcount = MAXPHYS;}/*** Start or n-bufferring code ***/#define ASYNC_RCOLL 	0x01#define ASYNC_WCOLL	0x02#define b_selflags b_pfcentstruct abuf {	struct abuf *b_forw, *b_back;	struct buf bp;};struct abuf *async_bp = (struct abuf *)0;/* * doingasync is used to decide if this device is really able to * do n-bufferring. */doingasync(dev, flag)	dev_t dev;	int flag;{	register struct buf *bp;	register struct abuf *dp;#ifdef mips	XPRINTF(XPR_VM,"enter doingasync",0,0,0,0);#endif mips	if((flag&FNBUF) == 0 || async_bp == (struct abuf *)0)		return(0);	for(dp = async_bp->b_forw; dp != async_bp; dp = dp->b_forw) {		bp = &dp->bp;		if(bp->b_dev == dev)			return(1);		if(dp->b_forw == async_bp)			break;	}	return(0);}/*  * Startasync is called by an ioctl. Its passed the number of buffers * to be used for n-bufferring while this device is open. */startasync(dev, count, flags)	dev_t dev;	int *count;	int flags;	/* fp flags */{	register int found = 0, s;	register struct abuf *tdp;	register struct proc *p = u.u_procp;			#ifdef mips	XPRINTF(XPR_VM,"enter startasync",0,0,0,0);#endif mips		if(async_bp == 0) {			KM_ALLOC(async_bp, struct abuf *, sizeof(struct abuf), KM_DEVBUF, KM_CLEAR);			async_bp->b_forw = async_bp;			async_bp->b_back = async_bp;		}	for(;found < *count; found++) {			KM_ALLOC(tdp, struct abuf *, sizeof(struct abuf), KM_DEVBUF, KM_CLEAR | KM_NOWAIT);			if(tdp == (struct abuf *)0)				break;#ifdef vax			s = spl5();#endif vax#ifdef mips			s = splbio();#endif mips			if(async_bp == 0) {				cprintf("No async_bp head\n");			} else				binshash(tdp, async_bp);				splx(s);			tdp->bp.b_flags = 0;			if(flags & FASYNC) {				tdp->bp.b_flags |= B_WANTED;			}			tdp->bp.b_proc = p;			tdp->bp.b_dev = dev;		}		*count = found;}/*  * aiodone is called via an ioctl to check on a buffers status. * It might block (unless non-blocking io enabled) until the * buffer completes. */aiodone(dev, addr, flags)	dev_t dev;	int addr;	int flags;	/* fp flags! */{	register struct abuf *dp;	register struct buf *bp;#ifdef mips	XPRINTF(XPR_VM,"enter aiodone",0,0,0,0);#endif mips	if(async_bp == (struct abuf *)0)		return(EINVAL);		for(dp = async_bp->b_forw; dp != async_bp; dp = dp->b_forw) {		register int s;		bp = &dp->bp;		if(dev != bp->b_dev) /* On correct device */			continue;		if(u.u_procp != bp->b_proc) /* By me */			continue;		if(addr == (int) bp->b_un.b_addr) {#ifdef vax			s=spl5();#endif vax#ifdef mips			s=splbio();#endif mips			if(bp->b_flags&B_BUSY) {/* Wait till done */				if(flags&FNDELAY) {					u.u_error = EWOULDBLOCK;					splx(s);					return(-1);				}				sleep((caddr_t) bp, PRIBIO);			}			splx(s);			/* We must be done here */			if(bp->b_flags&B_ERROR) {				bp->b_flags &= ~(B_BUSY|B_PHYS|B_DONE);				return(geterror(bp));			}			/* Clear flags out so I can reuse buffer */			bp->b_flags &= ~(B_BUSY|B_PHYS|B_ERROR|B_DONE);			u.u_r.r_val1 = bp->b_bcount - bp->b_resid;			return(0);		}	}	return(EINVAL);}/*  * Select code for raw devices (which can do n-bufferring). */asyncsel(dev, rw)	dev_t dev;	int rw;{	register struct buf *bp;	register struct abuf *dp;#ifdef vax	register int s = spl5();#endif vax#ifdef mips	register int s = splbio();#endif mips	register int doown = 0;	#ifdef mips	XPRINTF(XPR_VM,"enter asyncsel",0,0,0,0);#endif mips	if(async_bp == (struct abuf *)0)		return(EINVAL);		for(dp = async_bp->b_forw; dp != async_bp; dp = dp->b_forw) {		bp = &dp->bp;		if(bp->b_dev != dev)			continue;		if(bp->b_proc != u.u_procp)			continue;		doown++;		if(bp->b_flags&B_BUSY)			continue;		splx(s);		return(1); /* Found a non-busy buffer */	}	if(bp->b_proc->p_wchan == (caddr_t) &selwait)		bp->b_selflags |= (rw == FREAD ? ASYNC_RCOLL : ASYNC_WCOLL);	splx(s);	if(!doown) /* None owned so must be ok */		return(1);	return(0);	}/* * asyncclose is called to clean things up when the file desc. gets * closed down. Frees buffers and blocks till pending buffers finish. */asyncclose(dev, flag)	dev_t dev;	register flag;{	register int otherasync = 0;	register struct abuf *dp, *next;	register int s;#ifdef mips	XPRINTF(XPR_VM,"enter asyncclose",0,0,0,0);#endif mips	if (doingasync(dev, flag)) { /* This dev was doing async */		for(dp = async_bp->b_forw; dp != async_bp;) {			if(dp->bp.b_dev != dev) {				dp = dp->b_forw;				continue;			}			if(dp->bp.b_proc != u.u_procp) {				otherasync++;				dp = dp->b_forw;				continue;			}#ifdef vax			s = spl5();#endif vax#ifdef mips			s = splbio();#endif mips			if(dp->bp.b_flags&B_BUSY)				sleep((caddr_t) &dp->bp, PRIBIO);			splx(s);			if(dp->bp.b_flags&B_WANTED)				wakeup((caddr_t)&dp->bp);#ifdef vax			s = spl5();#endif vax#ifdef mips			s = splbio();#endif mips			next = dp->b_forw;			bremhash(dp);			splx(s);			KM_FREE(dp, KM_DEVBUF);			dp = next;		}	}	return(otherasync);}/*  * Asyncdone is called from interrupt level to mark the passed buffer * as being done. Someone might be blocked waiting for the buffer  * so we issue a wakeup. Someone also might want to be notified  * and if so issue a sigio. */asyncdone(bp)register struct buf *bp;{	register struct pte *pte;	register int npf;	register struct cmap *c;#ifdef mips	XPRINTF(XPR_VM,"enter asyncdone",0,0,0,0);#endif mips	pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr));	npf = btoc(bp->b_bcount + ((int)bp->b_un.b_addr & CLOFSET));	while (npf > 0) {		c = &cmap[pgtocm(pte->pg_pfnum)];		MUNLOCK(c);		if(bp->b_flags&B_READ)			pte->pg_m = 1;		pte += CLSIZE;		npf -= CLSIZE;	}	bp->b_flags &= ~B_BUSY;	/* Someone waiting on a select */	if(bp->b_proc->p_wchan == (caddr_t)&selwait)		selwakeup(bp->b_proc, bp->b_selflags & 			((bp->b_flags&B_READ) ? ASYNC_RCOLL : ASYNC_WCOLL));	/* Someone waiting on SIGIO */	if(bp->b_flags & B_WANTED) /* Someone wants to be notified */		psignal(bp->b_proc, SIGIO);	/* Anyone waiting on this buffer */	wakeup((caddr_t) bp);}/*  * aphysio is the front end to physio for n-buffered case. It finds * an available buffer & calls physio. */aphysio(strat, dev, rw, uio)	dev_t dev;	struct uio *uio;	int rw;	int (*strat)();{	register struct abuf *dp;	register struct buf *bp;	register int anyerror = 0, s;#ifdef mips	XPRINTF(XPR_VM,"enter aphysio",0,0,0,0);#endif mips		if(async_bp == (struct abuf *)0)			return(EINVAL);			for(dp = async_bp->b_forw; dp != async_bp; dp = dp->b_forw) {			bp = &dp->bp;			if(bp->b_dev != dev) /* On correct device */				continue;			if(bp->b_proc != u.u_procp)				continue;#ifdef vax			s = spl5();#endif vax#ifdef mips			s = splbio();#endif mips			if(bp->b_flags&B_BUSY) { /* bp done ? */				splx(s);				continue;			} else {			splx(s);			if(bp->b_flags&B_PHYS) /* Have I used it yet ? */				continue;			goto found;			}		}			return(ENOBUFS);found:		bp->b_resid = 0;		bp->b_flags &= ~(B_ERROR|B_BUSY);		bp->b_flags |= B_RAWASYNC|B_CALL;		bp->b_iodone = asyncdone;		anyerror = physio(strat, bp, dev, rw, minphys, uio);	return (anyerror);}

⌨️ 快捷键说明

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