diff --git a/repos/base-hw/src/core/include/kernel/early_translations.h b/repos/base-hw/src/core/include/kernel/early_translations.h index 82081c937..3f796907c 100644 --- a/repos/base-hw/src/core/include/kernel/early_translations.h +++ b/repos/base-hw/src/core/include/kernel/early_translations.h @@ -46,7 +46,7 @@ class Genode::Early_translations_allocator : public Genode::Core_mem_translator Early_translations_allocator() { } int add_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; } Alloc_return alloc_addr(size_t size, addr_t addr) { return Alloc_return::RANGE_CONFLICT; } diff --git a/repos/base-linux/src/core/include/platform.h b/repos/base-linux/src/core/include/platform.h index 34fa3d804..6ebbbacc4 100644 --- a/repos/base-linux/src/core/include/platform.h +++ b/repos/base-linux/src/core/include/platform.h @@ -47,7 +47,8 @@ namespace Genode { 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; return Alloc_return::OK; diff --git a/repos/base/include/base/allocator.h b/repos/base/include/base/allocator.h index 03a4e6732..7bfbdab9d 100644 --- a/repos/base/include/base/allocator.h +++ b/repos/base/include/base/allocator.h @@ -157,7 +157,7 @@ namespace Genode { * \param align alignment of new block specified * 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 diff --git a/repos/base/include/base/allocator_avl.h b/repos/base/include/base/allocator_avl.h index aa7182881..a8ff4b410 100644 --- a/repos/base/include/base/allocator_avl.h +++ b/repos/base/include/base/allocator_avl.h @@ -54,13 +54,19 @@ namespace Genode { * 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 align alignment (power of two) * \return true if block fits */ - inline bool _fits(size_t n, unsigned align = 1) { - return ((align_addr(addr(), align) >= addr()) && - _sum_in_range(align_addr(addr(), align), n) && - (align_addr(addr(), align) - addr() + n <= avail())); } + inline bool _fits(size_t n, unsigned align, + addr_t from, addr_t to) + { + 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: @@ -110,7 +116,8 @@ namespace Genode { /** * 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 @@ -215,7 +222,7 @@ namespace Genode { int add_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); void free(void *addr); size_t avail(); diff --git a/repos/base/include/base/sync_allocator.h b/repos/base/include/base/sync_allocator.h index 8042fe218..640bb441c 100644 --- a/repos/base/include/base/sync_allocator.h +++ b/repos/base/include/base/sync_allocator.h @@ -220,10 +220,10 @@ namespace Genode { 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); - 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) diff --git a/repos/base/src/base/allocator/allocator_avl.cc b/repos/base/src/base/allocator/allocator_avl.cc index 26d171808..0c4fdf623 100644 --- a/repos/base/src/base/allocator/allocator_avl.cc +++ b/repos/base/src/base/allocator/allocator_avl.cc @@ -28,7 +28,8 @@ inline void *operator new(size_t, void *at) { return at; } **************************/ 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 */ 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) 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) - 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; 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 */ 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) { _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 */ - 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 */ _cut_from_block(b, new_addr, size, dst1, dst2); diff --git a/repos/base/src/core/core_mem_alloc.cc b/repos/base/src/core/core_mem_alloc.cc index c6f87284b..9088fde92 100644 --- a/repos/base/src/core/core_mem_alloc.cc +++ b/repos/base/src/core/core_mem_alloc.cc @@ -36,7 +36,7 @@ void * Core_mem_allocator::Mapped_avl_allocator::map_addr(void * addr) 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(); void *phys_addr = 0; @@ -44,7 +44,7 @@ Core_mem_allocator::Mapped_mem_allocator::alloc_aligned(size_t size, void **out_ /* allocate physical pages */ Alloc_return ret1 = _phys_alloc->alloc_aligned(page_rounded_size, - &phys_addr, align); + &phys_addr, align, from, to); if (!ret1.is_ok()) { PERR("Could not allocate physical memory region of size %zu\n", page_rounded_size); diff --git a/repos/base/src/core/include/core_mem_alloc.h b/repos/base/src/core/include/core_mem_alloc.h index 9cfa453e1..6be0b3a0c 100644 --- a/repos/base/src/core/include/core_mem_alloc.h +++ b/repos/base/src/core/include/core_mem_alloc.h @@ -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 remove_range(addr_t base, size_t size) { return -1; } 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) { return Alloc_return::RANGE_CONFLICT; } 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) { 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); - return _mem_alloc.alloc_aligned(size, out_addr, align); + return _mem_alloc.alloc_aligned(size, out_addr, align, from, to); } void free(void *addr) diff --git a/repos/os/include/os/packet_allocator.h b/repos/os/include/os/packet_allocator.h index 7b8a8ca58..f7663e16d 100644 --- a/repos/os/include/os/packet_allocator.h +++ b/repos/os/include/os/packet_allocator.h @@ -90,9 +90,12 @@ class Genode::Packet_allocator : public Genode::Range_allocator 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 - : Alloc_return::RANGE_CONFLICT; } + : Alloc_return::RANGE_CONFLICT; + } bool alloc(size_t size, void **out_addr) {