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

📄 vm_mem.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
		size -= CLSIZE;		i = pte->pg_pfnum;		if (i < firstfree || i > maxfree)			panic("bad mem free");		i = pgtocm(i);		c = &cmap[i];#ifdef mips		if (c->c_type == CTEXT) {			xp = &text[c->c_ndx];			if (xp->x_flag & XTRC) {				int dev = c->c_mdev==MSWAPX?swapdev:mount[c->c_mdev].m_dev;				if (c->c_blkno && mfind(dev,c->c_blkno,xp->x_gptr)) {					munhash(dev,(daddr_t)(u_long)c->c_blkno,xp->x_gptr);				}			}		}#endif mips		if (c->c_free)			panic("dup mem free");		if (flg && c->c_type != CSYS) {			for (j = 0; j < CLSIZE; j++)				*(int *)(pte+j) &= PG_PROT;			c->c_gone = 1;		}		s = splimp();		/*		 * If	deallocating "u" pages, place on temp "u" list 		 *	to be cleared by "vcleanu" routine		 * else place either at the head or tail of freelist		 *	depending on whether it may be reclaimed		 */		if (flg == KMF_UAREA) {			/* insure that list doesn't get too long */			if (nucmap >= UCLEAR)	/* machine/vmparam.h */				vcleanu();			if (nucmap == 0)				ucmap = eucmap = i;			else {				cmap[eucmap].c_next = i;				c->c_prev = eucmap;				eucmap = i;			}			nucmap++;		} else if (flg == KMF_DETACH && c->c_blkno == 0) {			next = cmap[CMHEAD].c_next;			cmap[next].c_prev = i;			c->c_prev = CMHEAD;			c->c_next = next;			cmap[CMHEAD].c_next = i;			freemem += CLSIZE;		} else {			prev = cmap[CMHEAD].c_prev;			cmap[prev].c_next = i;			c->c_next = CMHEAD;			c->c_prev = prev;			cmap[CMHEAD].c_prev = i;			freemem += CLSIZE;		}		c->c_free = 1;		splx(s);		pte += CLSIZE;	}}/* ***************************************************************************** ***************************************************************************** * * Function: * *	vcleanu -- kernel routine * * Function description: * *	This function will remove all of the page frames on the "u" list *	to the free list.  Since the cmap entries have been properly  *	initialized and linked in memall, all that must be done is to *	move the list intact onto the top of the free list. * *	NOTE:  This routine is currently only being called in "pagein".   *	If additional calls become necessary, this routine must only be *	called if "nucmap != 0" (see "panic"). * * Return Value: * *	None * * Interface: * *	void vcleanu() * * Errors: * *	None * * Panics: * *	"vcleanu" *		This list is empty.  This routine should not have been called, *		which is one indication that the list may be corrupted. *	 ***************************************************************************** ***************************************************************************** */voidvcleanu(){register s, next;#ifdef mips	XPRINTF(XPR_VM,"enter vcleanu",0,0,0,0);#endif mips	s = splimp();	if (ucmap == -1)		panic("vcleanu");	if (freemem < CLSIZE * KLMAX)		wakeup((caddr_t)&freemem);	next = cmap[CMHEAD].c_next;	cmap[next].c_prev = eucmap;	cmap[ucmap].c_prev = CMHEAD;	cmap[eucmap].c_next = next;	cmap[CMHEAD].c_next = ucmap;	freemem += nucmap * CLSIZE;	ucmap = eucmap = -1;	nucmap = 0;	splx(s);}/* ***************************************************************************** ***************************************************************************** * * Function: * *	pfalloc -- kernel routine * * Function description: * *	This function will allocate page frame clusters.  These *	physical pages are not coupled in any manner to system page table *	space.  It's up to the requesting routine to allocate and map the *	returned PFNs into the system page table. * *	As a rule, this routine should only be used to allocate single *	page frame clusters (npfc == 1).  It should only be used for  *	multiple clusters at startup/configuration time, as the free *	list will get out of order, and the overhead will become unbearable. * * Interface: * *	unsigned int pfalloc (type, npfc) *	  int type;		type must = CSYS ( ../h/cmap.h) *	  int npfc;		number of page frame clusters requested *				(normally, should == 1) * * Return Value: * *	= 0	Error -- no memory to allocate *	> 0	Normal -- PFN of first physical page allocated in * *	In a normal return, the first PFN allocated is returned, the balance *	of the PFNs in the block are easily determined since they are  *	contiguous. * * Error Handling: * *	If return value = 0, then either: *		1. the "cmap" free list is empty. *		2. a block of size "npgf" contiguous page frames could not *		   be located. * * Panics: * *	"pfalloc: type" *		Type must equal CSYS.  User types are not permitted.  In the *		future, other system types may exist and be permitted to use *		this routine. * *	"pfalloc: dup mem alloc" *		The cmap entry was on the free list, but the c_free flag *		indicates that the entry is NOT free.  This indicates  *		corruption of the free list. * *	"pfalloc: bad mem alloc" *		The index into the cmap structures is too high for this  *		memory configuration.  This indicates that the index is *		corrupted, and memory can not be reliably allocated. * *	"pfalloc: intrans|want" *		At this point, the physical cluster should be free of  *		encumbrances, but the cmap entry indicates that the *		physical cluster is intransient or wanted by an user proc. * *	 ***************************************************************************** ***************************************************************************** */unsignedpfalloc (type, npfc)int type;	/* cluster type */int npfc;	/* number of page frame clusters */{	register struct cmap *c;	register next, curpos, count;	int end, head;	unsigned pf;	int s;#ifdef mips	XPRINTF(XPR_VM,"enter pfalloc",0,0,0,0);#endif mips	if (type != CSYS)		panic("pfalloc: type");	s = splimp();	if (freemem < npfc * CLSIZE) {		splx(s);		return(0);	}	/*	 * if only one cluster requested, bypass contiguous lookup	 * else look for contiguous page frames to pass back	 */	if (npfc == 1) {		head = CMHEAD;		pf = cmtopg(cmap[CMHEAD].c_next);	}	else {		next = CMHEAD;		end = cmap[CMHEAD].c_prev;		count = npfc;		while ((curpos = next = cmap[next].c_next) != end) {			while (--count && (cmap[next].c_next == next + 1))				next++;			if (count == 0) {				head = cmap[curpos].c_prev;				pf = cmtopg(curpos);				goto allocate;			}			count = npfc;		}		splx(s);		return(0);	/* sorry, not a large enough block */	}allocate:		while (npfc--) {		curpos = cmap[head].c_next;		c = &cmap[curpos];		freemem -= CLSIZE;		next = c->c_next;		cmap[head].c_next = next;		cmap[next].c_prev = head;		if (c->c_free == 0)			panic("pfalloc: dup mem alloc");		if (cmtopg(curpos) > maxfree)			panic("pfalloc: bad mem alloc");				/* clear CMAP entry */		pfclear(c);		/* intialize CMAP entry */		c->c_ndx = 0;		c->c_free = 0;		c->c_gone = 0;		if (c->c_intrans || c->c_want)			panic("pfalloc: intrans|want");		c->c_type = type;	}#ifdef KM_STATS	km_stats.tot_pfalloc++;#endif KM_STATS	splx(s);	return (pf);}/* ***************************************************************************** ***************************************************************************** * * Function: * *	pffree -- kernel routine * * Function description: * *	This routine will free physical page clusters by placing them on the *	"cmap" free list. * * Interface: * *	void pffree (pfn, npfc) *	  unsigned int pfn		First PFN in cluster to be deallocated *	  int npfc			must equal 1 (for now) * * Return Value: * *	None * * Error Handling: * *	None * * Panics: * *	"pffree: bad mem free" *		The PFN is outside the valid range for this memory  *		configuration or npfc not = 1 * *	"pffree: dup mem free" *		The cmap entry is marked as being free.  This indicates that *		either the free list is corrupted or that the input PFN has *		been currupted. *	 ***************************************************************************** ***************************************************************************** */voidpffree (pfn, npfc)unsigned pfn;int npfc;{	register int next;	register struct cmap *c;	register int s, i;	#ifdef mips	XPRINTF(XPR_VM,"enter pffree",0,0,0,0);#endif mips	if (pfn < firstfree || pfn > maxfree || npfc != 1)		panic("pffree: bad mem free");	i = pgtocm(pfn);	c = &cmap[i];	if (c->c_free)		panic("pffree: dup mem free");	if (freemem < CLSIZE * KLMAX)		wakeup((caddr_t)&freemem);	s = splimp();	next = cmap[CMHEAD].c_next;	cmap[next].c_prev = i;	c->c_prev = CMHEAD;	c->c_next = next;	cmap[CMHEAD].c_next = i;	c->c_free = 1;	freemem += CLSIZE;#ifdef KM_STATS	km_stats.tot_pffree++;#endif KM_STATS	splx(s);}/* * Enter clist block c on the hash chains. * It contains file system block bn from device dev. * Dev must either be a mounted file system or the swap device */mhash(c, dev, bn)	register struct cmap *c;	dev_t dev;	daddr_t bn;{	register int i = CMHASH(bn);	register struct mount *mp;	register struct text *xp;	#ifdef mips	XPRINTF(XPR_VM,"enter mhash",0,0,0,0);#endif mips	c->c_hlink = cmhash[i];	cmhash[i] = c - cmap;	c->c_blkno = bn;	xp = &text[c->c_ndx];	GETMP(mp, dev);		if(mp == NULL)		panic("mhash: no mp");	c->c_mdev = (mp == (struct mount *) MSWAPX) ? MSWAPX : mp - mount;	if (X_DO_RHASH(xp))	        G_SET_HCMAP(xp, xp->x_gptr, c, c - cmap);}/* * Pull the clist entry of <dev,bn> off the hash chains. * We have checked before calling (using mfind) that the * entry really needs to be unhashed, so panic if we can't * find it (can't happen). * * N.B. if dev == swapdev, gp is NULL since the block on the swap * device may not be associated with any active text or data segment */munhash(dev, bn, gp)	register dev_t dev;	register daddr_t bn;	register struct gnode *gp;{	register struct cmap *c1, *c2;	register int index;	register struct gnode *gpproto = NULL;	struct text *xp;	int i = CMHASH(bn);	struct mount *mp;	int needgp = 1;	int si = splimp();	#ifdef mips	XPRINTF(XPR_VM,"enter munhash",0,0,0,0);#endif mips	c1 = &cmap[cmhash[i]];	if (c1 == ecmap)		panic("munhash");		if (gp && gp->g_dev == dev) {	/* handle simple case to save */		index = gp->g_mp - mount;		mp = gp->g_mp;	} else {		GETMP(mp, dev)		index = (mp == (struct mount *) MSWAPX) ? MSWAPX : mp - mount;	}		/*	 * it is sufficient for the local case to use just dev and bn	 * since locally we use lbn's rather than vbn's	 */		if((index == MSWAPX) || (mp->m_flags & M_LOCAL)) {		gpproto = gp;	/* so matches work out */		needgp = 0;	/* local doesn't need gp */	} else  {	        if (c1->c_type != CTEXT)		        panic("munhash: unhashing non text page");		gpproto = text[c1->c_ndx].x_gptr;	}	if ((c1->c_blkno) == bn && (index == c1->c_mdev) && (gp == gpproto)) {		cmhash[i] = c1->c_hlink;	} else {		for (;;) {			c2 = c1;			c1 = &cmap[c2->c_hlink];			if (c1 == ecmap)				panic("munhash: ecmap");			if(needgp) {			        if (c1->c_type != CTEXT)				        panic("muhash: unhashing non text page 2");				gpproto = text[c1->c_ndx].x_gptr;			}							if ((c1->c_blkno == bn) && (index == c1->c_mdev) &&				(gp == gpproto)) {			  break;			}		}		c2->c_hlink = c1->c_hlink;	}	if (mfind(dev, bn, gp)) 		panic("munhash mfind");        xp = &text[c1->c_ndx];	if (X_DO_RHASH(xp))                G_RST_HCMAP(xp,gp,c1);	c1->c_mdev = (u_char) NODEV;	c1->c_blkno = 0;	c1->c_hlink = 0;	splx(si);}/* * maunhash -- This routine is the same as munhash(), except that the *             match is on the CMAP address not the mdev/gnode *   *             This gets rid of those silly "pseudo-munhashes" that have *             plagued us. */maunhash(c)     register struct cmap *c;{	register struct cmap *c1, *c2;	register int j;	register struct gnode *gp;	register struct text *xp;#ifdef mips	XPRINTF(XPR_VM,"enter maunhash",0,0,0,0);#endif mips        j = CMHASH(c->c_blkno);	c1 = &cmap[cmhash[j]];	if (c1 == c)		cmhash[j] = c1->c_hlink;	else {		for (;;) {			if (c1 == ecmap)				panic("maunhash ecmap");			c2 = c1;			c1 = &cmap[c2->c_hlink];			if (c1 == c)				break;		}		c2->c_hlink = c1->c_hlink;	}	if (c->c_type != CTEXT)	        panic("maunhash: unhashing non text page");	xp = &text[c->c_ndx];	gp = xp->x_gptr;	/* do an mfind() to insure that duplicates aren't found */	if (mfind(c->c_mdev==MSWAPX?swapdev:mount[c->c_mdev].m_dev,	      (daddr_t)c->c_blkno, gp)) {		printf(" maunhash: mdev 0x%x blkno %d x_gptr 0x%x\n",		  c->c_mdev== MSWAPX?swapdev:mount[c->c_mdev].m_dev,		  c->c_blkno, gp);		panic("maunhash: mfind");	}	/* if remote and large, remove from hash array */	if (X_DO_RHASH(xp))                G_RST_HCMAP(xp,gp,c);	/* finish unhashing the given CMAP entry */	c->c_mdev = (u_char) NODEV;	c->c_blkno = 0;	c->c_hlink = 0;}/* * Look for block bn of device dev in the free pool. * Currently it should not be possible to find it unless it is * c_free and c_gone, although this may later not be true. * (This is because active texts are locked against file system * writes by the system.) * * N.B. if dev == swapdev, gp is NULL since the block on the swap * device may not be associated with any active text or data segment */struct cmap *mfind(dev, bn, gp)	register dev_t dev;	register daddr_t bn;	register struct gnode *gp;{	register struct cmap *c1 = &cmap[cmhash[CMHASH(bn)]];	register int index;	register struct gnode *gpproto = NULL;	struct mount *mp;	int needgp = 1;	int si = splimp();	#ifdef mips	XPRINTF(XPR_VM,"enter mfind",0,0,0,0);#endif mips	if (gp && gp->g_dev == dev) {	/* handle simple case to save */		if ((mp = gp->g_mp) == NULL) {			splx(si);			return((struct cmap *) 0);		}		index = gp->g_mp - mount;	}	else {		GETMP(mp, dev)		if (mp == NULL) {			splx(si);			return((struct cmap *) 0);		}		index = (mp == (struct mount *) MSWAPX) ? MSWAPX : mp - mount;	}		/*	 * it is sufficient for the local case to use just dev and bn	 * since locally we use lbn's rather than vbn's	 * this includes the swap device	 */	if((index == MSWAPX) || (mp->m_flags & M_LOCAL)) {		gpproto = gp;	/* so matches work out */		needgp = 0;	/* local doesn't need the gp */	}	/* now search the core map */	while (c1 != ecmap) {		if(needgp) {		        if (c1->c_type != CTEXT)			        panic("mfind: trying to find non text on hash");		        gpproto = text[c1->c_ndx].x_gptr;		}		if((c1->c_blkno == bn) && (c1->c_mdev == index) &&		(gp == gpproto)) {			splx(si);			return (c1);		}		c1 = &cmap[c1->c_hlink];	}	splx(si);	return ((struct cmap *)0);}/* * Purge blocks from device dev from incore cache * before umount(). */mpurge(mdev)	int mdev;{	register struct cmap *c1, *c2;	register int i;	register struct text *xp;	int si = splimp();

⌨️ 快捷键说明

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