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

📄 page.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	  ||(opfe->md.mel == NULL )||( opfe->dbn_id == PAGEFILE_ID )) {		/* Check for invalid pages although they are unlikely to exist. */		err = E_MACV;		goto err_ret2;	}	/* Pages are write-protected before copy-on-write is performed, but sometimes	 * updated by BMS. In such a case, return an error so that such pages do not	 * remain on the disk cache.	 */	if ( isUpdateP(pte.w) ) {		opfe->err = TRUE;	}	/* Cancel the cache content to replace physical memory. */	InvalidateCachePage(laddr, lsid);	/* Reserve new page frame	 *	Turn old page frames into unregistered pages temporarily so that	 *	they are not paged out.	 */	opfe->reg = FALSE;	npfe = GetPFM(PFS_use, FALSE);	opfe->reg = TRUE;	if ( npfe == NULL ) {		/* If new page frames cannot be reserved,		   reuse old page frames. */		err = PageOut(opfe, FALSE);		if ( err < E_OK ) {			goto err_ret2;		}		/* Deregister from DBH and separate from queue. */		RemoveDBH(opfe);		removePageFrameQue(opfe);		/* Initialize opfe content. */		bzero(opfe, (size_t)sizeof(PFE));		/* Register in queue */		RegistPageFrame(opfe, PFS_use);		if ( isLocalSpace(laddr) != 0 ) {			/* Update process statistical information			   Reset the count by PageOut(). */			PINFO *pinfo = GetPINFO_lsid(lsid);			if ( pinfo != NULL ) {				pinfo->allocpage++;				pinfo->poutcount--;			}		}		npfe = opfe;	} else {		/* Copy content to new page frames */		memcpy(p = PFEtoLADR(npfe), PFEtoLADR(opfe), (size_t)PAGESIZE);		WriteBackDCachePage(p, 0);	}	/* Set PFE */	npfe->md.page.lsid = lsid;	npfe->md.page.pn = (UW)laddr / (UW)PAGESIZE;	/* Update page table */	pte.c.pfa = PFEtoPFA(npfe);	pte.w |= PT_Writable;	SetPTE(&pth, pte.w, TRUE);norm_ret:	EndPTH(&pth, FALSE);	return E_OK;err_ret2:	EndPTH(&pth, FALSE);err_ret1:	DEBUG_PRINT(("CopyOnWrite err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* *	Obtain/release page frame *//* * Connect to page frame queue */LOCAL void insertPageFrameQue( PFE *pfe, PFS stat ){	pfe->stat = stat;	/* Register in queue */	switch ( stat ) {	  case PFS_lock:		InsertPFE_Q(&LockPFE_Q, pfe);		break;	  case PFS_use:		InsertPFE_Q(&UsePFE_Q, pfe);		break;	  case PFS_free:		InsertPFE_Q(&FreePFE_Q, pfe);		break;	  case PFS_uninit:		PutUninitPFE(pfe);		break;	  default:		/* nothing to do */		break;	}}/* * Disconnect from page frame queue */LOCAL void removePageFrameQue( PFE *pfe ){	switch ( pfe->stat ) {	  case PFS_lock:		RemovePFE_Q(&LockPFE_Q, pfe);		break;	  case PFS_use:		RemovePFE_Q(&UsePFE_Q, pfe);		break;	  case PFS_free:		RemovePFE_Q(&FreePFE_Q, pfe);		break;	  case PFS_uninit:		RemoveUninitPFE(pfe);		break;	  default:		/* nothing to do */		break;	}}/* * Register page frame queue *	Register pfe in stat queue. *	"stat = PFS_uninit" is not acceptable. */EXPORT void RegistPageFrame( PFE *pfe, PFS stat ){	/* Register in DBH */	RegistDBH(pfe);	/* Register in queue */	insertPageFrameQue(pfe, stat);	pfe->reg = TRUE;  /* Page frame already registered */}/* * Move page frame queue *	Move from pfe->stat queue to stat queue. *	"PFS_uninit" is not acceptable for both queues. */EXPORT void MovePageFrame( PFE *pfe, PFS stat ){	removePageFrameQue(pfe);	insertPageFrameQue(pfe, stat);}/* * Cancel page frames *	"pfe->stat = PFS_uninit" is not acceptable. */EXPORT void DiscardPageFrame( PFE *pfe ){	/* Deregister from DBH. */	RemoveDBH(pfe);	/* Separate from queue */	removePageFrameQue(pfe);	/* Register in uninitialized page */	PutUninitPFE(pfe);}/* * Cancel page frames *	Cancel all page frames that have de disk content. */EXPORT void DiscardPageFrameDE( DE *de ){	ID	did = toDiskID(de);	PFE	*pfe;	PFN	npfn;	W	i;	for ( i = 0; i < (W)MaxDBH; i++ ) {		npfn = DiskBlockHash[i];		while( npfn != 0U ) {			pfe = PFNtoPFE(npfn);			npfn = pfe->dbh;			if ( pfe->dbn_id == did ) {				DiscardPageFrame(pfe);			}		}	}}/* * Obtain a page frame that follows ppfe. *	If it could not be obtained, return NULL. */LOCAL PFE* getNextPageFrame( PFE *ppfe, UW rank ){	PFE	*pfe = ppfe + 1;	ER	err;	if ( PFEtoPFN(pfe) > MaxPages ) {		return NULL;	}	/* High ranks are not acceptable. */	if ( pfe->rank < rank ) {		return NULL;	}	switch ( pfe->stat ) {	  case PFS_lock:		return NULL;	/* Pages must not be locked. */	  case PFS_use:		break;	  case PFS_free:		break;	  case PFS_uninit:		return RemoveUninitPFE(pfe);	  default:		/* nothing to do */		break;	}	/* Unregistered pages must not be allocated. */	if ( !pfe->reg ) {		return NULL;	}	/* Page out. */	err = PageOut(pfe, FALSE);	if ( err < E_OK ) {		goto err_ret;	}	/* Deregister from DBH and separate from queue. */	RemoveDBH(pfe);	removePageFrameQue(pfe);	SnatchCount++;	return pfe;err_ret:	DEBUG_PRINT(("getNextPageFrame err = %d\n", err));	return NULL;}/* * Obtain any of the page frames. *	When "nowrite = TRUE", search for pages to be allocated, except for pages that *	needed to be written to the disk (paged out). */LOCAL PFE* getFreePageFrame( BOOL nowrite ){	PFE	*pfe;	ER	err;	/* Search for uninitialized page */	pfe = GetUninitPFE();	if ( pfe != NULL ) {		return pfe;	}	/* Search for free page queue */	pfe = NULL;	while ( (pfe = NextPFE_Q(&FreePFE_Q, pfe)) != NULL ) {		/* Page out. */		err = PageOut(pfe, nowrite);		if ( err == E_OK ) {			/* Move queue top */			SetTopPFE_Q(&FreePFE_Q, pfe);			/* Deregister from DBH and separate from queue. */			RemoveDBH(pfe);			RemovePFE_Q(&FreePFE_Q, pfe);			return pfe;		}	}	/* Search for queue for page in use */	pfe = NULL;	while ( (pfe = NextPFE_Q(&UsePFE_Q, pfe)) != NULL ) {		/* Page out. */		err = PageOut(pfe, nowrite);		if ( err == E_OK ) {			/* Move queue top */			SetTopPFE_Q(&UsePFE_Q, pfe);			/* Deregister from DBH and separate from queue. */			RemoveDBH(pfe);			RemovePFE_Q(&UsePFE_Q, pfe);			return pfe;		}	}	return NULL;}/* * Obtain page frame *	1. A page frames that has dbn blocks *	2. If not found, obtain a page frame whose next page is below rank. *	3. If not found, obtain any other frame. *	When "dbn.id = dbn.no = 0", remove 1. *	When "ppfe = NULL", remove 2. * *	The obtained frame is an independent one that does not belong to any queue. *	If the obtained frame has dbn blocks, return 1 as a return value. *	If other page frame type was found, return 0. *	If no page frame was found, return E_NOMEM. */EXPORT W GetPageFrame( PFE **pfe_p, DBN dbn, PFE *ppfe, UW rank ){	PFE	*pfe = NULL;	W	hit = 0;	if ( !((dbn.no == 0 )&&( dbn.id == 0))) {		/* Search for DBH */		pfe = SearchDBH(dbn);		if ( pfe != NULL ) {			/* Temporarily deregister from DBH and separate from queue. */			RemoveDBH(pfe);			removePageFrameQue(pfe);			pfe->reg = FALSE;			if ( rank < pfe->rank ) {				pfe->rank = rank;			}			hit = 1;			HashHitCount++;		} else {			HashMissCount++;		}	}	if ( hit == 0 ) {		/* New page */		if ( ppfe != NULL ) {			/* Next page */			pfe = getNextPageFrame(ppfe, rank);		}		if ( pfe == NULL ) {			/* Any page */			pfe = getFreePageFrame(FALSE);		}		if ( pfe == NULL ) {			goto err_ret;		}		/* Initialize PFE content. */		bzero(pfe, (size_t)sizeof(PFE));		pfe->dbn_id = dbn.id;		pfe->dbn_no = dbn.no;		pfe->rank = rank;		pfe->stat = PFS_free;		/* Cancel cache content. */		InvalidateCachePage(PFEtoLADR(pfe), 0);	}	*pfe_p = pfe;	return hit;err_ret:	DEBUG_PRINT(("GetPageFrame err = %d\n", E_NOMEM));	return E_NOMEM;}/* * Uninitialize page frames obtained by GetPageFrame() and return. */EXPORT void UngetPageFrame( PFE *pfe ){	/* Deregister from DBH. */	RemoveDBH(pfe);	/* Register in uninitialized page */	PutUninitPFE(pfe);}/* * Obtain page frame *	When "nowrite = TRUE", search for pages to be allocated, except for pages that *	needed to be written to the disk (paged out). */EXPORT PFE* GetPFM( PFS stat, BOOL nowrite ){	PFE	*pfe;	/* Obtain any of the pages. */	pfe = getFreePageFrame(nowrite);	if ( pfe == NULL ) {		goto err_ret;	}	/* Initialize PFE content. */	bzero(pfe, (size_t)sizeof(PFE));	/* Register in queue */	RegistPageFrame(pfe, stat);	/* Cancel cache content. */	InvalidateCachePage(PFEtoLADR(pfe), 0);	return pfe;err_ret:	DEBUG_PRINT(("GetPFM err = %d\n", E_NOMEM));	return NULL;}/* ------------------------------------------------------------------------ *//* *	Allocate special page frame *//* * Adaptability to allocation */Inline UW MATCH( PFE *pfe ){	return ((UW)pfe->stat << TSD_MAT_SFT_4)		| ((TSD_MAT_VAL_7 - (UW)pfe->rank) << 1)		| (UW)pfe->upd;}/* * Search for consecutive free areas *	Allocate areas in such a way as to minimize unnecessary page-out processing. */LOCAL PFE* searchContinuousFreePFE( UW npage ){	PFE	*pfe, *top, *end;	UW	np, match, n, i;	struct {		UW	match;		PFE	*pfe;	} best;	best.match = TSD_SCP_MAT_0XFFFFFFFF;	best.pfe = NULL;	pfe = PageFrameEntry + 1;	for ( i = 0; i < (UW)MemInfo->n; i++ ) {		n = MemInfo->a[i].p.npage;		if ( n < npage ) {			pfe += n;			continue;		}		end = pfe + n;		match = np = 0;		while ( pfe < end ) {			if ( pfe->stat == PFS_uninit ) {				n = (UW)pfe->dbn_no; /* Number of consecutive free pages */				if ( n >= npage ) {					return pfe;				}				np += n;				pfe += n;			} else {				if (( pfe->stat == PFS_lock )|| !pfe->reg ) {					/* Pages that cannot be allocated */					match = np = 0;					pfe++;					continue;				}				match += MATCH(pfe);				np++;				pfe++;			}			while ( np >= npage ) {				top = pfe - np;				if ( match < best.match ) {					best.match = match;					best.pfe = top;				}				if ( top->stat == PFS_uninit ) {					np -= (UW)top->dbn_no;				} else {					match -= MATCH(top);					np--;				}			}		}	}	return best.pfe;}/* * Obtain page frames that have consecutive physical addresses. */EXPORT VP AllocPhysicalMem( UW npage ){	PFE	*pfe, *top;	/* Check if the upper size limit of resident memory is not exceeded. */	if ( (W)npage > LockablePages(NULL) ) {		goto err_ret;	}	/* Search for consecutive free areas */	top = searchContinuousFreePFE(npage);	if ( top == NULL ) {		goto err_ret;	}	/* Obtain free areas and set them to PFS_lock state. */	pfe = top - 1U;	while ( npage-- > 0U ) {		/* Obtain page */		pfe = getNextPageFrame(pfe, 0);		if ( pfe == NULL ) {			goto err_ret;		}		/* Initialize PFE content. */		bzero(pfe, (size_t)sizeof(PFE));		/* Register in queue */		RegistPageFrame(pfe, PFS_lock);		/* Cancel cache content. */		InvalidateCachePage(PFEtoLADR(pfe), 0);	}	return toPhysicalAddress(PFEtoLADR(top));err_ret:	DEBUG_PRINT(("AllocPhysicalMem err = %d\n", E_NOMEM));	return NULL;}/* ------------------------------------------------------------------------ *//* *	Control related to logical space (page table) and page frame *//* * Discontinue relations of pages (PTE). *	pinfo	For unique space, specify processes to use. *		For shared space, return NULL. */EXPORT ER UnlinkPage( PTE pte, PINFO *pinfo ){	if ( isPresentP(pte.w) || isValidP(pte.w)) {		/* Page frame is present. */		PFE *pfe = PFAtoPFE(pte.c.pfa);		if ( pfe == NULL ) {			return E_OK; /* Not to be managed */		}		if ( pfe->dbn_id == PAGEFILE_ID ) {			/* Page file			 *	Release, if any, obtained page files.			 *	Release page frames.			 */			if ( pfe->dbn_no > 0 ) {				FreePageFile(pfe->dbn_no);			}			DiscardPageFrame(pfe);		} else {			/* Disk map			 *	Check update flag			 *	Write-protect pages are sometimes			 *	updated by BMS. In such a case,			 *	do not write them to the disk.			 *	Return an error so that such pages			 *	do not remain on the disk cache.			 */			if ( isUpdateP(pte.w) ) {				if ( isWritableP(pte.w) ) {					pfe->upd = TRUE;				}else{					pfe->err = TRUE;				}			}		}		/* Update process statistical information */		if ( pinfo != NULL ) {			pinfo->allocpage--;		}	} else {		/* Page frame is absent.		 *	Disk map: Nothing has to be done.

⌨️ 快捷键说明

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