Implement sub-allocation of small requests

svn path=/trunk/; revision=15497
This commit is contained in:
Gé van Geldorp 2005-05-25 22:36:35 +00:00
parent fcb49212d9
commit d670d4f7e6
2 changed files with 45 additions and 3 deletions

View file

@ -35,7 +35,7 @@ VOID BootMain(char *CmdLine)
DebugInit(); DebugInit();
DbgPrint((DPRINT_WARNING, "BootMain() called. BootDrive = 0x%x BootPartition = %d\n", BootDrive, BootPartition)); DbgPrint((DPRINT_WARNING, "BootMain() called.\n"));
if (!MmInitializeMemoryManager()) if (!MmInitializeMemoryManager())
{ {

View file

@ -36,10 +36,30 @@ VOID DecrementAllocationCount(VOID);
VOID MemAllocTest(VOID); VOID MemAllocTest(VOID);
#endif // DEBUG #endif // DEBUG
/*
* Hack alert
* Normally, we allocate whole pages. This is ofcourse wastefull for small
* allocations (a few bytes). So, for small allocations (smaller than a page)
* we sub-allocate. When the first small allocation is done, a page is
* requested. We keep a pointer to that page in SubAllocationPage. The alloc
* is satisfied by returning a pointer to the beginning of the page. We also
* keep track of how many bytes are still available in the page in SubAllocationRest.
* When the next small request comes in, we try to allocate it just after the
* memory previously allocated. If it won't fit, we allocate a new page and
* the whole process starts again.
* Note that suballocations are done back-to-back, there's no bookkeeping at all.
* That also means that we cannot really free suballocations. So, when a free is
* done and it is determined that this might be a free of a sub-allocation, we
* just no-op the free.
* Perhaps we should use the heap routines from ntdll here.
*/
static PVOID SubAllocationPage = NULL;
static unsigned SubAllocationRest = 0;
PVOID MmAllocateMemory(ULONG MemorySize) PVOID MmAllocateMemory(ULONG MemorySize)
{ {
ULONG PagesNeeded; ULONG PagesNeeded;
ULONG FirstFreePageFromEnd; ULONG FirstFreePageFromEnd;
PVOID MemPointer; PVOID MemPointer;
if (MemorySize == 0) if (MemorySize == 0)
@ -49,6 +69,14 @@ PVOID MmAllocateMemory(ULONG MemorySize)
return NULL; return NULL;
} }
MemorySize = ROUND_UP(MemorySize, 4);
if (MemorySize <= SubAllocationRest)
{
MemPointer = SubAllocationPage + MM_PAGE_SIZE - SubAllocationRest;
SubAllocationRest -= MemorySize;
return MemPointer;
}
// Find out how many blocks it will take to // Find out how many blocks it will take to
// satisfy this allocation // satisfy this allocation
PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE; PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE;
@ -76,6 +104,13 @@ PVOID MmAllocateMemory(ULONG MemorySize)
FreePagesInLookupTable -= PagesNeeded; FreePagesInLookupTable -= PagesNeeded;
MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE); MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE);
if (MemorySize < MM_PAGE_SIZE)
{
SubAllocationPage = MemPointer;
SubAllocationRest = MM_PAGE_SIZE - MemorySize;
}
#ifdef DEBUG #ifdef DEBUG
IncrementAllocationCount(); IncrementAllocationCount();
DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount)); DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount));
@ -235,6 +270,13 @@ VOID MmFreeMemory(PVOID MemoryPointer)
#endif #endif
/* If this allocation is only a single page, it could be a sub-allocated page.
* Just don't free it */
if (1 == PageCount)
{
return;
}
// Loop through our array and mark all the // Loop through our array and mark all the
// blocks as free // blocks as free
for (Idx=PageNumber; Idx<(PageNumber + PageCount); Idx++) for (Idx=PageNumber; Idx<(PageNumber + PageCount); Idx++)