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

📄 vmm.cpp

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

	//
	//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);

	//
	//The following code reserves page table entries for the committed memory.
	//
	dwPteFlags = PTE_FLAGS_FOR_IOMAP;    //IO map flags,that is,this memory range will not
	                                     //use hardware cache.
	lpPhysical = lpStartAddr;

	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;
}

//
//The implementation of VirtualAlloc routine.
//

static LPVOID VirtualAlloc(__COMMON_OBJECT* lpThis,
						   LPVOID           lpDesiredAddr,
						   DWORD            dwSize,
						   DWORD            dwAllocFlags,
						   DWORD            dwAccessFlags,
						   UCHAR*           lpVaName,
						   LPVOID           lpReserved)
{
	switch(dwAllocFlags)
	{
	case VIRTUAL_AREA_ALLOCATE_IO:    //Call DoIoMap only.
		return DoIoMap(lpThis,
			lpDesiredAddr,
			dwSize,
			dwAllocFlags,
			dwAccessFlags,
			lpVaName,
			lpReserved);
		break;
	case VIRTUAL_AREA_ALLOCATE_RESERVE:
		return DoReserve(lpThis,
			lpDesiredAddr,
			dwSize,
			dwAllocFlags,
			dwAccessFlags,
			lpVaName,
			lpReserved);
		break;
	case VIRTUAL_AREA_ALLOCATE_ALL:
		return DoReserveAndCommit(lpThis,
			lpDesiredAddr,
			dwSize,
			dwAllocFlags,
			dwAccessFlags,
			lpVaName,
			lpReserved);
		break;
	case VIRTUAL_AREA_ALLOCATE_COMMIT:
		DoCommit(lpThis,
			lpDesiredAddr,
			dwSize,
			dwAllocFlags,
			dwAccessFlags,
			lpVaName,
			lpReserved);
		break;
	default:
		return NULL;
	}
	return NULL;
}

//
//A helper routine,used to delete a virtual area descriptor object from list.
//

static VOID DelVaFromList(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
	__VIRTUAL_MEMORY_MANAGER*      lpMemMgr  = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
	__VIRTUAL_AREA_DESCRIPTOR*     lpNext    = NULL;
	__VIRTUAL_AREA_DESCRIPTOR*     lpPrev    = NULL;

	if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
		return;
	lpPrev = lpMemMgr->lpListHdr;
	lpNext = lpMemMgr->lpListHdr;
	if(NULL == lpPrev)   //There is not any VAD in list.
	{
		//__POTENTIAL_BUT();
		return;
	}
	if(lpPrev == lpVad)  //The vad to be deleted is the first one.
	{
		lpMemMgr->lpListHdr = lpPrev->lpNext;
		lpMemMgr->dwVirtualAreaNum --;
		return;
	}
	while(lpPrev)
	{
		if(lpVad == lpPrev)
			break;
		lpNext = lpPrev;
		lpPrev = lpPrev->lpNext;
	}
	if(NULL == lpPrev)    //Can not find the virtual area descriptor object in list.
		return;
	lpNext->lpNext = lpPrev->lpNext; //Delete the VAD object.
	lpMemMgr->dwVirtualAreaNum --;
	return;
}

//
//A helper routine,used to delete a virtual area descriptor object from AVL
//tree.
//
static VOID DelVaFromTree(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
	return; //We will complete this routine in the future.
}

//
//A helper routine,used to release virtual area that committed and with physical memory
//pages allocated.
//
static VOID ReleaseCommit(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
	__VIRTUAL_MEMORY_MANAGER*             lpMemMgr    = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
	LPVOID                                lpStartAddr = NULL;
	LPVOID                                lpEndAddr   = NULL;
	__PAGE_INDEX_MANAGER*                 lpIndexMgr  = NULL;
	DWORD                                 dwSize      = 0L;

	if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
		return;
	lpIndexMgr = lpMemMgr->lpPageIndexMgr;
	if(NULL == lpIndexMgr)    //Fatal error.
		return;
	lpStartAddr = lpVad->lpStartAddr;
	lpEndAddr   = lpVad->lpEndAddr;
	dwSize      = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1;

	lpEndAddr   = lpIndexMgr->GetPhysicalAddress((__COMMON_OBJECT*)lpIndexMgr,
		lpStartAddr);    //Get the physical memory address.
	PageFrameManager.FrameFree((__COMMON_OBJECT*)&PageFrameManager,
		lpEndAddr,
		dwSize);    //Release the physical page.

	while(dwSize)
	{
		lpIndexMgr->ReleasePage((__COMMON_OBJECT*)lpIndexMgr,
			lpStartAddr);    //Release the page table entry that this area occupies.
		lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
		dwSize -= PAGE_FRAME_SIZE;
	}
}

