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

📄 virtual.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 5 页
字号:
}

// ********************************************************************
// 声明:static void Seg_FreeRegion( LPSEGMENT lpSeg, int idxFirstBlk )
// 参数:
//		IN lpSeg - 段结构指针
//		IN idxFirstBlk - 起始块
// 返回值:
//		无
// 功能描述:
//		释放块组(内存区域)
// 引用:
//		
// ********************************************************************
static void Seg_FreeRegion( LPSEGMENT lpSeg, int idxFirstBlk )
{
	LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxFirstBlk;  // 起始块地址
	LPMEMBLOCK * lppBlkEnd = lpSeg->lpBlks + BLOCKS_PER_SEGMENT; // 最大结束块地址
	LPMEMBLOCK lpBlk;

	while( lppBlks < lppBlkEnd )
	{
		lpBlk = *lppBlks;
		if( lpBlk == NULL_BLOCK )
			break;  // 结束
		else if( lpBlk <= RESERVED_BLOCK )
		{   // 设为NULL_BLOCK
			*lppBlks = NULL_BLOCK;
		}
		else if( lpBlk->idxFirst != idxFirstBlk )
		{   // 结束 end
			break;
		}
		else
		{   // 已分配的块,释放它commited block
			KHeap_Free( lpBlk, sizeof(MEMBLOCK) );//_kfree( lpBlk );
			*lppBlks = NULL_BLOCK;
		}
		lppBlks++;  // 下一个块
	}
}

