mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +00:00
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:
parent
97d44c5a79
commit
f925fef17b
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 **
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -165,15 +165,16 @@ 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;
|
||||
size_t avail() const override { return _phys_alloc->avail(); }
|
||||
bool valid_addr(addr_t addr) const override {
|
||||
void free(void *) override;
|
||||
size_t avail() const override { return _phys_alloc->avail(); }
|
||||
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 **
|
||||
|
@ -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; };
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
|
Loading…
x
Reference in New Issue
Block a user