base: Refine Range_allocator::alloc_aligned

This patch changes the 'alloc_aligned' interface as follows:

- The former 'from' and 'to' arguments are replaced by a single
  'range' argument.

- The distinction of the use cases of regular allocations vs.
  address-constrained allocations is now overed by a dedicated
  overload instead of relying on a default argument.

- The 'align' argument has been changed from 'int' to 'unsigned'
  to be better compatible with 'addr_t' and 'size_t'.

Fixes #4067
This commit is contained in:
Norman Feske 2021-04-06 16:20:01 +02:00
parent 97d44c5a79
commit f925fef17b
14 changed files with 68 additions and 49 deletions

View File

@ -75,7 +75,7 @@ class Genode::Platform : public Platform_generic
bool valid_addr(addr_t ) const override { ASSERT_NEVER_CALLED; }
bool alloc(size_t, void **) override { ASSERT_NEVER_CALLED; }
Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) override
Alloc_return alloc_aligned(size_t, void **, unsigned, Range) override
{ ASSERT_NEVER_CALLED; }
Alloc_return alloc_addr(size_t, addr_t) override
@ -94,10 +94,9 @@ class Genode::Platform : public Platform_generic
return true;
}
Alloc_return alloc_aligned(size_t, void **out_addr, int,
addr_t, addr_t) override
Alloc_return alloc_aligned(size_t, void **out, unsigned, Range) override
{
*out_addr = 0;
*out = 0;
return Alloc_return::OK;
}

View File

