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

📄 blkheap.c

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

/*****************************************************
文件说明:核心块堆管理
版本号:2.0.0
开发时期:2000
作者:李林
修改记录:

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

#include <ewindows.h>
#include <epcore.h>
#include <epalloc.h>
#include <coresrv.h>

#define BLOCK_EXCLUSIVE		0x1		//将一个页中剩余的部分全部加入该块的空闲快链,该功能要求块的大小应该与页成倍数

typedef struct _BLOCKHEAP
{
	USHORT wBlockSize;
	USHORT wFlag;
	LPBYTE lpFreeBlock;
#ifdef __DEBUG
	int nTotalBlock;
	int iUsed;
	//int   iMaxBlocks;
#endif
}BLOCKHEAP;

//预定义的块堆组
static BLOCKHEAP heap[] = {
    { 8,   0, 0,  },
	{ 16,  0, 0,  },
	{ 32,  0, 0,  },
	{ 64,  0, 0,  },
	{ 128, 0, 0,  },
	{ 256, 0, 0,  },
	{ 512, 0, 0,  },
	{ 1024,BLOCK_EXCLUSIVE, 0,  },
	{ 2048,BLOCK_EXCLUSIVE, 0,  },
	{ 4096,BLOCK_EXCLUSIVE, 0,  }
};
#define MAX_BLOCK_POOLS ( sizeof( heap ) / sizeof( BLOCKHEAP ) )

//将剩下的内存分割进块堆的开始索引
static int iRemainderIndex;
//剩下的内存
static LPBYTE lpFree;
//剩下的内存大小
static int  uiFreeSize;
//本块堆组的最小的快
static int uiMinBlockSize;

//将一个块插入对应的块堆自由列表
#define INSERT_FREE_BLOCK( lpHeap, lpvBlock ) \
	do{\
	    UINT uiSave; \
		LockIRQSave( &uiSave ); \
		*( (LPBYTE*)(lpvBlock) ) = (lpHeap)->lpFreeBlock;\
		(lpHeap)->lpFreeBlock = (LPBYTE)(lpvBlock);\
		UnlockIRQRestore( &uiSave ); \
	}while(0)

//从块堆自由列表移出一个块
#define REMOVE_FREE_BLOCK( lpHeap, lpRet ) \
	do{\
	    UINT uiSave; \
		LockIRQSave( &uiSave ); \
		if( ((lpRet) = (lpHeap)->lpFreeBlock ) != NULL ) \
		    (lpHeap)->lpFreeBlock = *( (LPBYTE*)(lpHeap)->lpFreeBlock );\
		UnlockIRQRestore( &uiSave ); \
	}while(0)

/**************************************************
声明:BLOCKHEAP * GetHeapPtr( UINT uiSize )
参数:
	uiSize - 需要分配的块内存大小  
返回值:
	假如成功,返回有效的块堆结构指针;否则,返回NULL
功能描述:
	根据需要的块大小从系统块堆组得到一个匹配的块堆结构指针,
	已便从该块堆结构分配需要的快
引用: 
	
************************************************/
static BLOCKHEAP * GetHeapPtr( UINT uiSize )
{
	BLOCKHEAP * lpHeap = &heap[0];
    int i;
	for( i = 0; i < MAX_BLOCK_POOLS; i++, lpHeap++ )
	{
		if( lpHeap->wBlockSize >= uiSize )
			return lpHeap;
	}
	RETAILMSG( 1, ( "error heap size:uiSize=%d.\r\n", uiSize ) );
	return NULL;
}

/**************************************************
声明:static void FreeToHeap( BLOCKHEAP * lpHeap, LPBYTE lpRemainder, int iRemainderSize )
参数:
	lpHeap - 块堆结构指针
	lpRemainder - 剩余的内存指针
	iRemainderSize - 剩余的内存大小
返回值:
功能描述:
	将剩余的内存尽可能分割到指定的块堆
引用: 
	
************************************************/
static void FreeToHeap( BLOCKHEAP * lpHeap, LPBYTE lpRemainder, int iRemainderSize )
{
	if( lpHeap )
	{
		int blockSize = (int)lpHeap->wBlockSize;
		while( iRemainderSize >= blockSize )
		{
			{
				INSERT_FREE_BLOCK( lpHeap, lpRemainder );
				
				lpRemainder += blockSize;
				iRemainderSize -= blockSize; 
#ifdef __DEBUG
				lpHeap->nTotalBlock++;
#endif
			}
		}
	}
	//将残余部分加入其它块
	if( iRemainderSize )
	{
		int i = iRemainderIndex;	
		UINT uiSave;
		
		while( iRemainderSize >= uiMinBlockSize )
		{
			ASSERT( i < MAX_BLOCK_POOLS );
			if( heap[i].wBlockSize <= iRemainderSize &&
				(heap[i].wFlag & BLOCK_EXCLUSIVE) == 0 )
			{
				INSERT_FREE_BLOCK( &heap[i], lpRemainder );
				
				lpRemainder += heap[i].wBlockSize;
				iRemainderSize -= heap[i].wBlockSize; 
#ifdef __DEBUG
				heap[i].nTotalBlock++;
#endif 
			}
			i = (i + 1) % MAX_BLOCK_POOLS;
		}
		LockIRQSave( &uiSave );
		
		iRemainderIndex = i;
		UnlockIRQRestore( &uiSave );
	}
}

