Skip to content

Commit 3b8b75f

Browse files
committed
Fixes allocator heap corruption bug and assertion failure.
- page_collect shouldn't assume that the page has an empty free list, but neither should it do O(n) work when it does not. - After page_free, alloc_generic should not refer to the page anymore. Signed-off-by: Nathan Ringo <me@remexre.com>
1 parent e3211a5 commit 3b8b75f

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

src/kernel/mm/alloc.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,14 @@ void *alloc_generic(usize size, struct mm_alloc_heap *heap) {
111111
page = container_of(page_head, struct mm_alloc_page, list);
112112
page_head = page_head->next;
113113

114-
// Collect free objects in the page.
115-
page_collect(page);
116-
117114
// Free the page if it's empty.
118-
if (page_is_empty(page))
115+
if (page_is_empty(page)) {
119116
page_free(page, heap);
117+
continue;
118+
}
119+
120+
// Collect free objects in the page.
121+
page_collect(page);
120122

121123
// If there are any free objects, use them.
122124
if (!page_is_full(page))

src/kernel/mm/alloc/page.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,11 @@ void page_bounds(const struct mm_alloc_page *page, uptr *out_start,
271271
}
272272

273273
void page_collect(struct mm_alloc_page *page) {
274+
// If we can allocate an object from the page, don't bother collecting it.
275+
if (block_ref_deref(page, page->free))
276+
return;
277+
274278
// Since our hart owns the local free list, we can just move it over.
275-
assert(!block_ref_deref(page, page->free));
276279
page->free = page->local_free;
277280
page->local_free = block_ref_make(page, nullptr);
278281

0 commit comments

Comments
 (0)