// ********************************************************************
// 声明:int Seg_ReviewRegion( LPSEGMENT lpSeg, 
//					 int idxFirstBlk,
//					 int idxReviewBlk,
//					 int idxStartPage,
//					 int iReviewPages,
//					 int * lpiCountPages )
// 参数:
//		IN lpSeg - 段结构指针
//		IN idxFirstBlk - 内存域第一个块
//		IN idxReviewBlk - 内存域中需要检视的起始块
//		IN idxStartPage - 内存域中需要检视的起始块中的开始页. 假如为-1,则检视到该域的结束
//		IN iReviewPages - 需要检视的页数
//		IN/OUT lpiCountPages - 用于接受检视的合法页数, 同时也说明该函数是否仅仅执行统计功能。
//							如果为NULL,则为每一个保留块分配一个块结构
// 返回值:
//		假如成功,返回需要分配的物理页数;错误返回-1
// 功能描述:
//		从指定区域位置开始检视一定的页数。假如lpiCountPages为NULL,则为每一个保留的块位置分配一个块结构
// 引用:
//		
// ********************************************************************
// returen need alloc physical page
#define DEBUG_SEG_REVIEWREGION 0
int Seg_ReviewRegion( LPSEGMENT lpSeg, 
					 int idxFirstBlk,
					 int idxReviewBlk,
					 int idxStartPage,
					 int iReviewPages,
					 int * lpiCountPages )
{
	LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxReviewBlk; // 起始块地址
	LPMEMBLOCK lpBlk, lpStartBlk;
	int iPages = 0;
	int iAllocPages = 0;


    lpStartBlk = lpSeg->lpBlks[idxFirstBlk];
	if( iReviewPages == -1 )  // 需要检视到结束吗 ?
	{	// 是,设置为最大
		iReviewPages = (BLOCKS_PER_SEGMENT - idxReviewBlk) * PAGES_PER_BLOCK - idxStartPage;//BLOCKS_PER_SEGMENT * PAGES_PER_BLOCK;
	}
	DEBUGMSG( DEBUG_SEG_REVIEWREGION, ( "idxFirstBlk=%d,idxReviewBlk=%d,idxStartPage=%d,iReviewPages=%d.\r\n", idxFirstBlk,idxReviewBlk,idxStartPage,iReviewPages ) );
	while( iPages < iReviewPages )
	{
		lpBlk = *lppBlks;
		DEBUGMSG( DEBUG_SEG_REVIEWREGION, ( "Seg_ReviewRegion:lpBlk=%x.\r\n", lpBlk ) );
		if( lpBlk <= RESERVED_BLOCK && lpBlk != NULL_BLOCK )  // 该块已被保留并且没有为其分配块结构吗 ?
		{   // 已被保留,假如可能,分配一个块结构。now to commit a reserver block if need
			int nAlloc;
			if( lpiCountPages == NULL )   // 仅仅为了统计吗 ?
			{    // 否,需要分配一个块结构
				lpBlk = KHeap_Alloc( sizeof( MEMBLOCK ) );
				if( lpBlk )
				{   // 初始化块结构
					memset( lpBlk, 0, sizeof( MEMBLOCK ) );					
					lpBlk->idxFirst = lpStartBlk->idxFirst;  // 指向内存域的第一个块
					lpBlk->uiKey = lpStartBlk->uiKey;
					lpBlk->wLockCount = lpStartBlk->wLockCount;	
					*lppBlks = lpBlk;
				}
				else //no memory
				{   // 没有内存
					ERRORMSG( 1, ( "Seg_ReviewRegion error: no enough memory.\r\n" ) );
					KL_SetLastError( ERROR_NOT_ENOUGH_MEMORY );
					goto _err_return;//break;
				}
			}
			nAlloc = PAGES_PER_BLOCK - idxStartPage; // 该块的页数
			if( iPages + nAlloc > iReviewPages )  // 是否已统计完所有的页?
			{   // 是
				iAllocPages += iReviewPages - iPages; // 真实的物理页
				iPages = iReviewPages;	// 统计完,设置退出循环条件				
			}
			else
			{	// 
				iPages += nAlloc;//已检视的页数
				iAllocPages += nAlloc;//需要的物理页数
			}
		}
		else if( lpBlk == NULL_BLOCK || lpBlk->idxFirst != idxFirstBlk )
		{	// 该内存域已结束
			if( lpiCountPages )
				break;  // 如果仅仅是为了统计,正常退出。end count
			// 不是为了统计,有错误!!!
			ERRORMSG( 1, ( "Seg_ReviewRegion error: invalid lpBlk=0x%x,lpBlk->idxFirst=%d,idxFirstBlk=%d.\r\n", lpBlk, (lpBlk) ? lpBlk->idxFirst : 0, idxFirstBlk ) );
			KL_SetLastError( ERROR_INVALID_PARAMETER );
			goto _err_return;
		}
		else
		{   // 该块有一个内存块结构,检视其页
			LPUINT lpuiPage = &lpBlk->uiPages[idxStartPage];
			DEBUGMSG( DEBUG_SEG_REVIEWREGION, ( "Seg_ReviewRegion:Commit Blk,iPages=%d.\r\n", iPages ) );
			while( iPages < iReviewPages && idxStartPage < PAGES_PER_BLOCK ) //
			{
				UINT uiPage;
				if( (uiPage = *lpuiPage) == 0 )  // 还没有提交物理页吗 ?
				{   // 没有,增加
					iAllocPages++;
				}
				else if( uiPage == INVALID_PAGE )
				{   // 该页是一个无效页,在内存域的结束边界。error
					if( lpiCountPages )  // 如果是为了统计,正确返回
						goto _return;
					// 错误,没有达到指定的检视页数
			        KL_SetLastError( ERROR_INVALID_PARAMETER );
					ERRORMSG( 1, ( "Seg_ReviewRegion error: invalid page.\r\n" ) );
					goto _err_return;
				}
				idxStartPage++;
				lpuiPage++;
				iPages++;
			}
		}
		idxStartPage = 0;  // 下一个块的开始页
		lppBlks++;	// 下一个块
	}
_return:
	if( lpiCountPages )
		*lpiCountPages = iPages;
	return iAllocPages;
_err_return:
	return -1;
}

