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

📄 vmm.cpp

📁 小型的操作系统开发的原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
					   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)) ? 

⌨️ 快捷键说明

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