[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/6] mm: document grub_free
From: |
Daniel Axtens |
Subject: |
[PATCH 4/6] mm: document grub_free |
Date: |
Thu, 25 Nov 2021 02:22:48 +1100 |
grub_free () posesses a surprising number of quirks, and also
uses single-letter variable names confusingly to iterate through
the free list.
Document what's going on.
Use prev and cur to iterate over the free list.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
grub-core/kern/mm.c | 63 +++++++++++++++++++++++++++++----------------
1 file changed, 41 insertions(+), 22 deletions(-)
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
index ac41cf4aab15..bec960c18e2b 100644
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -446,54 +446,73 @@ grub_free (void *ptr)
}
else
{
- grub_mm_header_t q, s;
+ grub_mm_header_t cur, prev;
#if 0
- q = r->first;
+ cur = r->first;
do
{
grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n",
- GRUB_FILE, __LINE__, q, q->size, q->magic);
- q = q->next;
+ GRUB_FILE, __LINE__, cur, cur->size, cur->magic);
+ cur = cur->next;
}
- while (q != r->first);
+ while (cur != r->first);
#endif
-
- for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q =
s->next)
+ /* Iterate over all blocks in the free ring.
+ *
+ * The free ring is arranged from high addresses to low
+ * addresses, modulo wraparound.
+ *
+ * We are looking for a block with a higher address than p or
+ * whose next address is lower than p.
+ */
+ for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p;
+ prev = cur, cur = prev->next)
{
- if (q->magic != GRUB_MM_FREE_MAGIC)
- grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic);
+ if (cur->magic != GRUB_MM_FREE_MAGIC)
+ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic);
- if (q <= q->next && (q > p || q->next < p))
+ /* Deal with wrap-around */
+ if (cur <= cur->next && (cur > p || cur->next < p))
break;
}
+ /* mark p as free and insert it between cur and cur->next */
p->magic = GRUB_MM_FREE_MAGIC;
- p->next = q->next;
- q->next = p;
+ p->next = cur->next;
+ cur->next = p;
+ /*
+ * If the block we are freeing can be merged with the next
+ * free block, do that.
+ */
if (p->next + p->next->size == p)
{
p->magic = 0;
p->next->size += p->size;
- q->next = p->next;
+ cur->next = p->next;
p = p->next;
}
- r->first = q;
+ r->first = cur;
- if (q == p + p->size)
+ /* Likewise if can be merged with the preceeding free block */
+ if (cur == p + p->size)
{
- q->magic = 0;
- p->size += q->size;
- if (q == s)
- s = p;
- s->next = p;
- q = s;
+ cur->magic = 0;
+ p->size += cur->size;
+ if (cur == prev)
+ prev = p;
+ prev->next = p;
+ cur = prev;
}
- r->first = q;
+ /*
+ * Set r->first such that the just free()d block is tried first.
+ * (An allocation is tried from *first->next, and cur->next == p.)
+ */
+ r->first = cur;
}
}
--
2.32.0
- [PATCH 0/6] Document mm, Daniel Axtens, 2021/11/24
- [PATCH 1/6] mm: document grub internal memory management structures, Daniel Axtens, 2021/11/24
- [PATCH 4/6] mm: document grub_free,
Daniel Axtens <=
- [PATCH 3/6] mm: grub_real_malloc: make small allocs comment match code, Daniel Axtens, 2021/11/24
- [PATCH 5/6] mm: document grub_mm_init_region, Daniel Axtens, 2021/11/24
- [PATCH 6/6] [RFC] docs: document mm, Daniel Axtens, 2021/11/24
- [PATCH 2/6] mm: clarify grub_real_malloc, Daniel Axtens, 2021/11/24