base: support range restriction in allocator

Issue #696
This commit is contained in:
Alexander Boettcher
2015-02-07 23:27:56 +01:00
committed by Christian Helmuth
parent 57c4678aa1
commit 95ff5ba11d
9 changed files with 37 additions and 25 deletions

View File

@ -46,7 +46,7 @@ class Genode::Early_translations_allocator : public Genode::Core_mem_translator
Early_translations_allocator() { } Early_translations_allocator() { }
int add_range(addr_t base, size_t size) { return -1; } int add_range(addr_t base, size_t size) { return -1; }
int remove_range(addr_t base, size_t size) { return -1; } int remove_range(addr_t base, size_t size) { return -1; }
Alloc_return alloc_aligned(size_t size, void **out_addr, int align) { Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) {
return Alloc_return::RANGE_CONFLICT; } return Alloc_return::RANGE_CONFLICT; }
Alloc_return alloc_addr(size_t size, addr_t addr) { Alloc_return alloc_addr(size_t size, addr_t addr) {
return Alloc_return::RANGE_CONFLICT; } return Alloc_return::RANGE_CONFLICT; }

View File

@ -47,7 +47,8 @@ namespace Genode {
return true; return true;
} }
Alloc_return alloc_aligned(size_t, void **out_addr, int) Alloc_return alloc_aligned(size_t, void **out_addr, int,
addr_t, addr_t)
{ {
*out_addr = 0; *out_addr = 0;
return Alloc_return::OK; return Alloc_return::OK;

View File

@ -157,7 +157,7 @@ namespace Genode {
* \param align alignment of new block specified * \param align alignment of new block specified
* as the power of two * as the power of two
*/ */
virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0) = 0; virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from=0, addr_t to = ~0UL) = 0;
/** /**
* Allocate block at address * Allocate block at address

View File

@ -54,13 +54,19 @@ namespace Genode {
* Query if block can hold a specified subblock * Query if block can hold a specified subblock
* *
* \param n number of bytes * \param n number of bytes
* \param from minimum start address of subblock
* \param to maximum end address of subblock
* \param align alignment (power of two) * \param align alignment (power of two)
* \return true if block fits * \return true if block fits
*/ */
inline bool _fits(size_t n, unsigned align = 1) { inline bool _fits(size_t n, unsigned align,
return ((align_addr(addr(), align) >= addr()) && addr_t from, addr_t to)
_sum_in_range(align_addr(addr(), align), n) && {
(align_addr(addr(), align) - addr() + n <= avail())); } addr_t a = align_addr(addr() < from ? from : addr(),
align);
return (a >= addr()) && _sum_in_range(a, n) &&
(a - addr() + n <= avail()) && (a + n - 1 <= to);
}
public: public:
@ -110,7 +116,8 @@ namespace Genode {
/** /**
* Find best-fitting block * Find best-fitting block
*/ */
Block *find_best_fit(size_t size, unsigned align = 1); Block *find_best_fit(size_t size, unsigned align = 1,
addr_t from = 0UL, addr_t to = ~0UL);
/** /**
* Find block that contains the specified address range * Find block that contains the specified address range
@ -215,7 +222,7 @@ namespace Genode {
int add_range(addr_t base, size_t size); int add_range(addr_t base, size_t size);
int remove_range(addr_t base, size_t size); int remove_range(addr_t base, size_t size);
Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0); Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from = 0, addr_t to = ~0UL);
Alloc_return alloc_addr(size_t size, addr_t addr); Alloc_return alloc_addr(size_t size, addr_t addr);
void free(void *addr); void free(void *addr);
size_t avail(); size_t avail();

View File

@ -220,10 +220,10 @@ namespace Genode {
return _alloc.remove_range(base, size); return _alloc.remove_range(base, size);
} }
Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0) Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from = 0, addr_t to = ~0UL)
{ {
Lock::Guard lock_guard(*_lock); Lock::Guard lock_guard(*_lock);
return _alloc.alloc_aligned(size, out_addr, align); return _alloc.alloc_aligned(size, out_addr, align, from, to);
} }
Alloc_return alloc_addr(size_t size, addr_t addr) Alloc_return alloc_addr(size_t size, addr_t addr)

View File

@ -28,7 +28,8 @@ inline void *operator new(size_t, void *at) { return at; }
**************************/ **************************/
Allocator_avl_base::Block * Allocator_avl_base::Block *
Allocator_avl_base::Block::find_best_fit(size_t size, unsigned align) Allocator_avl_base::Block::find_best_fit(size_t size, unsigned align,
addr_t from, addr_t to)
{ {
/* find child with lowest max_avail value */ /* find child with lowest max_avail value */
bool side = _child_max_avail(1) < _child_max_avail(0); bool side = _child_max_avail(1) < _child_max_avail(0);
@ -39,13 +40,13 @@ Allocator_avl_base::Block::find_best_fit(size_t size, unsigned align)
if (_child_max_avail(side) < size) if (_child_max_avail(side) < size)
continue; continue;
Block *res = child(side) ? child(side)->find_best_fit(size, align) : 0; Block *res = child(side) ? child(side)->find_best_fit(size, align, from, to) : 0;
if (res) if (res)
return (_fits(size, align) && size < res->size()) ? this : res; return (_fits(size, align, from, to) && size < res->size()) ? this : res;
} }
return (_fits(size, align)) ? this : 0; return (_fits(size, align, from, to)) ? this : 0;
} }
@ -247,7 +248,7 @@ 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) Range_allocator::Alloc_return Allocator_avl_base::alloc_aligned(size_t size, void **out_addr, int align, addr_t from, addr_t to)
{ {
Block *dst1, *dst2; Block *dst1, *dst2;
if (!_alloc_two_blocks_metadata(&dst1, &dst2)) if (!_alloc_two_blocks_metadata(&dst1, &dst2))
@ -255,7 +256,7 @@ Range_allocator::Alloc_return Allocator_avl_base::alloc_aligned(size_t size, voi
/* find best fitting block */ /* find best fitting block */
Block *b = _addr_tree.first(); Block *b = _addr_tree.first();
b = b ? b->find_best_fit(size, align) : 0; b = b ? b->find_best_fit(size, align, from, to) : 0;
if (!b) { if (!b) {
_md_alloc->free(dst1, sizeof(Block)); _md_alloc->free(dst1, sizeof(Block));
@ -264,7 +265,7 @@ Range_allocator::Alloc_return Allocator_avl_base::alloc_aligned(size_t size, voi
} }
/* calculate address of new (aligned) block */ /* calculate address of new (aligned) block */
addr_t new_addr = align_addr(b->addr(), align); addr_t new_addr = align_addr(b->addr() < from ? from : b->addr(), align);
/* remove new block from containing block */ /* remove new block from containing block */
_cut_from_block(b, new_addr, size, dst1, dst2); _cut_from_block(b, new_addr, size, dst1, dst2);

View File

@ -36,7 +36,7 @@ void * Core_mem_allocator::Mapped_avl_allocator::map_addr(void * addr)
Range_allocator::Alloc_return Range_allocator::Alloc_return
Core_mem_allocator::Mapped_mem_allocator::alloc_aligned(size_t size, void **out_addr, int align) Core_mem_allocator::Mapped_mem_allocator::alloc_aligned(size_t size, void **out_addr, int align, addr_t from, addr_t to)
{ {
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask(); size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
void *phys_addr = 0; void *phys_addr = 0;
@ -44,7 +44,7 @@ Core_mem_allocator::Mapped_mem_allocator::alloc_aligned(size_t size, void **out_
/* allocate physical pages */ /* allocate physical pages */
Alloc_return ret1 = _phys_alloc->alloc_aligned(page_rounded_size, Alloc_return ret1 = _phys_alloc->alloc_aligned(page_rounded_size,
&phys_addr, align); &phys_addr, align, from, to);
if (!ret1.is_ok()) { if (!ret1.is_ok()) {
PERR("Could not allocate physical memory region of size %zu\n", PERR("Could not allocate physical memory region of size %zu\n",
page_rounded_size); page_rounded_size);

View File

@ -162,7 +162,7 @@ class Genode::Core_mem_allocator : public Genode::Core_mem_translator
int add_range(addr_t base, size_t size) { return -1; } int add_range(addr_t base, size_t size) { return -1; }
int remove_range(addr_t base, size_t size) { return -1; } int remove_range(addr_t base, size_t size) { return -1; }
Alloc_return alloc_aligned(size_t size, void **out_addr, Alloc_return alloc_aligned(size_t size, void **out_addr,
int align = 0); int align = 0, addr_t from = 0, addr_t to = ~0UL);
Alloc_return alloc_addr(size_t size, addr_t addr) { Alloc_return alloc_addr(size_t size, addr_t addr) {
return Alloc_return::RANGE_CONFLICT; } return Alloc_return::RANGE_CONFLICT; }
void free(void *addr) {} void free(void *addr) {}
@ -274,10 +274,10 @@ class Genode::Core_mem_allocator : public Genode::Core_mem_translator
Alloc_return alloc_addr(size_t size, addr_t addr) { Alloc_return alloc_addr(size_t size, addr_t addr) {
return Alloc_return::RANGE_CONFLICT; } return Alloc_return::RANGE_CONFLICT; }
Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0) Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0, addr_t from = 0, addr_t to = ~0UL)
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return _mem_alloc.alloc_aligned(size, out_addr, align); return _mem_alloc.alloc_aligned(size, out_addr, align, from, to);
} }
void free(void *addr) void free(void *addr)

View File

@ -90,9 +90,12 @@ class Genode::Packet_allocator : public Genode::Range_allocator
return 0; return 0;
} }
Alloc_return alloc_aligned(size_t size, void **out_addr, int) { Alloc_return alloc_aligned(size_t size, void **out_addr, int, addr_t,
addr_t)
{
return alloc(size, out_addr) ? Alloc_return::OK return alloc(size, out_addr) ? Alloc_return::OK
: Alloc_return::RANGE_CONFLICT; } : Alloc_return::RANGE_CONFLICT;
}
bool alloc(size_t size, void **out_addr) bool alloc(size_t size, void **out_addr)
{ {