www.pudn.com > WinGOS.rar > Memory.cpp


#include "GOS.h" 
#include "Memory.h" 
 
#define TRACE(x)  
 
#define HA_INTSIZE sizeof(DWORD) 
#define HA_GROUPLAST 11 
#define HA_GROUPFIRST 4 
#define HA_BLOCKALIGN(nGroup) (1<<(nGroup)) 
#define HA_PAGEALIGN(nSize) ((((nSize)+4095)>>12)<<12) 
#define HA_PTRADDINT(p,i) PDWORD((DWORD(p)+(i))) 
#define HA_PAGECOUNT ((*(m_pHeap-1)+4059)>>12) 
#define HA_HEADINTCOUNT ((*(m_pHeap-1)+0x11ffdb)>>17) 
#define HA_BLOCKOFFSET(pBlock) (DWORD(pBlock)-DWORD(m_pHeap+HA_HEADINTCOUNT)) //调试用 
 
PVOID operator new(UINT nSize){return malloc(nSize);} 
VOID operator delete(PVOID pData){free(pData);} 
PVOID operator new[](UINT nSize){return malloc(nSize);} 
VOID operator delete[](PVOID pData){free(pData);} 
PVOID operator new(UINT nSize,PVOID pObj){return realloc(pObj,nSize);} 
VOID operator delete(PVOID pData,PVOID pObj){pData=pObj;} 
 
void CHeap::Create(PVOID pBlock) 
{ 
	DEBUG_ONLY(m_nPushCnt=0); 
	m_pHeap=PDWORD(pBlock); 
	ZeroMemory(m_pHeap,HA_HEADINTCOUNT*HA_INTSIZE); 
} 
 
PVOID CHeap::Delete() 
{ 
	ASSERT(!m_nPushCnt); 
	return m_pHeap; 
} 
 
BOOL CHeap::IncludePtr(PCVOID pBlock) 
{ 
	return DWORD(pBlock) > DWORD(m_pHeap) 
		&& DWORD(pBlock) < DWORD(m_pHeap) + *(PDWORD(m_pHeap)-1); 
} 
PVOID CHeap::Alloc(DWORD nSize) 
{ 
	PDWORD pBlock; 
	DWORD i,nGroup=i=Group(nSize+HA_INTSIZE); 
	TRACE("\r\n",nSize); 
	while(i<=HA_GROUPLAST && !m_pHeap[i-HA_GROUPFIRST]) 
		i++; 
	if(i<=HA_GROUPLAST) 
		pBlock=ChainPop(i); 
	else 
		pBlock=(PDWORD)PageAlloc(NULL,HA_PAGEALIGN(nSize+HA_INTSIZE)); 
	if(pBlock) 
	{ 
		SplitBlock(pBlock,i,nGroup); 
		pBlock[0]=nSize; 
		TRACE("HeapAlloc(%d),Addr=%d\r\n",nSize,HA_BLOCKOFFSET(pBlock)); 
		pBlock++; 
	} 
	else 
	{ 
		TRACE("HeapAlloc(%d),Addr=-1\r\n",nSize); 
	} 
	return pBlock; 
} 
 
PVOID CHeap::ReAlloc(PVOID pBlock,DWORD nSize) 
{ 
	if(!pBlock) 
		return Alloc(nSize); 
	if(!nSize) 
	{ 
		Free(pBlock); 
		return NULL; 
	} 
	 
	PDWORD pData=(PDWORD)pBlock-1; 
	DWORD i=Group(*pData+HA_INTSIZE); 
	DWORD nToGroup,j=nToGroup=Group(nSize+HA_INTSIZE); 
	 
	TRACE("\r\n",nSize); 
	if(j>i) 
	{ 
		pBlock=MergeBlock(pData,i,&nToGroup); 
		if(nToGroupi) 
			pBlock=PageAlloc(HA_PTRADDINT(pData,i),j-i); 
		else if(jHA_GROUPLAST) 
			PageFree(pData,i); 
		pBlock=Alloc(nSize); 
		if(pBlock) 
			CopyMemory(pBlock,pData+1,*pData); 
		if(nToGroup<=HA_GROUPLAST) 
			ChainPush(pData,nToGroup); 
	} 
	TRACE("HeapReAlloc(%d),Addr=%d\r\n",nSize,HA_BLOCKOFFSET(pBlock)-4); 
	return pBlock; 
} 
 
