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

📄 pagemgr.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 2 页
字号:
//返回值:
//	假如成功,返回有效内存页地址;否则返回NULL
//功能描述:
//	分配一内存页
//引用:
// ********************************************************************

void * Page_Alloc( BOOL bUpdateFreePages )
{
    void * lp = NULL;
	UINT uiSave;

    LockIRQSave( &uiSave );

	// 空闲页表是否为空?
	if( (bUpdateFreePages && uiFreePages) || 
		(bUpdateFreePages == FALSE && lpFreePageList) )
	//if( lpFreePageList )
	{   // 不为空
	    LPSEGMENTINFO lpSegInfo;

		//lp = lpFreePageList;
		lp = Page_RemoveFromFreeList( bUpdateFreePages );
		//	得到该页所在的内存段
		lpSegInfo = Page_GetSeg( lp );
//		ASSERT( lpSegInfo );
		//	将该页在内存段相应的位设为占用状态
		lpSegInfo->lpbFreeMemMap[GET_INDEX( lpSegInfo, lp )] = FLAG_USED;
	}
	UnlockIRQRestore( &uiSave );
	//	如果有CACHE功能,将其转化为CACHE指针
	return lp ? (void*)UNCACHE_TO_CACHE( lp ) : NULL;
}

// ********************************************************************
//声明:BOOL Page_Free( LPVOID lpvMemAdr  )
//参数:
// IN lpvMemAdr - 需要释放的页
//
//返回值:
// 假如成功,返回TRUE;否则返回FALSE
//功能描述:
//	与Page_Alloc相对应,释放一个页内存。
//引用:
// ********************************************************************
#define DEBUG_Page_Free 0
BOOL Page_Free( LPVOID lpvMemAdr  )
{
	LPSEGMENTINFO lpSegInfo;

//	ASSERT( lpvMemAdr );
	//	如果有CACHE功能,将其转化为UNCACHE指针
	lpvMemAdr = (LPVOID)CACHE_TO_UNCACHE( lpvMemAdr );
	//	得到该内存所在的页
	lpSegInfo = Page_GetSeg( lpvMemAdr );

	if( lpSegInfo )
	{
	    UINT uiSave;
		int index;
		// 得到该页在内存段的索引号
        index = GET_INDEX( lpSegInfo, lpvMemAdr );
		LockIRQSave( &uiSave );

		//ASSERT( lpSegInfo->lpbFreeMemMap[index] );
		// 该内存页的引用计数是否为0
		if( lpSegInfo->lpbFreeMemMap[index] )
		{
			if( --lpSegInfo->lpbFreeMemMap[index] == 0 )
				Page_AddToFreeList( lpvMemAdr );  //是,将其加入到空闲链表
		}
		else
		{
			ERRORMSG( DEBUG_Page_Free, ( "error in Page_Free: lpvMemAdr=0x%x.\r\n", lpvMemAdr ) );
		}

		UnlockIRQRestore( &uiSave );
	}
	else
	{	// 不一定是错,有可能是代码页,也通过该函数
		;//RETAILMSG( 1, ( "failure error at Page_Free(0x%x): lpSegInfo = NULL!.\r\n", lpvMemAdr ) );
	}

	return TRUE;
}

// ********************************************************************
//声明:BOOL Page_Get( LPVOID * lppAdr, DWORD dwPages )
//参数:
//	IN lppAdr - 指向用于接收页地址的指针数组,该数组的大小应该等于dwPages -> lppAdr[dwPages]
//	IN dwPages - 需要的页数
//返回值:
//	假如成功,返回TRUE;否则返回FALSE
//功能描述:
//	得到一些页内存
//引用:
// ********************************************************************

BOOL Page_Get( LPVOID * lppAdr, DWORD dwPages )
{
	// 先锁住需要的页
	if( Page_Lock( dwPages ) )
	{	//锁住成功
		while( dwPages-- )
		{	//得到每个页
			*lppAdr++ = Page_Alloc( FALSE ); 
		}
		return TRUE;
	}    
	return FALSE;
}

// ********************************************************************
//声明:BOOL Page_Release( LPVOID * lppAdr, DWORD dwPages )
//参数:
//	IN lppAdr - 指向用于保存有页地址的指针数组,该数组的大小应该等于dwPages -> lppAdr[dwPages]
//	IN dwPages - 需要释放的页数
//返回值:
//	假如成功,返回TRUE;否则返回FALSE
//功能描述:
//	与Page_Get对应,释放一些页内存
//引用:
// ********************************************************************
BOOL Page_Release( LPVOID * lppAdr, DWORD dwPages )
{
	while( dwPages-- )
	{
		//ASSERT( *lppAdr );
		Page_Free( *lppAdr );
		lppAdr++;
	}
	return TRUE;
}

