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

📄 klheap.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************
Copyright(c) 版权所有,1998-2003微逻辑。保留所有权利。
******************************************************/

/*****************************************************
文件说明:程序堆管理
版本号:2.0.0
开发时期:2000
作者:李林
修改记录:
    2003-05-14: 将API调用改为 Kernerl调用, By ln
    2003-05-13: 增加 互斥段代码, By ln
    2003-05-12: HeapAlloc 增加 HEAP_ZERO_MEMORY , By ln
    2003-05-09: LN, 将堆的必须限制改为可选择限制, By ln
******************************************************/


#include <eframe.h>
#include <epheap.h>
#include <coresrv.h>

#include <epalloc.h>

#define DISABLE()
#define ENABLE()


#define BUSY_FLAG 1		/* use this define for the BUSY_FLAG bit in lpNext */
#define ALLOC_FLAG 2      

#define IS_BUSY(x)	((long)(x)->busy.lpNext&BUSY_FLAG)
#define IS_ALLOC(x)	((long)(x)->busy.lpNext&ALLOC_FLAG)

// 对齐8bytes
#define ALIGNMASK (7)//sizeof(char*)<=2? 1: (sizeof(char*)<=4? 3: 7))

// 
static void _InsertToFree( LPHEAP, LPBLOCK );
static void _RemoveFromFree( LPHEAP, LPBLOCK );
static BOOL Heap_AddToSection( LPHEAP lpHeap, LPSECTION lp, ULONG ulLen );

// 互斥操作,进入
#define EnterCriticalLock( lpHeap, bSerial ) \
	do{ \
 	    if( (bSerial) && ( (lpHeap)->dwOption & HEAP_NO_SERIALIZE ) == 0 ) \
		{ \
			KL_EnterCriticalSection( &(lpHeap)->csHeap );\
		} \
	}while(0);

// 互斥操作,离开
#define LeaveCriticalLock( lpHeap, bSerial ) \
	do{ \
 	    if( (bSerial) && ( (lpHeap)->dwOption & HEAP_NO_SERIALIZE ) == 0 ) \
		{ \
			KL_LeaveCriticalSection( &(lpHeap)->csHeap );\
		} \
	}while(0);


#define PAGE_SIZE (4*1024)
#define ALLOC_SIZE (64*1024)

