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

📄 vm_swp.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char *sccsid = "@(#)vm_swp.c	4.1	(ULTRIX)	%G";#endif/************************************************************************ *									* *			Copyright (c) 1986 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.	* *									* ************************************************************************//* * *   Modification history: * *  2 Feb 88 - lp *	Fixed a problem on close of a non-nbuffered channel (check *	for no async_bp). * * 26 Jan 88 -- lp *	Fixed a race condition in asyncclose. This was uncovered *	by use of the new allocator in that some buffers were not  *	being freed as well as premature exit of the closing process. * * 14 Dec 87 -- jaa *	Added new KM_ALLOC/KM_FREE macros * * 15 Dec 86 -- depp *	The error messages in swkill() had become inconsistent and confusing, *	so I cleaned it up a tad (it really needs some rethinking). * * 11 Sep 86 -- lp *	Corrected problem in buffers which errored. * * 11 Sep 86 -- koehler *	corrected the text pointer name * * 20 Aug 86 -- koehler *	local execution/shmem fix (i.e., no text point attachment) * * 29 Apr 86 -- depp *	converted to locking macros from calls routines * * 11 Mar 86 -- lp *	Added routines for n-bufferring to raw devices. * * 11 Nov 85 -- depp *	Removed all conditional compiles for System V IPC. * * 11 Mar 85 -- depp *	Added System V shared memory support. * */#include "../machine/pte.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/conf.h"#include "../h/proc.h"#include "../h/text.h"#include "../h/file.h"#include "../h/seg.h"#include "../h/vm.h"#include "../h/trace.h"#include "../h/map.h"#include "../h/uio.h"#include "../h/ipc.h"#include "../h/shm.h"#include "../h/kmalloc.h"#include "../h/cmap.h"#include "../h/gnode.h"#include "../h/mount.h"/* * Swap IO headers - * They contain the necessary information for the swap I/O. * At any given time, a swap header can be in three * different lists. When free it is in the free list,  * when allocated and the I/O queued, it is on the swap  * device list, and finally, if the operation was a dirty  * page push, when the I/O completes, it is inserted  * in a list of cleaned pages to be processed by the pageout daemon. */struct	buf *swbuf;/* * swap I/O - * * If the flag indicates a dirty page push initiated * by the pageout daemon, we map the page into the i th * virtual page of process 2 (the daemon itself) where i is * the index of the swap header that has been allocated. * We simply initialize the header and queue the I/O but * do not wait for completion. When the I/O completes, * iodone() will link the header to a list of cleaned * pages to be processed by the pageout daemon. */swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)	struct proc *p;	swblk_t dblkno;	caddr_t addr;	int nbytes, rdflg, flag;	dev_t dev;	u_int pfcent;{	register struct buf *bp;	register u_int c;	register int p2dp;	register struct pte *dpte, *vpte;	register struct gnode *gp;	int s;	extern swdone();	int (*strat)();#ifdef GFSDEBUG	extern short GFS[];#endif#ifdef mips	XPRINTF(XPR_VM,"enter swap",0,0,0,0);#endif mips#ifdef vax	s = spl6();#endif vax#ifdef mips	s = splbio();#endif mips	while (bswlist.av_forw == NULL) {		bswlist.b_flags |= B_WANTED;		sleep((caddr_t)&bswlist, PSWP+1);	}	bp = bswlist.av_forw;	bswlist.av_forw = bp->av_forw;	splx(s);#ifdef GFSDEBUG	if(GFS[18])		cprintf("swap: pid %d gp 0x%x (%d) nbytes %d addr 0x%x op %s\n",		p->p_pid, p->p_textp ? p->p_textp->x_gptr : NULL,		p->p_textp ? p->p_textp->x_gptr->g_number : NULL,		nbytes, addr, rdflg == B_READ ? "READ" : "WRITE");#endif	bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;	if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)		if (rdflg == B_READ)			sum.v_pswpin += btoc(nbytes);		else			sum.v_pswpout += btoc(nbytes);	bp->b_proc = p;	if (flag & B_DIRTY) {		p2dp = ((bp - swbuf) * CLSIZE) * KLMAX;		dpte = dptopte(&proc[2], p2dp);		if(flag & B_SMEM)	/* SHMEM */			vpte = ((struct smem *)p)->sm_ptaddr + btop(addr);		else			vpte = vtopte(p, btop(addr));		for (c = 0; c < nbytes; c += NBPG) {			if (vpte->pg_pfnum == 0 || vpte->pg_fod)				panic("swap bad pte");			*dpte++ = *vpte++;		}		bp->b_un.b_addr = (caddr_t)ctob(dptov(&proc[2], p2dp));		bp->b_flags |= B_CALL;		bp->b_iodone = swdone;		bp->b_pfcent = pfcent;	} else		bp->b_un.b_addr = addr;	if(flag & B_SMEM) {	/* SHMEM */		gp = (struct gnode *) NULL;		strat = bdevsw[major(dev)].d_strategy;	} else {		gp = p->p_textp ? p->p_textp->x_gptr : NULL;		if(gp && GIOSTRATEGY(gp) && (dev == gp->g_dev)) {			strat = GIOSTRATEGY(gp);		} else			strat = bdevsw[major(dev)].d_strategy;	}	while (nbytes > 0) {		bp->b_bcount = nbytes;		minphys(bp);		c = bp->b_bcount;		bp->b_blkno = dblkno;		bp->b_dev = dev;#ifdef TRACE		trace(TR_SWAPIO, dev, bp->b_blkno);#endif		bp->b_gp = gp;		physstrat(bp, strat, PSWP);		if (flag & B_DIRTY) {			if (c < nbytes)				panic("big push");			return;		}		bp->b_un.b_addr += c;		bp->b_flags &= ~B_DONE;		if (bp->b_flags & B_ERROR) {			if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE) {				cprintf(				"swap err: bp = 0x%x, bp->b_blkno = 0x%x\n",				bp,bp->b_blkno);				panic("hard IO err in swap");			}			if((bp->b_flags & B_SMEM) == 0)	/* SHMEM */				swkill(p, (char *)0);		}		nbytes -= c;		dblkno += btodb(c);	}#ifdef vax	s = spl6();#endif vax#ifdef mips	s = splbio();#endif mips	bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY						|B_SMEM);	/* SHMEM */	bp->av_forw = bswlist.av_forw;	bswlist.av_forw = bp;	if (bswlist.b_flags & B_WANTED) {		bswlist.b_flags &= ~B_WANTED;		wakeup((caddr_t)&bswlist);		wakeup((caddr_t)&proc[2]);	}	splx(s);}/* * Put a buffer on the clean list after I/O is done. * Called from biodone. */swdone(bp)	register struct buf *bp;{	register int s;#ifdef mips	XPRINTF(XPR_VM,"enter swdone",0,0,0,0);#endif mips	if (bp->b_flags & B_ERROR)		panic("IO err in push");#ifdef vax	s = spl6();#endif vax#ifdef mips	s = splbio();#endif mips	bp->av_forw = bclnlist;	cnt.v_pgout++;	cnt.v_pgpgout += bp->b_bcount / NBPG;	bclnlist = bp;	if (bswlist.b_flags & B_WANTED)		wakeup((caddr_t)&proc[2]);	splx(s);}/* * If rout == 0 then killed on swap error, else * rout is the name of the routine where we either ran out of * swap space, or some other process killing error occured. */swkill(p, rout)	register struct proc *p;	register char *rout;{	register int pid = (int) p->p_pid;#ifdef mips	XPRINTF(XPR_VM,"enter swkill",0,0,0,0);#endif mips	if (rout) {		printf("pid %d was killed in %s\n", pid, rout);		uprintf("sorry, pid %d was killed: %s\n",pid, rout);	}	else {		printf("pid %d was killed on swap error\n",pid);		uprintf("sorry, pid %d was killed on swap error\n",pid);	}	/*	 * To be sure no looping (e.g. in vmsched trying to	 * swap out) mark process locked in core (as though	 * done by user) after killing it so noone will try	 * to swap it out.	 */	psignal(p, SIGKILL);	p->p_flag |= SULOCK;}/* * Raw I/O. The arguments are *	The strategy routine for the device *	A buffer, which will always be a special buffer *	  header owned exclusively by the device for this purpose *	The device number *	Read/write flag * Essentially all the work is computing physical addresses and * validating them. * If the user has the proper access privilidges, the process is * marked 'delayed unlock' and the pages involved in the I/O are * faulted and locked. After the completion of the I/O, the above pages * are unlocked. */physio(strat, bp, dev, rw, mincnt, uio)	int (*strat)();	register struct buf *bp;	dev_t dev;	int rw;	unsigned (*mincnt)();	struct uio *uio;{	register struct iovec *iov = uio->uio_iov;	register int c;	register char *a;	register int s, error = 0;#ifdef mips	XPRINTF(XPR_VM,"enter physio",0,0,0,0);#endif mipsnextiov:	if (uio->uio_iovcnt == 0)		return (0);	if (useracc(iov->iov_base,(u_int)iov->iov_len,rw==B_READ?B_WRITE:B_READ) == NULL)		return (EFAULT);#ifdef vax	s = spl6();#endif vax#ifdef mips	s = splbio();#endif mips	while (bp->b_flags&B_BUSY) {		bp->b_flags |= B_WANTED;		sleep((caddr_t)bp, PRIBIO+1);	}	splx(s);	if(bp->b_flags&B_RAWASYNC) {		if(uio->uio_iovcnt > 1 ) /* readv/writev dont work w/n-buffer */			return(EFAULT);	}	bp->b_error = 0;	bp->b_proc = u.u_procp;	bp->b_un.b_addr = iov->iov_base;	while (iov->iov_len > 0) {		if(bp->b_flags&B_RAWASYNC)			bp->b_flags |= B_BUSY | B_PHYS | rw;		else			bp->b_flags = B_BUSY | B_PHYS | rw;		bp->b_dev = dev;		bp->b_blkno = btodb(uio->uio_offset);		bp->b_bcount = iov->iov_len;		(*mincnt)(bp);		c = bp->b_bcount;#ifdef vax		s = spl6();#endif vax#ifdef mips		s = splbio();#endif mips		u.u_procp->p_flag |= SPHYSIO;		vslock(a = bp->b_un.b_addr, c);		splx(s);					physstrat(bp, strat, PRIBIO);

⌨️ 快捷键说明

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