//从系统区或保留区增加块
static LPBYTE IncreaseHeap( BLOCKHEAP * lpHeap )
{
	LPBYTE lpRet = NULL;
	UINT uiSave;
	int  size = lpHeap->wBlockSize;

	LockIRQSave( &uiSave );
	if( uiFreeSize >= size && 
		(lpHeap->wFlag & BLOCK_EXCLUSIVE) == 0 )
	{
		lpRet = lpFree;
		lpFree += size;
		uiFreeSize -= size;
		UnlockIRQRestore( &uiSave );
	}
	else
	{  //
		UnlockIRQRestore( &uiSave );
		
		if( (lpRet = (LPBYTE)Page_Alloc( TRUE )) )
		{
			LPBYTE lpRemainder;
			int uiRemainderSize;

			if( lpHeap->wFlag & BLOCK_EXCLUSIVE )
			{
				FreeToHeap( lpHeap, lpRet + size, PAGE_SIZE - size );
			}
			else
			{
				LockIRQSave( &uiSave );
				if( uiFreeSize < PAGE_SIZE - size )
				{
					lpRemainder = lpFree;
					uiRemainderSize = uiFreeSize;
					
					lpFree = lpRet + size;
					uiFreeSize = PAGE_SIZE - size;
				}
				else
				{
					lpRemainder = lpRet + size;
					uiRemainderSize = PAGE_SIZE - size;
				}
				UnlockIRQRestore( &uiSave );
				
				FreeToHeap( NULL, lpRemainder, uiRemainderSize );
			}
		}		
	}
	
	return lpRet;
}

//块堆初始化
BOOL KHeap_Init( void )
{
    int i;

    uiMinBlockSize = heap[0].wBlockSize;
#ifdef __DEBUG
		heap[0].nTotalBlock = 0;
#endif

	for( i = 1; i < MAX_BLOCK_POOLS; i++ )
	{
		uiMinBlockSize = min( heap[i].wBlockSize, uiMinBlockSize );
#ifdef __DEBUG
		heap[i].nTotalBlock = 0;
		heap[i].iUsed = 0;
#endif
         
	}
	uiFreeSize = 0;
	lpFree = NULL;
	iRemainderIndex = 0;
	return TRUE;

}

#ifdef __CHECK_MEM
int startCheckMem = 1;
int startCheckMemSize = 1;
UINT nCheckMemMinSize = 32;
UINT nCheckMemMaxSize = 64;
#endif

#ifdef __CHECK_MEM
LPVOID _KHeap_Alloc( UINT uiSize, const char * lpszFile, int line )
#else
LPVOID KHeap_Alloc( UINT uiSize )
#endif
{
	void * lpRet;
	BLOCKHEAP * lpHeap;

#ifdef __CHECK_MEM
	if( startCheckMem )
	{
		if( startCheckMemSize == 0 || 
			( uiSize > nCheckMemMinSize &&
			  uiSize <= nCheckMemMaxSize) )
			RETAILMSG( 1, ("_KHeap_Alloc:uiSize=%d,f=%s,l=%d,Proc=%s.\r\n", uiSize, lpszFile, line, lpCurThread->lpCurProcess->lpszApplicationName ) );
	}
#endif

    lpHeap = GetHeapPtr( uiSize );
//	ASSERT( lpHeap );
	
	REMOVE_FREE_BLOCK( lpHeap, lpRet ); 

	if( lpRet == NULL )
	{
		if( (lpRet = IncreaseHeap( lpHeap )) )
		{
#ifdef __DEBUG
			lpHeap->nTotalBlock++;
#endif
		}
		else
		{
			RETAILMSG( 1, ( "error in KHeap_Alloc: no enough memory!\r\n" ) );
			return NULL;
		}
	}

#ifdef __DEBUG
	//memset( lpRet, 0xCCCCCCCC, uiSize );
	lpHeap->iUsed++;
#endif

	// TEST
#ifdef VIRTUAL_MEM
    if( lpRet != NULL && ( (DWORD)lpRet & 0x8C000000) != 0x8C000000 )
	{
		RETAILMSG( 1, ("error in KHeap_Free: invalid ptr(0x%x)", lpRet ) );
	}
#endif
	//
	return lpRet;
}