@ -166,6 +166,8 @@ struct Genode::Range_allocator : Allocator
bool error() const { return !ok(); }
};
struct Range { addr_t start, end; };
/**
* Allocate block
*
@ -174,8 +176,18 @@ struct Genode::Range_allocator : Allocator
* undefined in the error case
* \param align alignment of new block specified
* as the power of two
* \param range address-range constraint for the allocation
*/
virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align, addr_t from=0, addr_t to = ~0UL) = 0;
virtual Alloc_return alloc_aligned(size_t size, void **out_addr,
unsigned align, Range range) = 0;
/**
* Allocate block without constraining the address range
*/
Alloc_return alloc_aligned(size_t size, void **out_addr, unsigned align)
{
return alloc_aligned(size, out_addr, align, Range { .start = 0, .end = ~0UL });
}
/**
* Allocate block at address

View File

@ -79,18 +79,15 @@ class Genode::Allocator_avl_base : public Range_allocator
* Query if block can hold a specified subblock
*
* \param n number of bytes
* \param from minimum start address of subblock
* \param to maximum end address of subblock
* \param range address constraint of subblock
* \param align alignment (power of two)
* \return true if block fits
*/
inline bool _fits(size_t n, unsigned align,
addr_t from, addr_t to)
inline bool _fits(size_t n, unsigned align, Range range)
{
addr_t a = align_addr(addr() < from ? from : addr(),
align);
addr_t a = align_addr(max(addr(), range.start), align);
return (a >= addr()) && _sum_in_range(a, n) &&
(a - addr() + n <= avail()) && (a + n - 1 <= to);
(a - addr() + n <= avail()) && (a + n - 1 <= range.end);
}
/*
@ -150,8 +147,7 @@ class Genode::Allocator_avl_base : public Range_allocator
/**
* Find best-fitting block
*/
Block *find_best_fit(size_t size, unsigned align,
addr_t from = 0UL, addr_t to = ~0UL);
Block *find_best_fit(size_t size, unsigned align, Range);
/**
* Find block that contains the specified address range
@ -264,13 +260,14 @@ class Genode::Allocator_avl_base : public Range_allocator
int add_range(addr_t base, size_t size) override;
int remove_range(addr_t base, size_t size) override;
Alloc_return alloc_aligned(size_t size, void **out_addr, int align,
addr_t from = 0, addr_t to = ~0UL) override;
Alloc_return alloc_aligned(size_t, void **, unsigned, Range) override;
Alloc_return alloc_addr(size_t size, addr_t addr) override;
void free(void *addr) override;
size_t avail() const override;
bool valid_addr(addr_t addr) const override;
using Range_allocator::alloc_aligned; /* import overloads */
/*************************
** Allocator interface **

View File

@ -168,7 +168,7 @@ _ZN6Genode17Timeout_schedulerD2Ev T
_ZN6Genode18Allocator_avl_base10_add_blockEPNS0_5BlockEmmb T
_ZN6Genode18Allocator_avl_base10alloc_addrEmm T
_ZN6Genode18Allocator_avl_base12remove_rangeEmm T
_ZN6Genode18Allocator_avl_base13alloc_alignedEmPPvimm T
_ZN6Genode18Allocator_avl_base13alloc_alignedEmPPvjNS_15Range_allocator5RangeE T
_ZN6Genode18Allocator_avl_base14_destroy_blockEPNS0_5BlockE T
_ZN6Genode18Allocator_avl_base14any_block_addrEPm T
_ZN6Genode18Allocator_avl_base15_cut_from_blockEPNS0_5BlockEmmS2_S2_ T

View File

@ -34,7 +34,8 @@ void * Mapped_avl_allocator::map_addr(void * addr)
Range_allocator::Alloc_return
Mapped_mem_allocator::alloc_aligned(size_t size, void **out_addr, int align, addr_t from, addr_t to)
Mapped_mem_allocator::alloc_aligned(size_t size, void **out_addr,
unsigned align, Range range)
{
size_t page_rounded_size = align_addr(size, get_page_size_log2());
void *phys_addr = 0;
@ -42,7 +43,7 @@ Mapped_mem_allocator::alloc_aligned(size_t size, void **out_addr, int align, add
/* allocate physical pages */
Alloc_return ret1 = _phys_alloc->alloc_aligned(page_rounded_size,
&phys_addr, align, from, to);
&phys_addr, align, range);
if (!ret1.ok()) {
error("Could not allocate physical memory region of size ",
page_rounded_size);

View File

@ -165,8 +165,7 @@ class Genode::Mapped_mem_allocator : public Genode::Core_mem_translator
int add_range(addr_t, size_t) override { return -1; }
int remove_range(addr_t, size_t) override { return -1; }
Alloc_return alloc_aligned(size_t, void **, int, addr_t from = 0,
addr_t to = ~0UL) override;
Alloc_return alloc_aligned(size_t, void **, unsigned, Range) override;
Alloc_return alloc_addr(size_t, addr_t) override {
return Alloc_return::RANGE_CONFLICT; }
void free(void *) override;
@ -174,6 +173,8 @@ class Genode::Mapped_mem_allocator : public Genode::Core_mem_translator
bool valid_addr(addr_t addr) const override {
return _virt_alloc->valid_addr(addr); }
using Range_allocator::alloc_aligned; /* import overloads */
/*************************
** Allocator interface **
@ -280,11 +281,11 @@ class Genode::Core_mem_allocator : public Genode::Core_mem_translator
Alloc_return alloc_addr(size_t, addr_t) override {
return Alloc_return::RANGE_CONFLICT; }
Alloc_return alloc_aligned(size_t size, void **out_addr, int align,
addr_t from = 0, addr_t to = ~0UL) override
Alloc_return alloc_aligned(size_t size, void **out_addr,
unsigned align, Range range) override
{
Mutex::Guard lock_guard(_mutex);
return _mem_alloc.alloc_aligned(size, out_addr, align, from, to);
return _mem_alloc.alloc_aligned(size, out_addr, align, range);
}
void free(void *addr) override
@ -297,6 +298,8 @@ class Genode::Core_mem_allocator : public Genode::Core_mem_translator
bool valid_addr(addr_t addr) const override { return _virt_alloc.valid_addr(addr); }
using Range_allocator::alloc_aligned; /* import overloads */
/*************************
** Allocator interface **

View File

@ -32,7 +32,8 @@ class Genode::Ram_dataspace_factory : public Ram_allocator,
{
public:
struct Phys_range { addr_t start, end; };
typedef Range_allocator::Range Phys_range;
static Phys_range any_phys_range() { return { 0UL, ~0UL }; }
struct Virt_range { addr_t start, size; };

View File

@ -93,9 +93,9 @@ class Genode::Synced_range_allocator : public Range_allocator
int remove_range(addr_t base, size_t size) override {
return _synced_object()->remove_range(base, size); }
Alloc_return alloc_aligned(size_t size, void **out_addr, int align,
addr_t from = 0, addr_t to = ~0UL) override {
return _synced_object()->alloc_aligned(size, out_addr, align, from, to); }
Alloc_return alloc_aligned(size_t size, void **out_addr,
unsigned align, Range range) override {
return _synced_object()->alloc_aligned(size, out_addr, align, range); }
Alloc_return alloc_addr(size_t size, addr_t addr) override {
return _synced_object()->alloc_addr(size, addr); }
@ -108,6 +108,8 @@ class Genode::Synced_range_allocator : public Range_allocator
bool valid_addr(addr_t addr) const override {
return _synced_object()->valid_addr(addr); }
using Range_allocator::alloc_aligned; /* import overloads */
};
#endif /* _CORE__INCLUDE__SYNCED_RANGE_ALLOCATOR_H_ */

View File