void CHeap::Free(PVOID pBlock) 
{ 
	if(!pBlock) 
		return; 
 
	PDWORD pData=PDWORD(pBlock)-1; 
	DWORD nSize=*pData; 
	DWORD nGroup=Group(nSize+HA_INTSIZE); 
	DWORD nToGroup=HA_GROUPLAST+1; 
 
	TRACE("\r\n",nSize); 
	if(nGroup<=HA_GROUPLAST) 
	{ 
		pData=MergeBlock(pData,nGroup,&nToGroup); 
	} 
	if(nToGroup>HA_GROUPLAST) 
		PageFree(pData,HA_PAGEALIGN(nSize+HA_INTSIZE)); 
	else 
		ChainPush(pData,nToGroup); 
	TRACE("HeapFree(%d),Size=%d\r\n",HA_BLOCKOFFSET(pData),nSize); 
} 
 
//决定组大小,HeapAlloc的Size需要上HA_INTSIZE; 
//返回为HA_GROUPLAST+1时是位图 
DWORD CHeap::Group(DWORD nSize) 
{ 
	DWORD i=HA_GROUPFIRST; 
	while((1UL<HA_GROUPLAST?HA_GROUPLAST+1:i; 
} 
 
//合并组,如果可以合并就把伙伴块从空闲链移除,组增大 
//返回时Group可达B12 
PDWORD CHeap::MergeBlock(PVOID pBlock,DWORD nGroup,PDWORD pToGroup) 
{ 
	PDWORD pBuffer=m_pHeap+HA_HEADINTCOUNT; 
	PDWORD pData,pData2; 
	DWORD nPartner,nBlockSize; 
	DWORD nPos=DWORD(pBlock)-DWORD(pBuffer); 
	while(nGroup<*pToGroup) 
	{ 
		nBlockSize=HA_BLOCKALIGN(nGroup); 
		if((nPos>>nGroup)&1) 
			nPartner=nPos-nBlockSize; 
		else 
			nPartner=nPos+nBlockSize; 
		pData=HA_PTRADDINT(pBuffer,nPartner); 
		if(*pData!=~nGroup) 
			break; 
 
		if(pData[1]) 
		{ 
			DEBUG_ONLY(m_nPushCnt--); 
			TRACE("MergeRemove(%d),Group=%d(PushCnt=%d)\r\n",HA_BLOCKOFFSET(pData),nGroup,m_nPushCnt); 
			pData2=PDWORD(pData[2]); 
			pData=PDWORD(pData[1]); 
			pData[2]=DWORD(pData2); 
			if(pData2) 
				pData2[1]=DWORD(pData); 
		} 
		else 
			pData=ChainPop(nGroup); 
		if(nPartnernToGroup) 
	{ 
		nGroup--; 
		nBlockSize=HA_BLOCKALIGN(nGroup); 
		pFree=HA_PTRADDINT(pBlock,nBlockSize); 
		ChainPush(pFree,nGroup); 
	} 
} 
void CHeap::ChainPush(PDWORD pBlock,DWORD nGroup) 
{ 
	DEBUG_ONLY(m_nPushCnt++); 
	TRACE("ChainPush(%d),Group=%d(PushCnt=%d)\r\n",HA_BLOCKOFFSET(pBlock),nGroup,m_nPushCnt); 
	PDWORD pChain=&m_pHeap[nGroup-HA_GROUPFIRST];  
	pBlock[0]=~nGroup; 
	pBlock[1]=NULL; 
	pBlock[2]=DWORD(*pChain); 
	if(pBlock[2]) 
		*(PDWORD(pBlock[2])+1)=DWORD(pBlock); 
	*pChain=DWORD(pBlock); 
} 
PDWORD CHeap::ChainPop(DWORD nGroup) 
{ 
	PDWORD pChain=&m_pHeap[nGroup-HA_GROUPFIRST]; 
	PDWORD pBlock=PDWORD(*pChain); 
	DEBUG_ONLY(m_nPushCnt--); 
	TRACE("ChainPop(%d),Group=%d(PushCnt=%d)\r\n",HA_BLOCKOFFSET(pBlock),nGroup,m_nPushCnt); 
	*pChain=pBlock[2]; 
	if(*pChain) 
		*(PDWORD(*pChain)+1)=NULL; 
	return pBlock; 
} 
 
//如果pBlock为空,自动分配 
//否则如果pBlock对应处有nSize空页,返回pBlock; 
//否则返回Null; 
PVOID CHeap::PageAlloc(PVOID pBlock,DWORD nSize) 
{ 
	DWORD i=pBlock?(DWORD(pBlock)-DWORD(m_pHeap+HA_HEADINTCOUNT))>>12:0; 
	DWORD nPage=-1,nPages=HA_PAGECOUNT; 
	PDWORD pBitmap=m_pHeap+8; 
	 
	for(nSize>>=12;i>5] & (1<<(i&31))) 
		{ 
			if(pBlock) 
			{ 
				i=nPages; 
				break; 
			} 
			nPage=-1; 
		} 
		else 
		{ 
			if(nPage==-1) 
				nPage=i; 
			if(i-nPage+1==nSize) 
				break; 
		} 
	} 
	if(i>5] |=1<<(i & 31); 
		} 
		DEBUG_ONLY(m_nPushCnt+=nSize-nPage); 
		TRACE("PageAlloc(HA_PAGECOUNT=%d,PageStart=%d,PushCnt=%d)\r\n",nSize-nPage,nPage,m_nPushCnt); 
		pBlock=HA_PTRADDINT(m_pHeap+HA_HEADINTCOUNT,nPage<<12); 
	} 
	else 
		pBlock=NULL; 
 
	return pBlock; 
} 
 
