From da1ef670642376a12441bd8997b34bb028da7cee Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Thu, 31 Mar 2022 13:58:53 +0200 Subject: [PATCH] base: Allocator_avl cleanup meta data After reverting unused ranges during allocator destruction '_meta_data.free_empty_blocks' may lead to more unused ranges because meta data blocks maybe freed where the meta data for the blocks is managed by other meta data blocks. This leads to dangling allocation warnings which are caused by meta data. Therefore, we call '_revert_unused_ranges' and 'free_empty_blocks' until no more ranges can be freed. issue #4466 --- repos/base/include/base/allocator_avl.h | 14 +++++++++++--- repos/base/src/lib/base/allocator_avl.cc | 11 +++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/repos/base/include/base/allocator_avl.h b/repos/base/include/base/allocator_avl.h index a74f1d93ce..4fa66e1660 100644 --- a/repos/base/include/base/allocator_avl.h +++ b/repos/base/include/base/allocator_avl.h @@ -208,7 +208,7 @@ class Genode::Allocator_avl_base : public Range_allocator void _cut_from_block(Block &b, addr_t cut_addr, size_t cut_size, Two_blocks); template - void _revert_block_ranges(ANY_BLOCK_FN const &); + bool _revert_block_ranges(ANY_BLOCK_FN const &); template Alloc_result _allocate(size_t, unsigned, Range, SEARCH_FN const &); @@ -225,7 +225,7 @@ class Genode::Allocator_avl_base : public Range_allocator * from the meta-data allocator. */ void _revert_allocations_and_ranges(); - void _revert_unused_ranges(); + bool _revert_unused_ranges(); /** * Find block by specified address @@ -354,7 +354,15 @@ class Genode::Allocator_avl_tpl : public Allocator_avl_base ~Allocator_avl_tpl() { _revert_unused_ranges(); - _metadata.free_empty_blocks(); + + /* + * The release of empty blocks may add unused ranges (formerly used + * by metadata). Thus, we loop until all empty blocks are freed and + * no additional unused ranges appear. + */ + do { + _metadata.free_empty_blocks(); + } while (_revert_unused_ranges()); _revert_allocations_and_ranges(); } diff --git a/repos/base/src/lib/base/allocator_avl.cc b/repos/base/src/lib/base/allocator_avl.cc index 76ce55f19a..d89e5c12c2 100644 --- a/repos/base/src/lib/base/allocator_avl.cc +++ b/repos/base/src/lib/base/allocator_avl.cc @@ -172,9 +172,10 @@ void Allocator_avl_base::_cut_from_block(Block &b, addr_t addr, size_t size, Two template -void Allocator_avl_base::_revert_block_ranges(FN const &any_block_fn) +bool Allocator_avl_base::_revert_block_ranges(FN const &any_block_fn) { - for (bool loop = true; loop; ) { + size_t blocks = 0; + for (bool loop = true; loop; blocks++) { Block *block_ptr = any_block_fn(); if (!block_ptr) @@ -188,12 +189,14 @@ void Allocator_avl_base::_revert_block_ranges(FN const &any_block_fn) loop = false; /* give up on OUT_OF_RAM or OUT_OF_CAPS */ }); } + + return blocks > 0; } -void Allocator_avl_base::_revert_unused_ranges() +bool Allocator_avl_base::_revert_unused_ranges() { - _revert_block_ranges([&] () { + return _revert_block_ranges([&] () { return _find_any_unused_block(_addr_tree.first()); }); }