grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v4 2/2] mm: Better handling of adding new regions


From: Zhang Boyang
Subject: [PATCH v4 2/2] mm: Better handling of adding new regions
Date: Sat, 15 Oct 2022 22:15:12 +0800

Previously, there are two problems of the handling of adding new
regions. First, it doesn't take region management cost into account.
Adding a memory area of `x` bytes will result in a heap region of less
than `x` bytes avaliable. Thus, the new region might not adequate for
current allocation request. Second, it doesn't pre-allocate a big region
for small allocations, so it might be slow for many small allocations.

This patch introduces GRUB_MM_MAX_COST to address the cost of region
management. The value of this constant should make
`grub_mm_init_region (addr, size + GRUB_MM_MAX_COST)` initialize a
region of at least `size` free bytes available. The size of heap growth
is now adjusted according this value before calling
grub_mm_add_region_fn ().

This patch also introduces GRUB_MM_HEAP_GROW to address the minimal heap
growth granularity. When a small allocation encounters heap space
exhaustion, the size of heap growth is now expended to this value, and a
new region of bigger size will be added. Thus subsequent allocations can
use the remaining space of that new region.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/kern/mm.c       | 18 +++++++++++++++---
 include/grub/mm_private.h | 12 ++++++++++++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
index ae2279133..fe630f061 100644
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -410,7 +410,9 @@ grub_memalign (grub_size_t align, grub_size_t size)
 {
   grub_mm_region_t r;
   grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
+  grub_size_t guarantee;
   int count = 0;
+  grub_size_t grow;
 
   if (!grub_mm_base)
     goto fail;
@@ -418,10 +420,13 @@ grub_memalign (grub_size_t align, grub_size_t size)
   if (size > ~(grub_size_t) align)
     goto fail;
 
+  /* Allocation can always success if max continuous free chunk >= guarantee */
+  guarantee = size + align;
+
   /* We currently assume at least a 32-bit grub_size_t,
      so limiting allocations to <adress space size> - 1MiB
      in name of sanity is beneficial. */
-  if ((size + align) > ~(grub_size_t) 0x100000)
+  if (guarantee > ~(grub_size_t) 0x100000)
     goto fail;
 
   align = (align >> GRUB_MM_ALIGN_LOG2);
@@ -443,11 +448,18 @@ grub_memalign (grub_size_t align, grub_size_t size)
   switch (count)
     {
     case 0:
+      /* Calculate optimal size of heap growth. */
+      grow = grub_max(guarantee, GRUB_MM_HEAP_GROW);
+
+      /* Adjust heap growth to address the cost of region management. */
+      if (grub_add(grow, GRUB_MM_MAX_COST, &grow))
+       goto fail;
+
       /* Request additional pages, contiguous */
       count++;
 
       if (grub_mm_add_region_fn != NULL &&
-          grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == 
GRUB_ERR_NONE)
+          grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == 
GRUB_ERR_NONE)
        goto again;
 
       /* fallthrough  */
@@ -462,7 +474,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
            * Try again even if this fails, in case it was able to partially
            * satisfy the request
            */
-          grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE);
+          grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_NONE);
           goto again;
         }
 
diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
index 96c2d816b..a01ba2507 100644
--- a/include/grub/mm_private.h
+++ b/include/grub/mm_private.h
@@ -95,6 +95,18 @@ typedef struct grub_mm_region
 }
 *grub_mm_region_t;
 
+/*
+ * Set an upper bound of management cost of each region,
+ * with sizeof(struct grub_mm_region), sizeof(struct grub_mm_header) and
+ * any possible alignment or padding taken into account.
+ * The value should make `grub_mm_init_region (addr, size + GRUB_MM_MAX_COST)`
+ * initialize a region of at least `size` free bytes available.
+ */
+#define GRUB_MM_MAX_COST 0x1000
+
+/* Minimal heap growth granularity, when existing heap space is exhausted. */
+#define GRUB_MM_HEAP_GROW 0x100000
+
 #ifndef GRUB_MACHINE_EMU
 extern grub_mm_region_t EXPORT_VAR (grub_mm_base);
 #endif
-- 
2.30.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]