📄 virtual.c
字号:
}
// ********************************************************************
// 声明: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 + -