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++)