Implement sub-allocation of small requests Modified: trunk/reactos/boot/freeldr/freeldr/freeldr.c Modified: trunk/reactos/boot/freeldr/freeldr/mm/mm.c _____
Modified: trunk/reactos/boot/freeldr/freeldr/freeldr.c --- trunk/reactos/boot/freeldr/freeldr/freeldr.c 2005-05-25 20:59:13 UTC (rev 15496) +++ trunk/reactos/boot/freeldr/freeldr/freeldr.c 2005-05-25 22:36:35 UTC (rev 15497) @@ -35,7 +35,7 @@
DebugInit();
- DbgPrint((DPRINT_WARNING, "BootMain() called. BootDrive = 0x%x BootPartition = %d\n", BootDrive, BootPartition)); + DbgPrint((DPRINT_WARNING, "BootMain() called.\n"));
if (!MmInitializeMemoryManager()) { _____
Modified: trunk/reactos/boot/freeldr/freeldr/mm/mm.c --- trunk/reactos/boot/freeldr/freeldr/mm/mm.c 2005-05-25 20:59:13 UTC (rev 15496) +++ trunk/reactos/boot/freeldr/freeldr/mm/mm.c 2005-05-25 22:36:35 UTC (rev 15497) @@ -36,10 +36,30 @@
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 @@ 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 @@ 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 @@
#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++)