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
This commit is contained in:
Alexander Boettcher 2021-02-10 15:27:31 +01:00 committed by Norman Feske
parent 1e84b46c3f
commit 18e282ab8a
3 changed files with 36 additions and 0 deletions

View File

@ -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();
}

View File

@ -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

View File

@ -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)