📄 vm_swp.c
字号:
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 + -