/**************************************************
声明:BOOL Heap_Init( LPHEAP lpHeap, DWORD dwOption, ULONG ulInitialSize, ULONG ulLimit )
参数:
	lpHeap - HEAP 结构指针,用于保存堆信息
	dwOption - 附加的功能,可以为以下值:
		HEAP_NO_SERIALIZE - 以后的HeapAlloc, HeapFree等功能不需要串行化(互斥操作)
		HEAP_VIRTUAL_ALLOC - 从系统内存空间分配内存的方法,该值说明用VirtualAlloc功能从系统分配;
		                     否则,用DoAllocPageMem功能从系统分配
	ulInitialSize - 初始化堆尺寸
	ulLimit - 堆尺寸最大限制
返回值:
	假如成功,TRUE;否则,返回FALSE
功能描述:
	初始化一个堆,以便与于以后的堆操作
引用: 
	
************************************************/
BOOL Heap_Init( LPHEAP lpHeap, DWORD dwOption, ULONG ulInitialSize, ULONG ulLimit )
{
	if( ulInitialSize > ulLimit )
		return FALSE;
	memset( lpHeap, 0, sizeof( HEAP ) );
	if( (dwOption & HEAP_NO_SERIALIZE) == 0 )
	{
		KL_InitializeCriticalSection( &lpHeap->csHeap );
	}
	lpHeap->dwOption = dwOption;
	ulInitialSize = (ulInitialSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
	ulLimit = (ulLimit + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
	lpHeap->dwHeapSizeLimit = ulLimit;

#ifdef VIRTUAL_MEM
	if( dwOption & HEAP_VIRTUAL_ALLOC )
	{
		BOOL bRetv = TRUE;
		
		if( ulLimit || ulInitialSize )
		{   // 预留内存
			DWORD dwReverse = MAX( ulLimit, ulInitialSize );
			LPVOID lpv;
			
			lpv = KL_VirtualAlloc( 0, dwReverse, MEM_RESERVE, PAGE_READWRITE );
			
			if( lpv )
			{
				lpHeap->lpbCur = lpHeap->lpbCurReserveBase = lpv;
				lpHeap->dwCurReserveSize = dwReverse;
				lpHeap->dwCurUseSize = 0;
				lpHeap->dwTotalReserveSize = dwReverse;
			}
			else
				bRetv = FALSE;
		}
		
		if( ulInitialSize && lpHeap->lpbCurReserveBase )
		{   // 提交物理内存
			DWORD dwCommitSize;
			LPVOID p;
			
			ulInitialSize = MAX( ulInitialSize, sizeof( SECTION ) );
			
			dwCommitSize = (ulInitialSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
			p = KL_VirtualAlloc( lpHeap->lpbCur, dwCommitSize, MEM_COMMIT, PAGE_READWRITE );
			if( p == NULL )
			{
				bRetv = FALSE;
				KL_VirtualFree( lpHeap->lpbCurReserveBase, 0, MEM_RELEASE );
				lpHeap->lpbCurReserveBase = lpHeap->lpbCur = NULL;
				lpHeap->dwCurReserveSize = 0;
				lpHeap->dwTotalReserveSize = 0;
			}
			else
			{
				lpHeap->dwTotalCommitSize = dwCommitSize;
				lpHeap->lpbCur += sizeof( SECTION );
				lpHeap->dwCurUseSize += sizeof( SECTION );
				
				Heap_AddToSection( lpHeap, p, lpHeap->dwTotalReserveSize );
			}
		}
		//RETAILMSG( 1, ( "Heap_Init:lpHeap=%x.\r\n", lpHeap ) );
		return bRetv;
	}
//#else
	else
#endif   //VIRTUAL_MEM
		return TRUE;
//#endif

}

/**************************************************
声明:HANDLE DoHeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
参数:
	flOptions - 附加的功能,可以为以下值:
		HEAP_NO_SERIALIZE - 以后的HeapAlloc, HeapFree等功能不需要串行化(互斥操作)
		HEAP_VIRTUAL_ALLOC - 从系统内存空间分配内存的方法,该值说明用VirtualAlloc功能从系统分配;
		                     否则,用DoAllocPageMem功能从系统分配
	dwInitialSize - 初始化堆尺寸
	dwMaximumSize - 堆尺寸最大限制
返回值:
	假如成功,有效的句柄;否则,返回NULL
功能描述:
	初始化一个堆,以便与于以后的堆操作
引用: 
	process.c用该函数去初始化进程堆
************************************************/

HANDLE DoHeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
{
	LPHEAP lpHeap = KHeap_Alloc( sizeof( HEAP ) );
	if( lpHeap )
	{
		if( Heap_Init( lpHeap, flOptions, dwInitialSize, dwMaximumSize ) == FALSE )
		{
			KHeap_Free( lpHeap, sizeof( HEAP ) );
			lpHeap = NULL;
		}
	}
	return lpHeap;
}

/**************************************************
声明:BOOL WINAPI DoHeapDestroy( HANDLE hHeap )
参数:
	hHeap - 堆句柄(为之前调用KL_HeapCreate所返回的句柄)
返回值:
	假如成功,返回TRUE; 否则,返回FALSE
功能描述:
	破坏堆的部分数据
引用: 
	内核调用

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

BOOL DoHeapDestroy( LPHEAP lpHeap )
{
//	LPHEAP lpHeap = (LPHEAP)hHeap;

//   1.因为 用户堆的链表指针也是在用户堆里,其指针也有可能被破坏,
//		如果是这样,在调用KL_HeapDestroy有可能出现异常,所以这里不用去释放 heap
//   2.Seg 管理器会释放所有的用户空间(包括用户堆)
//   3.内核在释放进程时会调用该函数

	// 进入互斥段		
	if( lpHeap )
	{
		if( (lpHeap->dwOption & HEAP_NO_SERIALIZE) == 0 )
			KL_DeleteCriticalSection( &lpHeap->csHeap );
	       // 释放分配的堆信息结构		
		KHeap_Free( lpHeap, sizeof( HEAP ) );
		return TRUE;
	}
	return FALSE;
}


/**************************************************
声明:HANDLE WINAPI KL_HeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
参数:
	flOptions - 附加的功能,可以为以下值:
		HEAP_NO_SERIALIZE - 以后的HeapAlloc, HeapFree等功能不需要串行化(互斥操作)
	dwInitialSize - 初始化堆尺寸
	dwMaximumSize - 堆尺寸最大限制
返回值:
	假如成功,有效的句柄;否则,返回NULL
功能描述:
	初始化一个堆,以便与于以后的堆操作
引用: 
	系统API调用
************************************************/

HANDLE WINAPI KL_HeapCreate( DWORD flOptions, ULONG dwInitialSize, ULONG dwMaximumSize )
{
//	
#ifdef VIRTUAL_MEM	
	return DoHeapCreate( flOptions|HEAP_VIRTUAL_ALLOC, dwInitialSize, dwMaximumSize );
#else
	flOptions &= ~HEAP_VIRTUAL_ALLOC;
	return DoHeapCreate( flOptions, dwInitialSize, dwMaximumSize );
#endif	
}

/**************************************************
声明:static BOOL Heap_AddToSection( LPHEAP lpHeap, LPSECTION lp, ULONG ulLen )
参数:
	lpHeap - HEAP 结构指针,指向堆信息
	lpsc - SECTION 结构指针,向堆增加的新内存段
	ulLen - 新内存段尺寸
返回值:
	假如成功,返回TRUE;否则,返回FALSE
功能描述:
	将一个新内存段加入堆链表
引用: 
	
************************************************/
static BOOL Heap_AddToSection( LPHEAP lpHeap, LPSECTION lpsc, ULONG ulLen )
{
	// 初始化SECTION 结构
	lpsc->ulLen = ulLen;
	lpsc->lpNext = lpHeap->lpSection;
	// 加入堆链表
	lpHeap->lpSection = lpsc;
	return TRUE;
}

/**************************************************
声明:void * GetSystemMem( LPHEAP lpHeap, DWORD dwSize, DWORD * lpdwRealSize )
参数:
	lpHeap - HEAP 结构指针,指向堆信息
	dwSize - 需要的内存大小
	lpdwRealSize - 返回的真实内存大小( > dwSize )
返回值:
	假如成功,返回非NULL的内存指针;否则,返回NULL
功能描述:
	既然堆里没有足够的内存块,则用该函数从系统内存分配内存块,并将其加入堆链表
 
引用: 
    Heap_Alloc, Heap_Realloc	
************************************************/
#define DEBUG_GETSYSTEMMEM 0
static void * GetSystemMem( LPHEAP lpHeap, DWORD dwSize, DWORD * lpdwRealSize )
{
	//RETAILMSG( 1, ( "GetSystemMem:lpHeap=%x,dwSize=%d,ProcessId=%d.\r\n", lpHeap, dwSize, KL_GetCurrentProcessId() ) );

#ifdef VIRTUAL_MEM
	// 如果系统有MMU管理,则用该段代码
    if( lpHeap->dwOption & HEAP_VIRTUAL_ALLOC )
	{   // 用VirtualAlloc去分配内存
		void * p = NULL;
		DWORD dwCommitSize;
		UINT uiNewSectionSize = 0;
		
		*lpdwRealSize = 0;
		
		dwCommitSize = (dwSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));  // align to page
		
		if( lpHeap->dwCurUseSize + dwCommitSize > lpHeap->dwCurReserveSize )
		{   // 当前堆里未提交(保留)的内存域 小于 需要的内存尺寸,必须分配新的内存域/段
			//dwSize += sizeof(SECTION);
			if( lpHeap->dwHeapSizeLimit )
			{   // 如果有整个堆的大小限制,则错误。
				RETAILMSG( 1, ( "error: GetSystemMem:Heap reach size limite(%d).\r\n", lpHeap->dwHeapSizeLimit ) );
				return NULL;
			}
			else
			{	// 没有尺寸限制,分配一个新的
				DWORD dwReserveSize = dwSize + sizeof(SECTION);
				// 对齐到ALLOC_SIZE大小
				dwReserveSize = (dwReserveSize + ALLOC_SIZE - 1) & (~(ALLOC_SIZE - 1));// align to 64k
				// 先保留内存域
				lpHeap->lpbCurReserveBase = KL_VirtualAlloc( 0, dwReserveSize, MEM_RESERVE, PAGE_READWRITE );
				if( lpHeap->lpbCurReserveBase == NULL )
				{   //保留内存域失败
					WARNMSG( DEBUG_GETSYSTEMMEM, ( "error: GetSystemMem: can't to reserve space size(%d).\r\n", dwReserveSize ) );
					dwReserveSize = 0;
				}
				else
					uiNewSectionSize = sizeof(SECTION);
				// 初始化新的内存域
				lpHeap->lpbCur = lpHeap->lpbCurReserveBase;
				lpHeap->dwCurReserveSize = dwReserveSize;
				lpHeap->dwCurUseSize = 0;
				lpHeap->dwTotalReserveSize += dwReserveSize;
			}
		}
		
		if( lpHeap->dwHeapSizeLimit && 
			lpHeap->dwCurUseSize == NULL )
			uiNewSectionSize = sizeof(SECTION);  // 为section保留空间
		// 真实的需要提交/分配的内存
		dwCommitSize = (dwSize + uiNewSectionSize + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
		// 合法检查
		if( lpHeap->dwCurUseSize + dwCommitSize <= lpHeap->dwCurReserveSize )
		{   // 提交/分配新的内存块
			p = KL_VirtualAlloc( lpHeap->lpbCur, dwCommitSize, MEM_COMMIT, PAGE_READWRITE );
			if( p )
			{
#ifdef __DEBUG
				memset( p, 0xCCCCCCCC, dwCommitSize );
#endif
				
				if( uiNewSectionSize )
				{  // 需要将其加入堆链表
					Heap_AddToSection( lpHeap, (LPSECTION)p, lpHeap->dwCurReserveSize );
					p = (LPBLOCK)( (DWORD)p + uiNewSectionSize );
				}

⌨️ 快捷键说明

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