//
//A helper routine,used to release virtual area that committed,but without physical
//memory pages allocated,such as IO map zone.
//This routine only release the page table entry that this virtual area occupies.
//
static VOID ReleaseIoMap(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad)
{
	__VIRTUAL_MEMORY_MANAGER*             lpMemMgr    = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
	LPVOID                                lpStartAddr = NULL;
	LPVOID                                lpEndAddr   = NULL;
	__PAGE_INDEX_MANAGER*                 lpIndexMgr  = NULL;
	DWORD                                 dwSize      = 0L;

	if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters.
		return;
	lpIndexMgr = lpMemMgr->lpPageIndexMgr;
	if(NULL == lpIndexMgr)    //Fatal error.
		return;
	lpStartAddr = lpVad->lpStartAddr;
	lpEndAddr   = lpVad->lpEndAddr;
	dwSize      = (DWORD)lpEndAddr - (DWORD)lpStartAddr + 1;
	while(dwSize)
	{
		lpIndexMgr->ReleasePage((__COMMON_OBJECT*)lpIndexMgr,
			lpStartAddr);    //Release the page table entry that this area occupies.
		lpStartAddr = (LPVOID)((DWORD)lpStartAddr + PAGE_FRAME_SIZE);
		dwSize -= PAGE_FRAME_SIZE;
	}
}

//
//The implementation of VirtualFree routine.
//This routine frees the virtual area allocated by VirtualAlloc,and
//frees any resource,such as physical memory page,page table entries,
//and virtual area descriptor objects,associated with the virtual
//area object.
//

static VOID VirtualFree(__COMMON_OBJECT* lpThis,LPVOID lpVirtualAddr)
{
	__VIRTUAL_MEMORY_MANAGER*            lpMemMgr   = (__VIRTUAL_MEMORY_MANAGER*)lpThis;
	__VIRTUAL_AREA_DESCRIPTOR*           lpVad      = NULL;
	__PAGE_INDEX_MANAGER*                lpIndexMgr = NULL;
	BOOL                                 bResult    = FALSE;
	DWORD                                dwFlags    = 0L;

	if((NULL == lpThis) || (NULL == lpVirtualAddr)) //Invalidate parameters.
		return;
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM)  //Should search in the list.
		lpVad = GetVaByAddr_l(lpThis,lpVirtualAddr);    //Get the virtual area descriptor.
	else
		lpVad = GetVaByAddr_t(lpThis,lpVirtualAddr);
	if(NULL == lpVad)    //This virtual address is not allocated yet.
	{
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		goto __TERMINAL;
	}
	//
	//Now,we have got the virtual area descriptor object,so,
	//first delete it from list or tree.
	//
	if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM)  //Delete from list.
		DelVaFromList(lpThis,lpVad);
	else                                            //Delete from tree.
		DelVaFromTree(lpThis,lpVad);

	//
	//According to different allocating type,to do the different actions.
	//
	switch(lpVad->dwAllocFlags)
	{
	case VIRTUAL_AREA_ALLOCATE_COMMIT:    //The virtual memory area is committed.
		ReleaseCommit(lpThis,lpVad);
		KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);  //Release the memory occupied by
		                                                //virtual area descriptor.
		break;
	case VIRTUAL_AREA_ALLOCATE_RESERVE:   //Only reserved.
		KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);  //Only release the memory.
		break;
	case VIRTUAL_AREA_ALLOCATE_IO:        //Committed,but without physical memory pages.
		ReleaseIoMap(lpThis,lpVad);
		KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0L);
		break;
	default:
		break;
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
	bResult = TRUE;    //Set the completing flags.

__TERMINAL:
	return;
}

//
//The implementation of GetPdAddress routine.
//This routine returns the physical address of page directory.
//

static LPVOID GetPdAddress(__COMMON_OBJECT* lpThis)
{
	__VIRTUAL_MEMORY_MANAGER*       lpManager = NULL;

	if(NULL == lpThis)    //Parameter check.
		return NULL;

	lpManager = (__VIRTUAL_MEMORY_MANAGER*)lpThis;

	return (LPVOID)lpManager->lpPageIndexMgr->lpPdAddress;
}

/***********************************************************************************
************************************************************************************
************************************************************************************
************************************************************************************
***********************************************************************************/

//
//The definition of object Virtual Memory Manager.
//This is one of the global objects,but it is created by CreateObject routine of
//ObjectManager.
//

__VIRTUAL_MEMORY_MANAGER*    lpVirtualMemoryMgr    = NULL;

⌨️ 快捷键说明

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