?? vmm.cpp
字號(hào):
DWORD dwSize,
DWORD dwAllocFlags,
DWORD dwAccessFlags,
UCHAR* lpVaName,
LPVOID lpReserved)
{
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
LPVOID lpStartAddr = NULL;
LPVOID lpPhysical = NULL;
DWORD dwFlags = 0L;
DWORD dwPteFlags = 0L;
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
BOOL bResult = FALSE;
if((NULL == lpThis) || (NULL == lpDesiredAddr))
return NULL;
if(dwAllocFlags != VIRTUAL_AREA_ALLOCATE_COMMIT) //This routine only process commit.
return NULL;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Should search in list.
lpVad = GetVaByAddr_l(lpThis,lpDesiredAddr);
else //Should search in the AVL tree.
lpVad = GetVaByAddr_t(lpThis,lpDesiredAddr);
if(NULL == lpVad) //The virtual memory area is not reserved before.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
lpStartAddr = lpVad->lpStartAddr;
dwSize = (DWORD)lpVad->lpEndAddr - (DWORD)lpStartAddr + 1;
lpPhysical = PageFrameManager.FrameAlloc((__COMMON_OBJECT*)&PageFrameManager,
dwSize,
0L);
if(NULL == lpPhysical) //Can not allocate physical memory.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
//
//The following code reserves page table entries for this virtual area.
//
lpVad->dwAllocFlags = VIRTUAL_AREA_ALLOCATE_COMMIT;
dwPteFlags = PTE_FLAGS_FOR_NORMAL; //Normal flags.
while(dwSize)
{
if(!lpIndexMgr->ReservePage((__COMMON_OBJECT*)lpIndexMgr,
lpStartAddr,lpPhysical,dwPteFlags))
{
PrintLine("Fatal Error : Internal data structure is not consist.");
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
dwSize -= PAGE_FRAME_SIZE;
lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
lpPhysical = (LPVOID)((DWORD)lpPhysical + PAGE_FRAME_SIZE);
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
bResult = TRUE; //Indicate that the whole operation is successfully.
__TERMINAL:
if(!bResult) //The transaction is failed.
{
if(lpPhysical)
PageFrameManager.FrameFree((__COMMON_OBJECT*)&PageFrameManager,
lpPhysical,
dwSize);
return NULL;
}
return lpDesiredAddr; //The lpDesiredAddr should never be changed.
}
//
//DoReserve routine.When VirtualAlloc is called with VIRTUAL_AREA_ALLOCATE_RESERVE,
//then is routine is called by VirtualAlloc.
//
static LPVOID DoReserve(__COMMON_OBJECT* lpThis,
LPVOID lpDesiredAddr,
DWORD dwSize,
DWORD dwAllocFlags,
DWORD dwAccessFlags,
UCHAR* lpVaName,
LPVOID lpReserved)
{
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
LPVOID lpStartAddr = lpDesiredAddr;
LPVOID lpEndAddr = NULL;
DWORD dwFlags = 0L;
BOOL bResult = FALSE;
LPVOID lpPhysical = NULL;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
DWORD dwPteFlags = NULL;
if((NULL == lpThis) || (0 == dwSize)) //Parameter check.
return NULL;
if(VIRTUAL_AREA_ALLOCATE_RESERVE != dwAllocFlags) //Invalidate flags.
return NULL;
lpIndexMgr = lpMemMgr->lpPageIndexMgr;
if(NULL == lpIndexMgr) //Validate.
return NULL;
lpStartAddr = (LPVOID)((DWORD)lpStartAddr & ~(PAGE_FRAME_SIZE - 1)); //Round up to page.
lpEndAddr = (LPVOID)((DWORD)lpDesiredAddr + dwSize );
lpEndAddr = (LPVOID)(((DWORD)lpEndAddr & (PAGE_FRAME_SIZE - 1)) ?
(((DWORD)lpEndAddr & ~(PAGE_FRAME_SIZE - 1)) + PAGE_FRAME_SIZE - 1)
: ((DWORD)lpEndAddr - 1)); //Round down to page.
dwSize = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1; //Get the actually size.
lpVad = (__VIRTUAL_AREA_DESCRIPTOR*)KMemAlloc(sizeof(__VIRTUAL_AREA_DESCRIPTOR),
KMEM_SIZE_TYPE_ANY); //In order to avoid calling KMemAlloc routine in the
//critical section,we first call it here.
if(NULL == lpVad) //Can not allocate memory.
goto __TERMINAL;
lpVad->lpManager = lpMemMgr;
lpVad->lpStartAddr = NULL;
lpVad->lpEndAddr = NULL;
lpVad->lpNext = NULL;
lpVad->dwAccessFlags = dwAccessFlags;
lpVad->dwAllocFlags = dwAllocFlags;
__INIT_ATOMIC(lpVad->Reference);
lpVad->lpLeft = NULL;
lpVad->lpRight = NULL;
if(lpVaName)
{
if(StrLen((LPSTR)lpVaName) > MAX_VA_NAME_LEN)
lpVaName[MAX_VA_NAME_LEN - 1] = 0;
StrCpy((LPSTR)lpVad->strName[0],(LPSTR)lpVaName); //Set the virtual area's name.
}
else
lpVad->strName[0] = 0;
lpVad->dwCacheFlags = VIRTUAL_AREA_CACHE_NORMAL;
//
//The following code searchs virtual area list or AVL tree,to check if the lpDesiredAddr
//is occupied,if so,then find a new one.
//
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Should search in the list.
lpStartAddr = SearchVirtualArea_l((__COMMON_OBJECT*)lpMemMgr,lpStartAddr,dwSize);
else //Should search in the AVL tree.
lpStartAddr = SearchVirtualArea_t((__COMMON_OBJECT*)lpMemMgr,lpStartAddr,dwSize);
if(NULL == lpStartAddr) //Can not find proper virtual area.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
lpVad->lpStartAddr = lpStartAddr;
lpVad->lpEndAddr = (LPVOID)((DWORD)lpStartAddr + dwSize -1);
lpDesiredAddr = lpStartAddr;
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM)
InsertIntoList((__COMMON_OBJECT*)lpMemMgr,lpVad); //Insert into list or tree.
else
InsertIntoTree((__COMMON_OBJECT*)lpMemMgr,lpVad);
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
bResult = TRUE; //Indicate that the whole operation is successfully.
//In this operation(only reserve),we do not commit page table entries,
//so,if access the memory space(read or write) of this range,will
//cause a page fault exception.
//The caller must call VirtualAlloc routine again to commit this
//block of area before access it.
__TERMINAL:
if(!bResult) //Process failed.
{
if(lpVad)
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);
if(lpPhysical)
PageFrameManager.FrameFree((__COMMON_OBJECT*)&PageFrameManager,
lpPhysical,
dwSize);
return NULL;
}
return lpDesiredAddr;
}
//
//DoReserveAndCommit routine.When VirtualAlloc is called with VIRTUAL_AREA_ALLOCATE_ALL or
//VIRTUAL_AREA_ALLOCATE_DEFAULT,then is routine is called by VirtualAlloc.
//
static LPVOID DoReserveAndCommit(__COMMON_OBJECT* lpThis,
LPVOID lpDesiredAddr,
DWORD dwSize,
DWORD dwAllocFlags,
DWORD dwAccessFlags,
UCHAR* lpVaName,
LPVOID lpReserved)
{
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
LPVOID lpStartAddr = lpDesiredAddr;
LPVOID lpEndAddr = NULL;
DWORD dwFlags = 0L;
BOOL bResult = FALSE;
LPVOID lpPhysical = NULL;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
DWORD dwPteFlags = NULL;
if((NULL == lpThis) || (0 == dwSize)) //Parameter check.
return NULL;
if(VIRTUAL_AREA_ALLOCATE_ALL != dwAllocFlags) //Invalidate flags.
return NULL;
lpIndexMgr = lpMemMgr->lpPageIndexMgr;
if(NULL == lpIndexMgr) //Validate.
return NULL;
lpStartAddr = (LPVOID)((DWORD)lpStartAddr & ~(PAGE_FRAME_SIZE - 1)); //Round up to page.
lpEndAddr = (LPVOID)((DWORD)lpDesiredAddr + dwSize );
lpEndAddr = (LPVOID)(((DWORD)lpEndAddr & (PAGE_FRAME_SIZE - 1)) ?
(((DWORD)lpEndAddr & ~(PAGE_FRAME_SIZE - 1)) + PAGE_FRAME_SIZE - 1)
: ((DWORD)lpEndAddr - 1)); //Round down to page.
dwSize = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1; //Get the actually size.
lpVad = (__VIRTUAL_AREA_DESCRIPTOR*)KMemAlloc(sizeof(__VIRTUAL_AREA_DESCRIPTOR),
KMEM_SIZE_TYPE_ANY); //In order to avoid calling KMemAlloc routine in the
//critical section,we first call it here.
if(NULL == lpVad) //Can not allocate memory.
{
PrintLine("In DoReserveAndCommit: Can not allocate memory for VAD.");
goto __TERMINAL;
}
lpVad->lpManager = lpMemMgr;
lpVad->lpStartAddr = NULL;
lpVad->lpEndAddr = NULL;
lpVad->lpNext = NULL;
lpVad->dwAccessFlags = dwAccessFlags;
lpVad->dwAllocFlags = VIRTUAL_AREA_ALLOCATE_COMMIT; //dwAllocFlags;
__INIT_ATOMIC(lpVad->Reference);
lpVad->lpLeft = NULL;
lpVad->lpRight = NULL;
if(lpVaName)
{
if(StrLen((LPSTR)lpVaName) > MAX_VA_NAME_LEN)
lpVaName[MAX_VA_NAME_LEN - 1] = 0;
StrCpy((LPSTR)lpVad->strName[0],(LPSTR)lpVaName); //Set the virtual area's name.
}
else
lpVad->strName[0] = 0;
lpVad->dwCacheFlags = VIRTUAL_AREA_CACHE_NORMAL;
lpPhysical = PageFrameManager.FrameAlloc((__COMMON_OBJECT*)&PageFrameManager,
dwSize,
0L); //Allocate physical memory pages.In order to reduce the time
//in critical section,we allocate physical memory here.
if(NULL == lpPhysical) //Can not allocate physical memory.
{
PrintLine("In DoReserveAndCommit: Can not allocate physical memory.");
goto __TERMINAL;
}
//
//The following code searchs virtual area list or AVL tree,to check if the lpDesiredAddr
//is occupied,if so,then find a new one.
//
lpEndAddr = lpStartAddr; //Save the lpStartAddr,because the lpStartAddr may changed
//after the SearchVirtualArea_X is called.
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Should search in the list.
lpStartAddr = SearchVirtualArea_l((__COMMON_OBJECT*)lpMemMgr,lpStartAddr,dwSize);
else //Should search in the AVL tree.
lpStartAddr = SearchVirtualArea_t((__COMMON_OBJECT*)lpMemMgr,lpStartAddr,dwSize);
if(NULL == lpStartAddr) //Can not find proper virtual area.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
PrintLine("In DoReserveAndCommit: SearchVirtualArea failed.");
goto __TERMINAL;
}
lpVad->lpStartAddr = lpStartAddr;
lpVad->lpEndAddr = (LPVOID)((DWORD)lpStartAddr + dwSize -1);
if(!(lpStartAddr == lpEndAddr)) //Have not get the desired area.
lpDesiredAddr = lpStartAddr;
if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM)
InsertIntoList((__COMMON_OBJECT*)lpMemMgr,lpVad); //Insert into list or tree.
else
InsertIntoTree((__COMMON_OBJECT*)lpMemMgr,lpVad);
//
//The following code reserves page table entries for the committed memory.
//
dwPteFlags = PTE_FLAGS_FOR_NORMAL; //Normal flags.
while(dwSize)
{
if(!lpIndexMgr->ReservePage((__COMMON_OBJECT*)lpIndexMgr,
lpStartAddr,lpPhysical,dwPteFlags))
{
PrintLine("Fatal Error : Internal data structure is not consist.");
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
goto __TERMINAL;
}
dwSize -= PAGE_FRAME_SIZE;
lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
lpPhysical = (LPVOID)((DWORD)lpPhysical + PAGE_FRAME_SIZE);
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
bResult = TRUE; //Indicate that the whole operation is successfully.
__TERMINAL:
if(!bResult) //Process failed.
{
if(lpVad)
KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);
if(lpPhysical)
PageFrameManager.FrameFree((__COMMON_OBJECT*)&PageFrameManager,
lpPhysical,
dwSize);
return NULL;
}
return lpDesiredAddr;
}
//
//DoIoMap routine.When VirtualAlloc is called with VIRTUAL_AREA_ALLOCATE_IO,
//then is routine is called by VirtualAlloc.
//
static LPVOID DoIoMap(__COMMON_OBJECT* lpThis,
LPVOID lpDesiredAddr,
DWORD dwSize,
DWORD dwAllocFlags,
DWORD dwAccessFlags,
UCHAR* lpVaName,
LPVOID lpReserved)
{
__VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL;
__VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
LPVOID lpStartAddr = lpDesiredAddr;
LPVOID lpEndAddr = NULL;
DWORD dwFlags = 0L;
BOOL bResult = FALSE;
LPVOID lpPhysical = NULL;
__PAGE_INDEX_MANAGER* lpIndexMgr = NULL;
DWORD dwPteFlags = NULL;
if((NULL == lpThis) || (0 == dwSize)) //Parameter check.
return NULL;
if(VIRTUAL_AREA_ALLOCATE_IO != dwAllocFlags) //Invalidate flags.
return NULL;
lpIndexMgr = lpMemMgr->lpPageIndexMgr;
if(NULL == lpIndexMgr) //Validate.
return NULL;
lpStartAddr = (LPVOID)((DWORD)lpStartAddr & ~(PAGE_FRAME_SIZE - 1)); //Round up to page.
lpEndAddr = (LPVOID)((DWORD)lpDesiredAddr + dwSize );
lpEndAddr = (LPVOID)(((DWORD)lpEndAddr & (PAGE_FRAME_SIZE - 1)) ?
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -