diff --git a/reactos/boot/freeldr/freeldr/freeldr.c b/reactos/boot/freeldr/freeldr/freeldr.c index 05913e561d0..54e8638bbef 100644 --- a/reactos/boot/freeldr/freeldr/freeldr.c +++ b/reactos/boot/freeldr/freeldr/freeldr.c @@ -35,7 +35,7 @@ VOID BootMain(char *CmdLine) DebugInit(); - DbgPrint((DPRINT_WARNING, "BootMain() called. BootDrive = 0x%x BootPartition = %d\n", BootDrive, BootPartition)); + DbgPrint((DPRINT_WARNING, "BootMain() called.\n")); if (!MmInitializeMemoryManager()) { diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index 402069a634e..6b81d8e16ef 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -36,10 +36,30 @@ VOID DecrementAllocationCount(VOID); VOID MemAllocTest(VOID); #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) { - ULONG PagesNeeded; - ULONG FirstFreePageFromEnd; + ULONG PagesNeeded; + ULONG FirstFreePageFromEnd; PVOID MemPointer; if (MemorySize == 0) @@ -49,6 +69,14 @@ PVOID MmAllocateMemory(ULONG MemorySize) 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 // satisfy this allocation PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE; @@ -76,6 +104,13 @@ PVOID MmAllocateMemory(ULONG MemorySize) FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE); + if (MemorySize < MM_PAGE_SIZE) + { + SubAllocationPage = MemPointer; + SubAllocationRest = MM_PAGE_SIZE - MemorySize; + } + + #ifdef DEBUG IncrementAllocationCount(); 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 + /* 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 // blocks as free for (Idx=PageNumber; Idx<(PageNumber + PageCount); Idx++)