From 18e282ab8ac6e3e797a2f407cab9e617c89ffd1f Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 10 Feb 2021 15:27:31 +0100 Subject: [PATCH] allocator_avl: avoid false dangling warnings By first removing unused ranges, implicitly meta data allocations are freed up. This leads to more unused slab blocks and freed up meta data allocations in the avl tree. Issue #4014 --- repos/base/include/base/allocator_avl.h | 3 +++ repos/base/lib/symbols/ld | 2 ++ repos/base/src/lib/base/allocator_avl.cc | 31 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/repos/base/include/base/allocator_avl.h b/repos/base/include/base/allocator_avl.h index 9accdfc27e..a2e0c94c90 100644 --- a/repos/base/include/base/allocator_avl.h +++ b/repos/base/include/base/allocator_avl.h @@ -188,6 +188,7 @@ class Genode::Allocator_avl_base : public Range_allocator addr_t base, size_t size, bool used); Block *_find_any_used_block(Block *sub_tree); + Block *_find_any_unused_block(Block *sub_tree); /** * Destroy block @@ -215,6 +216,7 @@ class Genode::Allocator_avl_base : public Range_allocator * from the meta-data allocator. */ void _revert_allocations_and_ranges(); + void _revert_unused_ranges(); /** * Find block by specified address @@ -342,6 +344,7 @@ class Genode::Allocator_avl_tpl : public Allocator_avl_base ~Allocator_avl_tpl() { + _revert_unused_ranges(); _metadata.free_empty_blocks(); _revert_allocations_and_ranges(); } diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 7e8aa86adc..66f83c53c5 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -173,6 +173,8 @@ _ZN6Genode18Allocator_avl_base14any_block_addrEPm T _ZN6Genode18Allocator_avl_base15_cut_from_blockEPNS0_5BlockEmmS2_S2_ T _ZN6Genode18Allocator_avl_base20_find_any_used_blockEPNS0_5BlockE T _ZN6Genode18Allocator_avl_base21_alloc_block_metadataEv T +_ZN6Genode18Allocator_avl_base21_revert_unused_rangesEv T +_ZN6Genode18Allocator_avl_base22_find_any_unused_blockEPNS0_5BlockE T _ZN6Genode18Allocator_avl_base26_alloc_two_blocks_metadataEPPNS0_5BlockES3_ T _ZN6Genode18Allocator_avl_base30_revert_allocations_and_rangesEv T _ZN6Genode18Allocator_avl_base4freeEPv T diff --git a/repos/base/src/lib/base/allocator_avl.cc b/repos/base/src/lib/base/allocator_avl.cc index a23379eee7..cd6807d264 100644 --- a/repos/base/src/lib/base/allocator_avl.cc +++ b/repos/base/src/lib/base/allocator_avl.cc @@ -187,6 +187,21 @@ void Allocator_avl_base::_cut_from_block(Block *b, addr_t addr, size_t size, } +void Allocator_avl_base::_revert_unused_ranges() +{ + do { + Block * const block = _find_any_unused_block(_addr_tree.first()); + if (!block) + break; + + int const error = remove_range(block->addr(), block->size()); + if (error && block == _find_any_unused_block(_addr_tree.first())) + /* if the invocation fails, release the block to break endless loop */ + _destroy_block(block); + } while (true); +} + + void Allocator_avl_base::_revert_allocations_and_ranges() { /* revert all allocations */ @@ -390,6 +405,22 @@ size_t Allocator_avl_base::size_at(void const *addr) const } +Allocator_avl_base::Block *Allocator_avl_base::_find_any_unused_block(Block *sub_tree) +{ + if (!sub_tree) + return nullptr; + + if (!sub_tree->used()) + return sub_tree; + + for (unsigned i = 0; i < 2; i++) + if (Block *block = _find_any_unused_block(sub_tree->child(i))) + return block; + + return nullptr; +} + + Allocator_avl_base::Block *Allocator_avl_base::_find_any_used_block(Block *sub_tree) { if (!sub_tree)