@ -47,10 +47,12 @@ Ram_dataspace_factory::alloc(size_t ds_size, Cache_attribute cached)
* constraints.
*/
if (_phys_range.start == 0 && _phys_range.end == ~0UL) {
addr_t const high_start = (sizeof(void *) == 4 ? 3UL : 4UL) << 30;
Phys_range const range { .start = high_start, .end = _phys_range.end };
for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) {
if (_phys_alloc.alloc_aligned(ds_size, &ds_addr, align_log2,
high_start, _phys_range.end).ok()) {
if (_phys_alloc.alloc_aligned(ds_size, &ds_addr, align_log2, range).ok()) {
alloc_succeeded = true;
break;
}
@ -61,7 +63,7 @@ Ram_dataspace_factory::alloc(size_t ds_size, Cache_attribute cached)
if (!alloc_succeeded) {
for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) {
if (_phys_alloc.alloc_aligned(ds_size, &ds_addr, align_log2,
_phys_range.start, _phys_range.end).ok()) {
_phys_range).ok()) {
alloc_succeeded = true;
break;
}

View File

@ -24,7 +24,7 @@ using namespace Genode;
Allocator_avl_base::Block *
Allocator_avl_base::Block::find_best_fit(size_t size, unsigned align,
addr_t from, addr_t to)
Range range)
{
/* find child with lowest max_avail value */
bool side = _child_max_avail(1) < _child_max_avail(0);
@ -35,13 +35,13 @@ Allocator_avl_base::Block::find_best_fit(size_t size, unsigned align,
if (_child_max_avail(side) < size)
continue;
Block *res = child(side) ? child(side)->find_best_fit(size, align, from, to) : 0;
Block *res = child(side) ? child(side)->find_best_fit(size, align, range) : 0;
if (res)
return (_fits(size, align, from, to) && size < res->size()) ? this : res;
return (_fits(size, align, range) && size < res->size()) ? this : res;
}
return (_fits(size, align, from, to)) ? this : 0;
return (_fits(size, align, range)) ? this : 0;
}
@ -304,8 +304,8 @@ int Allocator_avl_base::remove_range(addr_t base, size_t size)
Range_allocator::Alloc_return
Allocator_avl_base::alloc_aligned(size_t size, void **out_addr, int align,
addr_t from, addr_t to)
Allocator_avl_base::alloc_aligned(size_t size, void **out_addr, unsigned align,
Range range)
{
Block *dst1, *dst2;
if (!_alloc_two_blocks_metadata(&dst1, &dst2))
@ -313,7 +313,7 @@ Allocator_avl_base::alloc_aligned(size_t size, void **out_addr, int align,
/* find best fitting block */
Block *b = _addr_tree.first();
b = b ? b->find_best_fit(size, align, from, to) : 0;
b = b ? b->find_best_fit(size, align, range) : 0;
if (!b) {
_md_alloc->free(dst1, sizeof(Block));
@ -322,7 +322,7 @@ Allocator_avl_base::alloc_aligned(size_t size, void **out_addr, int align,
}
/* calculate address of new (aligned) block */
addr_t new_addr = align_addr(b->addr() < from ? from : b->addr(), align);
addr_t new_addr = align_addr(max(b->addr(), range.start), align);
/* remove new block from containing block */
_cut_from_block(b, new_addr, size, dst1, dst2);

View File

@ -76,7 +76,7 @@ class Pci_driver : public Bsd::Bus_driver
Pci_driver &drv)
: Genode::Allocator_avl(&alloc), env(env), _drv(drv) { }
Genode::addr_t alloc(Genode::size_t size, int align)
Genode::addr_t alloc(Genode::size_t size, unsigned align)
{
using namespace Genode;

View File

@ -142,7 +142,7 @@ namespace Allocator {
return _range.alloc(size, out_addr);
}
void *alloc_aligned(size_t size, int align = 0)
void *alloc_aligned(size_t size, unsigned align = 0)
{
void *addr;
@ -207,7 +207,7 @@ namespace Allocator {
Fap(bool cached)
: _back_allocator(cached ? CACHED : UNCACHED) { }
void *alloc(size_t size, int align = 0)
void *alloc(size_t size, unsigned align = 0)
{
return _back_allocator.alloc_aligned(size, align);
}

View File

@ -116,8 +116,8 @@ class Genode::Packet_allocator : public Genode::Range_allocator
return 0;
}
Alloc_return alloc_aligned(size_t size, void **out_addr, int, addr_t,
addr_t) override
Alloc_return alloc_aligned(size_t size, void **out_addr, unsigned,
Range) override
{
return alloc(size, out_addr) ? Alloc_return::OK
: Alloc_return::RANGE_CONFLICT;

View File

@ -662,6 +662,8 @@ class Genode::Packet_stream_source : private Packet_stream_base
typedef typename POLICY::Ack_queue Ack_queue;
typedef typename POLICY::Content_type Content_type;
enum { PACKET_ALIGNMENT = POLICY::Packet_descriptor::PACKET_ALIGNMENT };
Genode::Range_allocator &_packet_alloc;
Packet_descriptor_transmitter<Submit_queue> _submit_transmitter;
@ -765,7 +767,7 @@ class Genode::Packet_stream_source : private Packet_stream_base
* \return packet descriptor with an assigned range within the
* bulk buffer shared between source and sink
*/
Packet_descriptor alloc_packet(Genode::size_t size, int align = POLICY::Packet_descriptor::PACKET_ALIGNMENT)
Packet_descriptor alloc_packet(Genode::size_t size, unsigned align = PACKET_ALIGNMENT)
{
void *base = 0;
if (size && _packet_alloc.alloc_aligned(size, &base, align).error())