// ********************************************************************
// 声明:BOOL Seg_ScanCommitRegion( LPSEGMENT lpSeg, 
//					 int idxFirstBlk,
//					 int idxScanBlk,
//					 int idxStartPage,
//					 int iScanPages )

// 参数:
//		IN lpSeg - 段结构指针
//		IN idxFirstBlk - 内存域第一个块
//		IN idxScanBlk - 内存域中需要扫描的起始块
//		IN idxStartPage - 内存域中需要扫描的起始块中的开始页
//		IN iScanPages - 需要扫描的页数
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		扫描指定的内存域是否有指定的(iReviewPages)已经提交的物理页。假如有,返回TRUE.
// 引用:
//		
// ********************************************************************
// returen need alloc physical page
BOOL Seg_ScanCommitRegion( LPSEGMENT lpSeg, 
					 int idxFirstBlk,
					 int idxScanBlk,
					 int idxStartPage,
					 int iScanPages )
{
	LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxScanBlk;  // 开始扫描块
	LPMEMBLOCK lpBlk;
	int iPages = 0;
	BOOL bRetv = TRUE;

	while( iPages < iScanPages )
	{
		lpBlk = *lppBlks;
		// 2004-01-28, this is a error ?, i will check it
		//if( lpBlk > RESERVED_BLOCK && lpBlk->idxFirst != idxFirstBlk )
		if( lpBlk > RESERVED_BLOCK && lpBlk->idxFirst == idxFirstBlk )
		// 
		{
			LPUINT lpuiPage = &lpBlk->uiPages[idxStartPage];
			while( iPages < iScanPages && idxStartPage < PAGES_PER_BLOCK )
			{
				UINT uiPage;
				if( (uiPage = *lpuiPage) == 0 ||
					 uiPage == INVALID_PAGE )   //  页已经提交了吗 ?
				{	// 没有,错误
					bRetv = FALSE;
			        KL_SetLastError( ERROR_INVALID_PARAMETER );
					goto _return;
				}
				idxStartPage++;
				lpuiPage++;  // 下一页
				iPages++;  // 已统计的页数
			}
		}
		else
		{	// 有非该内存域的块或有非提交页,错误
			bRetv = FALSE;
	        KL_SetLastError( ERROR_INVALID_PARAMETER );
			goto _return;
		}

		idxStartPage = 0;
		lppBlks++;	//下一个块
	}
_return:
	return bRetv;
}

// ********************************************************************
// 声明:BOOL Seg_ResetPageAttrib( 
//					    LPPROCESS_SEGMENTS lpProcessSeg,
//						LPSEGMENT lpSeg, 
//						int idxFirstBlk,
//						int idxReviewBlk,
//						int idxStartPage,
//						int iReviewPages,
//						DWORD dwNewAttrib )