// ********************************************************************
//声明:LPVOID Page_GetContiguous( DWORD dwPages, DWORD dwAlignmentMask )
//参数:
//	IN dwPages - 需要分配的页数
//	IN dwAlignmentMask - 页开始地址对齐mask
//返回值:
//	假如成功,返回非NULL的内存地址;否则返回NULL
//功能描述:
//	得到连续的页内存
//引用:
// ********************************************************************
LPVOID Page_GetContiguous( DWORD dwPages, DWORD dwAlignmentMask )
{
	LPVOID lpvRet = NULL;
	// 锁住需要的页
	if( Page_Lock( dwPages ) )
	{	// 
		LPSEGMENTINFO lpSegInfo = memInfo.lpSectionInfo;
		LPSEGMENTINFO lpSegInfoEnd = lpSegInfo + memInfo.dwSections;
        // 遍历所有的内存段,得到一块连续的内存
		for( ; lpSegInfo < lpSegInfoEnd; lpSegInfo++ )
		{
			LPBYTE lpbMemMapS = lpSegInfo->lpbFreeMemMap;
			LPBYTE lpbMemMapE = lpbMemMapS + lpSegInfo->dwTotalPages - dwPages;
			LPBYTE lpbPageStart = lpSegInfo->lpbFreePageStart;
			DWORD dwIndexBegin = 0;
			// 查找当前内存段
			for( ; lpbMemMapS <= lpbMemMapE; lpbMemMapS++, dwIndexBegin++, lpbPageStart += PAGE_SIZE )
			{	// 该页是否是空闲的或是否对齐地址
				if( *lpbMemMapS ||
					( (DWORD)lpbPageStart & dwAlignmentMask )
					)
				{	// 占用或没有对齐
					continue;
				}
				else
				{	// 符合条件,从该页向下遍历其它需要的内存页
					LPBYTE lpbFirst = lpbMemMapS;
					LPBYTE lpbEnd = lpbFirst + dwPages;
					DWORD dwCurIndex = dwIndexBegin;
					for( ; lpbFirst < lpbEnd; lpbFirst++, dwCurIndex++ )
					{	// 是否是空闲 或 分配成功?
						if( *lpbFirst ||
							Page_GetSpecific( lpSegInfo, dwCurIndex ) == FALSE )
						{   // 不成功,释放之前已分配的内存页 							
							DWORD n = dwIndexBegin;
							for( ; n < dwCurIndex; n++ )
							{
								Page_ReleaseSpecific( lpSegInfo, n );
							}
							// 重新设定遍历开始位置
							lpbMemMapS = lpbFirst + 1;
							dwIndexBegin = dwCurIndex + 1;
							lpbPageStart = lpSegInfo->lpbFreePageStart + dwIndexBegin * PAGE_SIZE;
							break;
						}
					}
					if( lpbFirst == lpbEnd )
					{   // 已经得到所有需要的内存页 //i get all page needed
						lpvRet = lpbPageStart;
						goto _RET;
					}
				}
			}
			// 不成功,解锁
			Page_Unlock( dwPages );
		}
	}
_RET:
	//	如果有CACHE功能,将其转化为CACHE指针

	return lpvRet ? (LPVOID)UNCACHE_TO_CACHE(lpvRet) : NULL;
}

// ********************************************************************
//声明:BOOL Page_ReleaseContiguous( LPVOID lpAdr, DWORD dwPages )
//参数:
//	IN lpAdr - 需要释放的页开始地址
//	IN dwPages - 需要释放的页数
//返回值:
//	假如成功,返回TRUE;否则返回FALSE
//功能描述:
//	与Page_GetContiguous对应,释放连续的页内存
//引用:
// ********************************************************************
BOOL Page_ReleaseContiguous( LPVOID lpAdr, DWORD dwPages )
{
	for( ; dwPages; dwPages-- )
	{
		//ASSERT( lpAdr );
		Page_Free( lpAdr );
		//	下一页地址
		lpAdr = (LPVOID)( (DWORD)lpAdr + PAGE_SIZE ); 
	}
	return TRUE;
}