#ifdef __CHECK_MEM
BOOL _KHeap_Free( LPVOID lpvBlock, UINT uiSize, const char * lpszFile, int line )
#else
BOOL KHeap_Free( LPVOID lpvBlock, UINT uiSize )
#endif
{
	BLOCKHEAP * lpHeap;

#ifdef __CHECK_MEM
	if( startCheckMem )
	{
		if( startCheckMemSize == 0 || 
			( uiSize > nCheckMemMinSize &&
			  uiSize <= nCheckMemMaxSize) )
					RETAILMSG( 1, ("KHeap_Free:uiSize=%d,f=%s,l=%d,Proc=%s.\r\n", uiSize, lpszFile, line, lpCurThread->lpCurProcess->lpszApplicationName ) );
	}
#endif

#ifdef VIRTUAL_MEM
	if( ( (DWORD)lpvBlock & 0x8C000000 ) != 0x8C000000 )
	{
		RETAILMSG( 1, ( "error in KHeap_Free: invalid ptr(0x%x), size(%d).\r\n", lpvBlock, uiSize ) );
		return FALSE;
	}
#endif

    lpHeap = GetHeapPtr( uiSize );
//    ASSERT( lpHeap );

    INSERT_FREE_BLOCK( lpHeap, lpvBlock );

#ifdef __DEBUG
	lpHeap->iUsed--;
#endif

    return TRUE;
}

#ifdef __CHECK_MEM
LPVOID _KHeap_AllocString( UINT uiSize, const char * lpszFile, int line )
#else
LPVOID KHeap_AllocString( UINT uiSize )
#endif
{
	UINT nSize = ( uiSize + sizeof( UINT ) + 7 ) & (~7); //align to 8
	UINT * p;

#ifdef __CHECK_MEM
	if( startCheckMem )
	{
		if( startCheckMemSize == 0 || 
			( nSize > nCheckMemMinSize &&
			  nSize <= nCheckMemMaxSize) )
		RETAILMSG( 1, ("_KHeap_AllocString:uiSize=%d,f=%s,l=%d.\r\n", nSize, lpszFile, line ) );
	}
#endif
	p = (UINT*)KHeap_Alloc( nSize );


	if( p ) 
	{
		*p = nSize;
		p++;
	}
	return p;
}

#ifdef __CHECK_MEM
BOOL  _KHeap_FreeString( LPVOID lpv, const char * lpszFile, int line )
#else
BOOL  KHeap_FreeString( LPVOID lpv )
#endif
{
	UINT * p = (UINT*)lpv - 1;

#ifdef __CHECK_MEM
	if( startCheckMem )
	{
		if( startCheckMemSize == 0 || 
			( *p > nCheckMemMinSize &&
			  *p <= nCheckMemMaxSize) )
		RETAILMSG( 1, ("_KHeap_FreeString:s=%d,f=%s,l=%d.\r\n", *p, lpszFile, line ) );
	}
#endif

	if( *p )
	{
		return KHeap_Free( p, *p );
	}
	return FALSE;
}

void KHeap_Check( void )
{
#ifdef __DEBUG

	UINT uiSave;
	int i;
	DWORD dwTotalSize = 0;

	LockIRQSave( &uiSave );

	for( i = 0; i < MAX_BLOCK_POOLS; i++ )
	{
		RETAILMSG( 1, ( "kheap size(%d),nTotalBlock(%d),Used(%d), sum=(%d).\r\n", heap[i].wBlockSize, heap[i].nTotalBlock, heap[i].iUsed,  heap[i].wBlockSize * heap[i].nTotalBlock ) );
		dwTotalSize += heap[i].wBlockSize * heap[i].nTotalBlock;
	}
	RETAILMSG( 1, ( "kheap dwTotalSize=%d.\r\n", dwTotalSize ) );	

	UnlockIRQRestore( &uiSave );

#endif
}

⌨️ 快捷键说明

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