// 参数:
//		IN lpProcessSeg - 进程段组
//		IN lpSeg - 段结构指针
//		IN idxFirstBlk - 内存域第一个块
//		IN idxReviewBlk - 内存域中需要重设的起始块
//		IN idxStartPage - 内存域中需要重设的起始块中的开始页
//		IN iReviewPages - 需要重设的页数
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		重新设定页的属性
// 引用:
//		
// ********************************************************************
//
BOOL Seg_ResetPageAttrib( 
						 LPPROCESS_SEGMENTS lpProcessSeg,
						 LPSEGMENT lpSeg, 
						 int idxFirstBlk,
						 int idxReviewBlk,
						 int idxStartPage,
						 int iReviewPages,
						 DWORD dwNewAttrib )
{
	LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxReviewBlk;  // 开始页
	LPMEMBLOCK lpBlk;
	int iPages = 0;
	BOOL bRetv = TRUE;
	UINT uStartPage; 
	BOOL bWriteToSecondPage;
	UINT uMinPage, uMaxPage;

	DWORD dwPhysAddrMask = GetPhyPageAdrMask();

	uMinPage = uStartPage = idxReviewBlk * PAGES_PER_BLOCK + idxStartPage;
	uMaxPage = uStartPage + iReviewPages;

	bWriteToSecondPage = GetPagesInCacheRange( lpProcessSeg, &uMinPage, &uMaxPage );

	while( iPages < iReviewPages )
	{
		LPUINT lpuiPage;

		lpBlk = *lppBlks;
		// 2004-01-28, this is a error, i will test it
		// ASSERT( lpBlk > RESERVED_BLOCK && lpBlk->idxFirst != idxFirstBlk );
		ASSERT( lpBlk > RESERVED_BLOCK && lpBlk->idxFirst == idxFirstBlk );
		//
		//重新设定该块的页的属性 
		lpuiPage = &lpBlk->uiPages[idxStartPage];
		while( iPages < iReviewPages && idxStartPage < PAGES_PER_BLOCK )
		{
			ASSERT( *lpuiPage != 0 && *lpuiPage != INVALID_PAGE );
			*lpuiPage = ( *lpuiPage & dwPhysAddrMask ) | dwNewAttrib;

			//更新页表-2005-02-03
			if( bWriteToSecondPage && 
				PAGE_IN_RANGE( uStartPage, uMinPage, uMaxPage ) )
			{
				lpProcessSeg->lpdwSecondPageTable[uStartPage] = *lpuiPage;
			}
			uStartPage++;
			//

			lpuiPage++;  // 下一页
			idxStartPage++;
			iPages++;
		}

		idxStartPage = 0;
		lppBlks++;	//下一个块
	}
	return TRUE;
}

// ********************************************************************
// 声明:BOOL Seg_DecommitPages( 
//							LPPROCESS_SEGMENTS lpProcessSeg,
//							LPSEGMENT lpSeg,
//							int idxStartBlk,
//							int idxStartPages,
//							int iPages 
//							)
// 参数:
//		IN lpProcessSeg - 进程段组
//		IN lpSeg - 段结构指针
//		IN idxStartBlk - 内存域中需要重设的起始块
//		IN idxStartPages - 内存域中需要重设的起始块中的开始页
//		IN iPages - 需要重设的页数
// 返回值:
//		假如有释放物理页,返回TRUE;否则,返回FALSE
// 功能描述:
//		释放指定内存域的物理页
// 引用:
//		
// ********************************************************************
#define DEBUG_SEG_DECOMMITPAGES 0
BOOL Seg_DecommitPages( LPPROCESS_SEGMENTS lpProcessSeg, 
					    LPSEGMENT lpSeg, 
						int idxStartBlk, 
						int idxStartPages, 
						int iPages )
{
	LPMEMBLOCK * lppBlks = lpSeg->lpBlks + idxStartBlk; // 开始块
	BOOL bFlush = FALSE;
	UINT uStartPage, uMinPage, uMaxPage;
	BOOL bWriteToSecondPage;

	//需要CACHE ?-2005-02-02
	uMinPage = uStartPage = idxStartBlk * PAGES_PER_BLOCK + idxStartPages;
	uMaxPage = uStartPage + iPages;
	bWriteToSecondPage = GetPagesInCacheRange( lpProcessSeg, &uMinPage, &uMaxPage );

	//

	while( iPages > 0 )
	{
		ASSERT( *lppBlks != NULL_BLOCK );
		if( *lppBlks <= RESERVED_BLOCK )
		{	// 是保留块,减去其中的页数
			int n = PAGES_PER_BLOCK - idxStartPages;
			iPages -= n;

			uStartPage += n;
		}
		else
		{	// 内存块
			UINT *lpui;
			// 查找块内是否有物理页
			lpui = &(*lppBlks)->uiPages[idxStartPages];
			while( iPages && idxStartPages < PAGES_PER_BLOCK )
			{
				if( *lpui && *lpui != INVALID_PAGE )

⌨️ 快捷键说明

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