// ********************************************************************
//声明:BOOL Page_InitSysPages( void )
//参数:
//	无
//返回值:
//	假如成功,返回TRUE;否则返回FALSE
//功能描述:
//	当内核启动时,初始化系统内存页,在调用该函数之前lpbSysMainMem,ulSysMainMemLength必须先初始化
//引用:
// ********************************************************************
BOOL Page_InitSysPages( void )
{
	extern void OEM_WriteDebugString( LPCTSTR lpszStr );

    int k, iSegNum;	
	MEM_SEGMENT seg[MAX_SEGMENTS];
	char buf[16];

	// 输出调试信息 - begin
	OEM_WriteDebugString( "Page_InitSysPages:lpbSysMainMem=0x" );
	itoa( (DWORD)lpbSysMainMem, buf, 16 );
	OEM_WriteDebugString( buf );
	OEM_WriteDebugString( ",ulSysMainMemLength=" );
	itoa( (DWORD)ulSysMainMemLength, buf, 10 );
	OEM_WriteDebugString( buf );
	OEM_WriteDebugString( "\r\n" );
	// - end
	
	//	如果带MMU,先刷新CACHE
#ifdef VIRTUAL_MEM
	FlushCacheAndClearTLB();
#endif
	// 初始化句柄基本地址
    dwHandleBase = (DWORD)lpbSysMainMem & 0xE0000000;
	lpbSysMainMemEnd = lpbSysMainMem + ulSysMainMemLength;
	//初始化memInfo 信息
	memInfo.lpbMainMemStart = (LPBYTE)CACHE_TO_UNCACHE( lpbSysMainMem );
	memInfo.lpbMainMemEnd = memInfo.lpbMainMemStart + ulSysMainMemLength;
	memInfo.lpbMainMemFreeStart = memInfo.lpbMainMemStart;
	memInfo.dwMainMemFreeSize = ulSysMainMemLength;
	//建立第一个内存段结构(用主内存)
	memInfo.lpSectionInfo = (LPSEGMENTINFO)ALIGN_DWORD( (DWORD)memInfo.lpbMainMemFreeStart );
	//初始化第一个内存段
	seg[0].lpbStart = (LPBYTE)( memInfo.lpSectionInfo + MAX_SEGMENTS );
	seg[0].dwSize = memInfo.dwMainMemFreeSize - ( seg[0].lpbStart - memInfo.lpbMainMemFreeStart );
	//得到系统其它附加内存段数
	iSegNum = OEM_EnumExtensionDRAM( seg+1, MAX_SEGMENTS-1 );
	iSegNum += 1;  // 总的内存段数
	//初始化每一个内存段
	for( k = 0; k < iSegNum; k++ )
	{
		LPBYTE lpbPageStart, lpbPageEnd;
		DWORD dwPages;

		memInfo.lpSectionInfo[k].lpbMemStart = seg[0].lpbStart;
		memInfo.lpSectionInfo[k].dwMemSize = seg[0].dwSize;
		memInfo.lpSectionInfo[k].lpbFreeMemMap = memInfo.lpSectionInfo[k].lpbMemStart;//
        // 该段页开始位置
		lpbPageStart = (LPBYTE)ALIGN_PAGE_UP( (DWORD)memInfo.lpSectionInfo[k].lpbMemStart );
		// 该段页结束位置
		lpbPageEnd = (LPBYTE)ALIGN_PAGE_DOWN( (DWORD)(memInfo.lpSectionInfo[k].lpbMemStart + memInfo.lpSectionInfo[k].dwMemSize) );//.lpbMemStart + 
		// 该段页数
		dwPages = (lpbPageEnd - lpbPageStart) / PAGE_SIZE;
		// 该段空闲页开始位置
		memInfo.lpSectionInfo[k].lpbFreePageStart =  (LPBYTE)ALIGN_PAGE_UP( (DWORD)(memInfo.lpSectionInfo[k].lpbFreeMemMap + dwPages) );
        // 该段空闲页结束位置
		memInfo.lpSectionInfo[k].lpbFreePageEnd = lpbPageEnd; 
		// 该段总的可用页数
	    memInfo.lpSectionInfo[k].dwTotalPages = (memInfo.lpSectionInfo[k].lpbFreePageEnd - memInfo.lpSectionInfo[k].lpbFreePageStart) / PAGE_SIZE;
		// 将页属性设为空闲状态
		memset( memInfo.lpSectionInfo[k].lpbFreeMemMap, 0, memInfo.lpSectionInfo[k].dwTotalPages );
	}

	memInfo.dwSections = iSegNum;

    // 将所有内存段的空闲页加入空闲链表。now , add free pages to pagelist	
	for( k = 0; k < iSegNum ; k++ )
	{
		LPBYTE lpbPageStart = memInfo.lpSectionInfo[k].lpbFreePageStart;
		LPBYTE lpbPageEnd = memInfo.lpSectionInfo[k].lpbFreePageEnd;
		while( lpbPageStart < lpbPageEnd )
		{
		    Page_AddToFreeList( (LPPAGELIST)lpbPageStart );
		    lpbPageStart += PAGE_SIZE;
		}
	}
	//
	return TRUE;
}

// ********************************************************************
//声明:BOOL _InitSysMem( void )
//参数:
//	无
//返回值:
//	假如成功,返回TRUE;否则返回FALSE
//功能描述:
//	当内核启动时,初始化系统内存页,在调用该函数之前lpbSysMainMem,ulSysMainMemLength必须先初始化
//引用:
// ********************************************************************
BOOL _InitSysMem( void )
{
    return Page_InitSysPages();
}

⌨️ 快捷键说明

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