#include "precomp.h" #pragma hdrstop // // This thing is COMPLETELY single-threaded. // Use no serialize to speed things up. // HANDLE Heap; // // Define structure used to track preallocations. // typedef struct _PREALLOC { DWORD BlockSize; DWORD BlockCount; PVOID BaseAddress; PVOID EndAddress; LONG FreeIndex; PVOID bitmap; RTL_BITMAP Bitmap; // // Just for statistics // DWORD NumUsed; } PREALLOC, *PPREALLOC; PREALLOC Prealloc[] = { { 32,1000 }, { 128,1000 }, { 512,20 }, { 4096,30 }, { 8192,10 }, { 16384 , 5 }, { 0 } }; PVOID pAllocPreAlloc( IN OUT PPREALLOC Prealloc ); VOID pFreePreAlloc( IN OUT PPREALLOC Prealloc, IN PVOID p ); BOOL SInit( IN BOOL Init ) { BOOL b; unsigned u; PPREALLOC p; if(Init) { if(Heap) { b = TRUE; } else { if(Heap = HeapCreate(HEAP_NO_SERIALIZE,512*1024,0)) { b = TRUE; for(u=0; b && Prealloc[u].BlockSize; u++) { p = &Prealloc[u]; p->BaseAddress = HeapAlloc(Heap,0,p->BlockSize*p->BlockCount); if(p->BaseAddress) { p->EndAddress = (PUCHAR)p->BaseAddress + (p->BlockSize*p->BlockCount); p->FreeIndex = 0; p->bitmap = HeapAlloc(Heap,HEAP_ZERO_MEMORY,(p->BlockCount+7) / 8); if(p->bitmap) { RtlInitializeBitMap(&p->Bitmap,p->bitmap,p->BlockCount); } else { b = FALSE; } } else { b = FALSE; } } } else { b = FALSE; } } } else { // // If heap is null this will return FALSE which is what we want. // b = HeapDestroy(Heap); Heap = NULL; } return(b); } PVOID SAlloc( IN DWORD Size ) { PVOID p; PPREALLOC prealloc; if(!Heap) { return(NULL); } // // Determine which block size to use. // for(prealloc=Prealloc; prealloc->BlockSize; prealloc++) { if(Size < prealloc->BlockSize) { // // Found the right size block. // p = pAllocPreAlloc(prealloc); if(!p) { // // None available. Go to the heap. // break; } return(p); } } // // No preallocated block will suffice. Go to the heap. // return(HeapAlloc(Heap,HEAP_NO_SERIALIZE,(DWORD)Size)); } VOID SFree( IN PVOID Block ) { PPREALLOC prealloc; if(!Heap) { return; } // // See whether the block comes from our prealloced memory. // for(prealloc=Prealloc; prealloc->BlockSize; prealloc++) { if((Block >= prealloc->BaseAddress) && (Block < prealloc->EndAddress)) { pFreePreAlloc(prealloc,Block); return; } } // // Not a preallocated block. Go to the heap. // HeapFree(Heap,HEAP_NO_SERIALIZE,Block); } PVOID SRealloc( IN PVOID Block, IN DWORD NewSize ) { SIZE_T u; PVOID p; BOOL b; PPREALLOC NewPrealloc,OldPrealloc; if(!Heap) { return(NULL); } NewPrealloc = NULL; OldPrealloc = NULL; b = FALSE; for(u=0; Prealloc[u].BlockSize; u++) { // // See whether the original block comes from this prealloc. // if((OldPrealloc == NULL) && (Block >= Prealloc[u].BaseAddress) && (Block < Prealloc[u].EndAddress)) { OldPrealloc = &Prealloc[u]; } // // See whether we have a prealloc block appropriate // to satisfy the request. Only the smallest appropriate // size is allowed. // if(!b && (NewSize < Prealloc[u].BlockSize)) { // // Special case: the old block is from prealloc memory // and the same size prealloc block would satisfy the request. // Just reuse the existing block. // if(OldPrealloc == &Prealloc[u]) { return(Block); } if(Prealloc[u].FreeIndex != -1) { NewPrealloc = &Prealloc[u]; } b = TRUE; } } // // See if the current block is from prealloc memory and we can // satisfy the request from a different prealloc block size. // if(OldPrealloc && NewPrealloc) { p = pAllocPreAlloc(NewPrealloc); if(!p) { // // Something is very wrong, because NewPrealloc can be set // only if there was a free block! // return(NULL); } CopyMemory(p,Block,__min(NewPrealloc->BlockSize,OldPrealloc->BlockSize)); pFreePreAlloc(OldPrealloc,Block); return(p); } // // If the current block is from prealloc memory but we can't // satisfy the request from prealloc memory, allocate memory from // the heap. // if(OldPrealloc && !NewPrealloc) { if(p = HeapAlloc(Heap,HEAP_NO_SERIALIZE,NewSize)) { CopyMemory(p,Block,__min(OldPrealloc->BlockSize,NewSize)); pFreePreAlloc(OldPrealloc,Block); } return(p); } // // If the current block is not from prealloc memory and we can // satisy the request from prealloc memory, copy the current memory // into the prealloc block and return the prealloc block. // if(!OldPrealloc && NewPrealloc) { u = HeapSize(Heap,HEAP_NO_SERIALIZE,Block); if(u == (SIZE_T)(-1)) { return(NULL); } p = pAllocPreAlloc(NewPrealloc); if(!p) { // // Something is very wrong, because NewPrealloc can be set // only if there was a free block! // return(NULL); } CopyMemory(p,Block,__min(u,NewPrealloc->BlockSize)); HeapFree(Heap,HEAP_NO_SERIALIZE,Block); return(p); } // // The current block is not from prealloc memory and there's no // preallocated memory to satisfy the request. Pass the request // to the heap. // return(HeapReAlloc(Heap,HEAP_NO_SERIALIZE,Block,NewSize)); } PVOID pAllocPreAlloc( IN OUT PPREALLOC Prealloc ) { PVOID p; if(Prealloc->FreeIndex == -1) { return(NULL); } // // Calculate the address of the block. // p = (PUCHAR)Prealloc->BaseAddress + (Prealloc->FreeIndex * Prealloc->BlockSize); Prealloc->NumUsed++; // // Mark the block we are going to return as used. // RtlSetBits(&Prealloc->Bitmap,Prealloc->FreeIndex,1); // // Locate the next free block. This sets FreeIndex to -1 // if there are no more free blocks of this size. // Prealloc->FreeIndex = (LONG)RtlFindClearBits( &Prealloc->Bitmap, 1, Prealloc->FreeIndex ); return(p); } VOID pFreePreAlloc( IN OUT PPREALLOC Prealloc, IN PVOID p ) { LONG Index; // // Figure out which block this is. // Index = (LONG)((LONG_PTR)p - (LONG_PTR)Prealloc->BaseAddress) / Prealloc->BlockSize; Prealloc->NumUsed--; // // Mark the block free. // RtlClearBits(&Prealloc->Bitmap,Index,1); Prealloc->FreeIndex = Index; }