fixheap.c

来自「wince下的源代码集合打包」· C语言 代码 · 共 753 行 · 第 1/2 页

C
753
字号
			pTrav->pCur = ptr2;			if ((pTrav->dwFree > (pTrav->dwCommitted >> 3)) &&				((pTrav->dwFree > pTrav->dwLastCompact + (pagemask+1)*6) ||				 ((UserKInfo[KINX_PAGEFREE]*UserKInfo[KINX_PAGESIZE] < 2*1024*1024) &&				  (pTrav->dwFree > pTrav->dwLastCompact + (pagemask+1)*2))))				FixedHeapCompact(pTrav);			return TRUE;		}	}	pvaprev = 0;	for (pva = pHeap->pVallocs; pva; pvaprev = pva, pva = pva->pnext)		if (pva->pBase == ptr) {    		if (!pvaprev)    			pHeap->pVallocs = pva->pnext;    		else    			pvaprev->pnext = pva->pnext;	    	VirtualFree(pva->pBase,0,MEM_RELEASE);    		FixedHeapFree(pHeap,pva);    		return TRUE;		}	DEBUGCHK(0);	SetLastError(ERROR_INVALID_PARAMETER);	return FALSE;}// Alloc a heap blockLPVOID FixedHeapAlloc(pheap pHeapIn, UINT size, BOOL zero) {   	pheap pHeap2;	heap newheap;	LPVOID ptr;	UINT increase, presize;	pheap pHeap;	DWORD  dwMaxLeft;#ifdef MEMTRACKING	WCHAR Name[14];#endif	if (size & 0x80000000) {		SetLastError(ERROR_NOT_ENOUGH_MEMORY);		return 0;	}	size = (size + ALIGNMASK) & ~ALIGNMASK;    if (size >= CE_VALLOC_MINSIZE) {    	vaheapalloc *pva;		if (!(ptr=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE)))			SetLastError(ERROR_NOT_ENOUGH_MEMORY);		else {			if (!(pva = FixedHeapAlloc(pHeapIn,sizeof(vaheapalloc),0))) {				VirtualFree(ptr,0,MEM_RELEASE);				ptr = 0;			} else {				pva->pBase = ptr;				pva->dwSize = (size + pagemask) & ~pagemask;				pva->pnext = pHeapIn->pVallocs;				pHeapIn->pVallocs = pva;			}		}#ifdef DEBUG        if (!zero && ptr)			memset(ptr, 0xcc, pva->dwSize);#endif    		return ptr;	}	for (pHeap = pHeapIn; pHeap; pHeap = pHeap->pGrowthHeap) {		if (!pHeap->pMem)			if (!SetupFixedHeap(pHeap))				return 0;		if ((!pHeap->dwMaxLeft && (size <= pHeap->dwFree)) || (size <= pHeap->dwMaxLeft)) {			ptr = pHeap->pCur;			dwMaxLeft = 0;			do {				if (!ISINUSE(ptr)) {					if (ISFREE(ptr)) {						GrowFree(pHeap,ptr);						if (ITEMSIZE(ptr) >= size)							goto FoundBlock;					}					DEBUGCHK(!pHeap->dwMaxLeft || (ITEMSIZE(ptr) <= pHeap->dwMaxLeft));					if (ITEMSIZE(ptr) > dwMaxLeft)						dwMaxLeft = ITEMSIZE(ptr);				}				ptr = NEXTBLOCK(pHeap,ptr);			} while (((DWORD)ptr > (DWORD)pHeap->pCur) || 	                 (((DWORD)ptr + ITEMSIZE(ptr)) < (DWORD)pHeap->pCur));	        pHeap->dwMaxLeft = dwMaxLeft;		}		pHeap->pCur = pHeap->pMem;	}	for (pHeap = pHeapIn; pHeap; pHeap = pHeap->pGrowthHeap) {		DEBUGCHK(pHeap->pMem);		DEBUGCHK(pHeap->pCur == pHeap->pMem);		ptr = pHeap->pMem;		if (size <= (pHeap->dwFree + pHeap->dwMaximumSize - pHeap->dwCommitted)) {			do {				if (!ISINUSE(ptr) && MakePotentialSize(pHeap,ptr,size))					goto FoundBlock;				pHeap->pNexttolast = ptr;				ptr = NEXTBLOCK(pHeap,ptr);			} while (ptr != pHeap->pMem);		}	}	for (pHeap = pHeapIn; pHeap; pHeap = pHeap->pGrowthHeap) {		DEBUGCHK(pHeap->pMem);		DEBUGCHK(pHeap->pCur == pHeap->pMem);		if (size <= (pHeap->dwFree + ((DWORD)pHeap->pMem + pHeap->dwMaximumSize - (DWORD)pHeap->pHigh))) {			if (!ISFREE(pHeap->pNexttolast) || ISDEAD(pHeap->pNexttolast)) {				ptr = pHeap->pHigh;				presize = 0;			} else {				ptr = pHeap->pNexttolast;				presize = ITEMSIZE(pHeap->pNexttolast) + HDRSIZE + TLRSIZE;			}			increase = (size - presize + HDRSIZE + TLRSIZE + pagemask) & ~pagemask;			if ((DWORD)pHeap->pHigh + increase <= (DWORD)pHeap->pMem + pHeap->dwMaximumSize) {		        pHeap->flOptions |= HEAP_IS_CHANGING_VM;				if (VirtualAlloc(pHeap->pHigh,increase,MEM_COMMIT,PAGE_READWRITE)) {					pHeap->pHigh = (LPVOID)((DWORD)pHeap->pHigh + increase);					pHeap->dwCommitted += increase;					pHeap->dwFree += increase;					if (!presize)						pHeap->dwFree -= (HDRSIZE+TLRSIZE);					INITFREEBLOCK(ptr,increase-HDRSIZE-TLRSIZE+presize);					if (pHeap->dwMaxLeft && (ITEMSIZE(ptr) > pHeap->dwMaxLeft))						pHeap->dwMaxLeft = ITEMSIZE(ptr);				} else					ptr = 0;		        pHeap->flOptions &= ~HEAP_IS_CHANGING_VM;		        goto FoundBlock;		    }		}	}	if (pHeapIn->flOptions & HEAP_IS_NEW)		return 0;	newheap.pNextHeap	  = 0;	newheap.pGrowthHeap   = 0;	newheap.pVallocs 	  = 0;    newheap.flOptions     = (pHeapIn->flOptions & ~HEAP_IS_CHANGING_VM) | HEAP_IS_NEW;    newheap.dwMaximumSize = CE_FIXED_HEAP_MAXSIZE;    newheap.pMem          = NULL;    newheap.pHigh         = NULL;    newheap.pCur          = NULL;    newheap.dwCommitted   = 0;    newheap.dwFree        = 0;    newheap.dwLastCompact = 0;    newheap.dwMaxLeft     = 0;   	if ((ptr = FixedHeapAlloc(&newheap,size,zero)) && (pHeap2 = FixedHeapAlloc(&newheap,sizeof(heap),0))) {		*pHeap2 = newheap;		pHeap2->pGrowthHeap = pHeapIn->pGrowthHeap;		pHeapIn->pGrowthHeap = pHeap2;		pHeap2->flOptions &= ~HEAP_IS_NEW;#ifdef MEMTRACKING		swprintf(Name, L"Heap %08X", pHeap2);		pHeap2->dwMemType     = RegisterTrackedItem(Name);#endif		goto done;	}	if (newheap.pMem) {		VirtualFree(newheap.pMem,newheap.dwMaximumSize,MEM_DECOMMIT);		VirtualFree(newheap.pMem, 0, MEM_RELEASE);	}   	return 0;FoundBlock:	if (ptr) {		SplitFreeBlock(pHeap,ptr,size);		DEBUGCHK(pHeap->dwFree >= ITEMSIZE(ptr));		pHeap->dwFree -= ITEMSIZE(ptr);		if (pHeap->dwMaxLeft == ITEMSIZE(ptr))			pHeap->dwMaxLeft = 0;		INITUSEDBLOCK(ptr,ITEMSIZE(ptr));		pHeap->pCur = NEXTBLOCK(pHeap,ptr);		ptr = HEAPTOPTR(ptr);		if (zero)			memset(ptr,0,ITEMSIZE(PTRTOHEAP(ptr)));#ifdef DEBUG        if (!zero) {        	UINT loop;        	for (loop = 0; loop < ITEMSIZE(PTRTOHEAP(ptr)); loop++)        		DEBUGCHK(((LPBYTE)ptr)[loop] == 0xcc);        }#endif    	} else		pHeap->pCur = pHeap->pMem;done:	return ptr;}// Realloc a heap blockLPVOID FixedHeapReAlloc(pheap pHeap, LPVOID ptr, UINT size, BOOL zero, BOOL move) {	LPVOID newptr;	UINT oldsize;	pheap pTrav;	vaheapalloc *pva, *pvaprev;	for (pva = pHeap->pVallocs; pva; pva = pva->pnext) {		if (pva->pBase == ptr) {			if (size <= pva->dwSize) {				if (!move)					return ptr;				if (!(newptr = FixedHeapAlloc(pHeap,size,0)))					return ptr;				memcpy(newptr,ptr,size);			} else {				if (!move)					return 0;				if (!(newptr = FixedHeapAlloc(pHeap,size,0)))					return 0;				memcpy(newptr,ptr,pva->dwSize);				if (zero)					memset((LPBYTE)newptr+pva->dwSize,0,size-pva->dwSize);			}			VirtualFree(pva->pBase,0,MEM_RELEASE);			if (pHeap->pVallocs == pva)				pHeap->pVallocs = pva->pnext;			else {				for (pvaprev = pHeap->pVallocs; pvaprev->pnext != pva; pvaprev = pvaprev->pnext)					;				pvaprev->pnext = pva->pnext;			}    		FixedHeapFree(pHeap,pva);			return newptr;		}	}	if (size & 0x80000000) {		SetLastError(ERROR_NOT_ENOUGH_MEMORY);		return 0;	}	size = (size + ALIGNMASK) & ~ALIGNMASK;	newptr = ptr = PTRTOHEAP(ptr);	for (pTrav = pHeap; pTrav; pTrav = pTrav->pGrowthHeap) {		if (pTrav->pMem && IsSigValid(pTrav,ptr,0)) {			oldsize = ITEMSIZE(ptr);			if (size <= oldsize) {				ShrinkBlock(pTrav,ptr,size);				pTrav->pCur = NEXTBLOCK(pTrav,ptr);				newptr = HEAPTOPTR(ptr);				goto DoneRealloc;			}			newptr = NEXTBLOCK(pTrav,newptr);			if ((newptr > ptr) && ISFREE(newptr)) {				GrowFree(pTrav,newptr);				if (ITEMSIZE(newptr)+HDRSIZE+TLRSIZE+oldsize >= size) {					DEBUGCHK(pTrav->dwFree >= ITEMSIZE(newptr));					pTrav->dwFree -= ITEMSIZE(newptr);					if (pTrav->dwMaxLeft == ITEMSIZE(newptr))						pTrav->dwMaxLeft = 0;					INITUSEDBLOCK(ptr,oldsize+ITEMSIZE(newptr)+HDRSIZE+TLRSIZE);					ShrinkBlock(pTrav,ptr,size);					pTrav->pCur = NEXTBLOCK(pTrav,ptr);					newptr = HEAPTOPTR(ptr);					goto DoneRealloc;				}				pTrav->pCur = newptr;			}			if (move && (newptr = FixedHeapAlloc(pHeap,size,0))) {				memcpy(newptr,HEAPTOPTR(ptr),oldsize);				FixedHeapFree(pHeap,HEAPTOPTR(ptr));				goto DoneRealloc;			}			return 0;		}	}	DEBUGCHK(0);	return 0;DoneRealloc:	if (zero && (size > oldsize))		memset((LPBYTE)newptr+oldsize,0,FixedHeapSize(pHeap,newptr)-oldsize);	return newptr;}// Compact a heapvoid FixedHeapCompact(pheap pHeap) {	LPBYTE ptr, ptr2;	int numpieces, deadbytes, size, size2;	if (!(ptr = pHeap->pMem) || (pHeap->flOptions & HEAP_IS_CHANGING_VM) || (pHeap->flOptions & HEAP_IS_SHARED))		return;	do {		if (ISINUSE(ptr))			ptr = NEXTBLOCK(pHeap, ptr);		else {			numpieces = deadbytes = 0;			ptr2 = ptr;			do {				numpieces--;				if (ITEMSIZE(ptr2) == pHeap->dwMaxLeft)					pHeap->dwMaxLeft = 0;				if (ISDEAD(ptr2))					deadbytes -= ITEMSIZE(ptr2);			} while (((ptr2 = NEXTBLOCK(pHeap, ptr2)) != pHeap->pMem) && !ISINUSE(ptr2));			if (ptr2 != pHeap->pMem) {				// see if there are going to be dead pages				if (((DWORD)(ptr + HDRSIZE + pagemask) & ~pagemask) < ((DWORD)(ptr2 - TLRSIZE) & ~pagemask)) {					// see if there is room at the start for a live free block					size = pagemask + 1 - ((DWORD)ptr & pagemask);					if (size > HDRSIZE + TLRSIZE + HDRSIZE) {						INITFREEBLOCK(ptr, size - HDRSIZE - TLRSIZE - HDRSIZE);						if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr)))							pHeap->dwMaxLeft = ITEMSIZE(ptr);						ptr += size - HDRSIZE;						numpieces++;					}					// now do the dead block					size = ptr2 - ptr;					if (((DWORD)(ptr2 - TLRSIZE) & pagemask) >= HDRSIZE + TLRSIZE)						size -= ((DWORD)ptr2 - TLRSIZE) & pagemask;					INITDEADBLOCK(ptr,size - HDRSIZE - TLRSIZE);					if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr)))						pHeap->dwMaxLeft = ITEMSIZE(ptr);					numpieces++;					size2 = ((DWORD)(ptr2 - TLRSIZE) & ~pagemask) - ((DWORD)(ptr + HDRSIZE + pagemask) & ~pagemask);					VirtualFree((LPVOID)((DWORD)(ptr+HDRSIZE+pagemask) & ~pagemask), size2, MEM_DECOMMIT);					deadbytes += size - HDRSIZE - TLRSIZE;					ptr += size;				}				// Do the final free block, if any				if (ptr != ptr2) {					DEBUGCHK(ptr + HDRSIZE + TLRSIZE <= ptr2);					INITFREEBLOCK(ptr, ptr2 - ptr - HDRSIZE - TLRSIZE);					if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr)))						pHeap->dwMaxLeft = ITEMSIZE(ptr);					numpieces++;				}				pHeap->pCur = pHeap->pMem;				pHeap->dwCommitted -= deadbytes;				DEBUGCHK((deadbytes + numpieces * (int)(HDRSIZE + TLRSIZE) < 0) || 					(pHeap->dwFree >= deadbytes + numpieces * (HDRSIZE + TLRSIZE)));				pHeap->dwFree -= deadbytes + numpieces*(HDRSIZE+TLRSIZE);				ptr = NEXTBLOCK(pHeap, ptr2);			} else {				if (ptr == pHeap->pMem) {					VirtualFree(pHeap->pMem,(LPBYTE)pHeap->pHigh - ptr,MEM_DECOMMIT);					VirtualFree(pHeap->pMem,0,MEM_RELEASE);				    pHeap->pMem = NULL;				    pHeap->pHigh = NULL;				    pHeap->pCur = NULL;				    pHeap->dwCommitted = 0;				    pHeap->dwFree = 0;				    pHeap->dwMaxLeft = 0;				} else {					// see if there are going to be free bytes					if ((DWORD)ptr & pagemask) {						size = pagemask + 1 - ((DWORD)ptr & pagemask);						if (size < HDRSIZE + TLRSIZE) {#ifdef DEBUG							// The place we want to put the tail signature could be on a free							// block.  Since this is only in debug, and pretty rare, just							// ignore the case.							pHeap->pCur = pHeap->pMem;							break;#else													size += pagemask + 1;#endif						}						INITFREEBLOCK(ptr, size - HDRSIZE - TLRSIZE);						if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr)))							pHeap->dwMaxLeft = ITEMSIZE(ptr);						numpieces++;						ptr = ptr + size;					}					if (ptr != pHeap->pHigh) {						size2 = (LPBYTE)pHeap->pHigh - ptr;						VirtualFree(ptr, size2, MEM_DECOMMIT);						deadbytes += size2;						pHeap->pHigh = ptr;					}					pHeap->pCur = pHeap->pMem;					pHeap->dwCommitted -= deadbytes;					DEBUGCHK((deadbytes + numpieces * (int)(HDRSIZE + TLRSIZE) < 0) || 						(pHeap->dwFree >= deadbytes + numpieces * (HDRSIZE + TLRSIZE)));					pHeap->dwFree -= deadbytes + numpieces * (HDRSIZE + TLRSIZE);				}				break;			}		}	} while (ptr != pHeap->pMem);	pHeap->dwLastCompact = pHeap->dwFree;}

⌨️ 快捷键说明

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