//从位图中将对应的位标记为空闲 
void CHeap::PageFree(PVOID pBlock,DWORD nSize) 
{ 
	DWORD i=(DWORD(pBlock)-DWORD(m_pHeap+HA_HEADINTCOUNT))>>12; 
	PDWORD pBitmap=m_pHeap+8; 
	DEBUG_ONLY(m_nPushCnt-=nSize>>12); 
	TRACE("PageFree(HA_PAGECOUNT=%d,PageStart=%d,PushCnt=%d)\r\n",nSize>>12,i,m_nPushCnt); 
	nSize=i+(nSize>>12); 
	for(;i>5] &=~(1<<(i & 31)); 
	} 
} 
 
int CHeap::ElementCount(int nElementBytes,int nCount,int nReservedBytes) 
{ 
	int nBytes=HA_INTSIZE+nReservedBytes; 
	if(nCount>0) 
		nBytes+=nCount*nElementBytes; 
	else 
		nBytes-=nCount?nCount:-128; 
	nCount=16; 
	while(nCount0); 
 
	return nCount; 
} 
 
 
void FillMemory(PVOID pDest,DWORD nLength,BYTE nFill) 
{ 
	DWORD p=DWORD(pDest); 
	DWORD i,nData=nFill; 
 
	nData=nFill; 
	nData=(nData<<8)|nData; 
	nData=(nData<<16)|nData; 
	 
	nLength=DWORD(pDest)+nLength; 
	if((DWORD(pDest) & ~0x03) == (nLength & ~0x03)) 
	{ 
		i=DWORD(pDest) & 0x03; 
		if(i) 
		{ 
			p-=i; 
			i=(1<<(i<<3))-1; 
		} 
		nLength &= 0x03; 
		nLength=(1<<(nLength<<3))-1; 
		i |= ~nLength; 
		*(PDWORD)p &= i; 
		*(PDWORD)p |= ~i & nData ; 
	} 
	else 
	{ 
		i=DWORD(pDest) & 0x03; 
		if(i) 
		{ 
			p-=i; 
			i=(1<<(i<<3))-1; 
			*(PDWORD)p &= i; 
			*(PDWORD)p |= ~i & nData ; 
			p+=4; 
		} 
		i=nLength & ~0x03; 
		while(ppSrc) 
		{ 
			p=DWORD(pDest); 
			s=DWORD(pSrc)+nLength-p; 
			while(nLength>p) 
			{ 
				nLength--; 
				s--; 
				*PBYTE(nLength)=*PBYTE(s); 
			} 
		} 
	} 
	else if(pDestpSrc) 
	{ 
		nLength=DWORD(pDest)+nLength; 
		p=nLength & ~0x03; 
		s=DWORD(pSrc)+p-DWORD(pDest); 
		i=nLength & 0x03; 
		if(i) 
		{ 
			i=(1<<(i<<3))-1; 
			*PDWORD(p) &= ~i; 
			*PDWORD(p) |= i & *PDWORD(s); 
		} 
		i=(DWORD(pDest) & ~0x03)+4; 
		while(p>i) 
		{ 
			p-=4; 
			s-=4; 
			*PDWORD(p)=*PDWORD(s); 
		} 
		p-=4;s-=4; 
		i=DWORD(pDest) & 0x03; 
		if(i) 
		{ 
			i=(1<<(i<<3))-1; 
			*(PDWORD)p &= i; 
			*(PDWORD)p |= ~i & *PDWORD(s); 
		} 
		else 
		{ 
			*PDWORD(p)=*PDWORD(s); 
		} 
	} 
}