From 419f2d6f3ed3f9cddc9932829fda4f7a114c853c Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 1 Sep 2009 08:46:39 +0000 Subject: [PATCH] Fix errors in maintaining the area list due to assumptions that are only true for the page list but not the area one. Since multiple pages can be allocated at once, even an area that is not at the top of the list can become empty. In such a case the area list would previously have lost entries. Also because we can remove more than one page from any area, not just the top one, we may need to move forward in the list so that it stays ordered by free pages. +alphabranch git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32880 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/heap.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/heap.cpp b/src/system/kernel/heap.cpp index a8d0ccf167..8dd693ccd4 100644 --- a/src/system/kernel/heap.cpp +++ b/src/system/kernel/heap.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008, Michael Lotz, mmlr@mlotz.ch. + * Copyright 2008-2009, Michael Lotz, mmlr@mlotz.ch. * Distributed under the terms of the MIT License. * * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. @@ -1193,10 +1193,35 @@ heap_free_pages_removed(heap_allocator *heap, heap_area *area, uint32 pageCount) if (area->free_page_count == 0) { // the area is now full so we remove it from the area list - heap->areas = area->next; + if (area->prev) + area->prev->next = area->next; if (area->next) - area->next->prev = NULL; + area->next->prev = area->prev; + if (heap->areas == area) + heap->areas = area->next; area->next = area->prev = NULL; + } else { + // we might need to move forward in the area list + if (area->prev && area->prev->free_page_count > area->free_page_count) { + // move ourselfs so the list stays ordered + heap_area *insert = area->prev; + while (insert->prev + && insert->prev->free_page_count > area->free_page_count) + insert = insert->prev; + + if (area->prev) + area->prev->next = area->next; + if (area->next) + area->next->prev = area->prev; + + area->prev = insert->prev; + area->next = insert; + if (area->prev) + area->prev->next = area; + if (heap->areas == insert) + heap->areas = area; + insert->prev = area; + } } }