From e380d0da95e4512123bd70b4e7bbc1b3cc503d70 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sat, 5 Apr 2025 22:26:25 +0200 Subject: [PATCH] base: use 'Allocation' interface for mem alloc This patch converts the memory-allocator interfaces ('Allocator', 'Range_allocator') and their implementations ('Heap', 'Sliced heap', 'Slab', 'Allocator_avl', 'Synced_allocator') to the new 'Allocation' utility. The new interface resides at base/memory.h whereas the traditional allocators implement the new interface. Down the road, the traditional allocators can successively be decoupled from the traditional 'Allocator' and 'Range_allocator' interfaces. Issue #5502 Issue #5245 --- .../src/core/io_mem_session_support.cc | 7 +- repos/base-fiasco/src/core/platform.cc | 10 ++- .../src/core/io_mem_session_support.cc | 10 +-- .../src/core/irq_session_component.cc | 10 ++- repos/base-foc/src/core/platform.cc | 66 +++++++-------- repos/base-foc/src/core/rpc_cap_factory.cc | 6 +- repos/base-hw/src/bootstrap/platform.cc | 4 +- repos/base-hw/src/core/core_region_map.cc | 20 ++--- repos/base-hw/src/core/cpu_thread_allocator.h | 22 +++-- repos/base-hw/src/core/guest_memory.h | 11 ++- .../base-hw/src/core/irq_session_component.cc | 10 ++- repos/base-hw/src/core/kernel/thread.cc | 18 +++-- repos/base-hw/src/core/platform.cc | 81 ++++++++----------- repos/base-hw/src/core/platform_pd.cc | 16 ++-- repos/base-hw/src/core/platform_thread.cc | 9 ++- .../base-hw/src/core/ram_dataspace_support.cc | 44 +++++----- repos/base-hw/src/core/rpc_cap_factory.h | 7 +- repos/base-linux/src/core/include/platform.h | 8 +- .../base-linux/src/lib/lx_hybrid/lx_hybrid.cc | 5 +- repos/base-linux/src/test/lx_rmap/main.cc | 4 +- repos/base-nova/src/core/core_region_map.cc | 6 +- .../src/core/irq_session_component.cc | 22 ++--- repos/base-nova/src/core/platform.cc | 64 ++++++++------- .../src/core/ram_dataspace_support.cc | 6 +- repos/base-okl4/src/core/core_region_map.cc | 9 ++- .../src/core/irq_session_component.cc | 10 ++- repos/base-okl4/src/core/platform.cc | 43 +++++----- .../src/core/ram_dataspace_support.cc | 51 +++++------- .../src/core/io_mem_session_support.cc | 5 +- .../src/core/irq_session_component.cc | 10 ++- repos/base-pistachio/src/core/platform.cc | 10 ++- repos/base-sel4/src/core/core_region_map.cc | 9 ++- repos/base-sel4/src/core/include/platform.h | 4 +- .../src/core/include/untyped_memory.h | 7 +- .../src/core/irq_session_component.cc | 10 ++- repos/base-sel4/src/core/platform.cc | 34 ++++---- repos/base-sel4/src/core/platform_thread.cc | 17 ++-- .../src/core/ram_dataspace_support.cc | 5 +- repos/base/include/base/allocator.h | 49 +++-------- repos/base/include/base/allocator_avl.h | 13 ++- repos/base/include/base/heap.h | 31 +++++-- repos/base/include/base/memory.h | 62 ++++++++++++++ repos/base/include/base/slab.h | 14 +++- repos/base/include/base/synced_allocator.h | 13 ++- repos/base/lib/symbols/ld | 19 ++++- repos/base/src/core/core_mem_alloc.cc | 17 ++-- .../src/core/include/accounted_core_ram.h | 10 ++- repos/base/src/core/include/core_mem_alloc.h | 28 +++++-- .../src/core/include/synced_range_allocator.h | 13 ++- .../base/src/core/io_mem_session_component.cc | 16 +++- repos/base/src/core/ram_dataspace_factory.cc | 42 ++++------ repos/base/src/core/region_map_component.cc | 14 +++- .../spec/x86/io_port_session_component.cc | 8 +- repos/base/src/core/stack_area.cc | 10 ++- repos/base/src/core/vm_session_common.cc | 8 +- repos/base/src/lib/base/allocator_avl.cc | 11 +-- repos/base/src/lib/base/heap.cc | 20 +++-- repos/base/src/lib/base/slab.cc | 7 +- repos/base/src/lib/base/sliced_heap.cc | 7 +- repos/base/src/lib/cxx/emutls.cc | 7 +- repos/base/src/lib/cxx/malloc_free.cc | 7 +- repos/base/src/lib/ldso/include/region_map.h | 15 +++- repos/base/src/test/new_delete/main.cc | 21 +++-- repos/dde_bsd/src/lib/audio/pci.cc | 6 +- .../dde_ipxe/src/lib/dde_ipxe/dde_support.cc | 39 ++++++--- repos/dde_linux/src/lib/lx_kit/memory.cc | 12 ++- .../dde_rump/src/include/util/allocator_fap.h | 36 +++++---- repos/demo/src/lib/mini_c/malloc_free.cc | 10 +-- repos/gems/include/gems/cached_font.h | 12 +-- repos/gems/include/gems/dynamic_array.h | 9 ++- repos/libports/include/libc/allocator.h | 7 +- repos/libports/ports/sanitizer.hash | 2 +- repos/libports/src/lib/gcov/libc/libc.cc | 4 +- repos/libports/src/lib/libc/libc_mem_alloc.cc | 26 +++--- repos/libports/src/lib/libc/malloc.cc | 9 ++- repos/libports/src/lib/libdrm/ioctl_iris.cc | 7 +- repos/libports/src/lib/libdrm/ioctl_lima.cc | 7 +- repos/libports/src/lib/lwip/sys_arch.cc | 5 +- .../src/lib/sanitizer/sanitizer.patch | 6 +- .../src/lib/vfs/legacy_lwip/sys_arch.cc | 5 +- repos/os/include/nic/packet_allocator.h | 28 +++---- repos/os/include/os/packet_allocator.h | 8 +- repos/os/include/os/packet_stream.h | 14 ++-- repos/os/src/driver/acpi/memory.h | 5 +- .../os/src/driver/gpu/intel/ppgtt_allocator.h | 15 +++- repos/os/src/driver/platform/dma_allocator.cc | 10 ++- repos/os/src/test/fb_bench/main.cc | 7 +- repos/os/src/test/ram_fs_chunk/main.cc | 14 ++-- repos/os/src/test/slab/main.cc | 22 ++--- .../pc/expanding_page_table_allocator.h | 6 +- repos/ports/src/virtualbox6/sup_gmm.cc | 7 +- 91 files changed, 847 insertions(+), 643 deletions(-) create mode 100644 repos/base/include/base/memory.h diff --git a/repos/base-fiasco/src/core/io_mem_session_support.cc b/repos/base-fiasco/src/core/io_mem_session_support.cc index e55aa04ae3..58dfc16eda 100644 --- a/repos/base-fiasco/src/core/io_mem_session_support.cc +++ b/repos/base-fiasco/src/core/io_mem_session_support.cc @@ -96,13 +96,14 @@ Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local( return platform().region_alloc().alloc_aligned(size, align).convert( - [&] (void *ptr) { - addr_t const core_local_base = (addr_t)ptr; + [&] (Range_allocator::Allocation &core_local) { + addr_t const core_local_base = (addr_t)core_local.ptr; map_io_region(phys_base, core_local_base, size); + core_local.deallocate = false; return Map_local_result { .core_local_addr = core_local_base, .success = true }; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("core-local mapping of memory-mapped I/O range failed"); return Map_local_result(); }); diff --git a/repos/base-fiasco/src/core/platform.cc b/repos/base-fiasco/src/core/platform.cc index 3ae52fbeac..75434a71b4 100644 --- a/repos/base-fiasco/src/core/platform.cc +++ b/repos/base-fiasco/src/core/platform.cc @@ -444,11 +444,11 @@ Core::Platform::Platform() size_t const size = 1 << get_page_size_log2(); ram_alloc().alloc_aligned(size, get_page_size_log2()).with_result( - [&] (void *phys_ptr) { + [&] (Range_allocator::Allocation &phys) { /* core-local memory is one-to-one mapped physical RAM */ - addr_t const phys_addr = reinterpret_cast(phys_ptr); - void * const core_local_ptr = phys_ptr; + addr_t const phys_addr = reinterpret_cast(phys.ptr); + void * const core_local_ptr = phys.ptr; region_alloc().remove_range((addr_t)core_local_ptr, size); memset(core_local_ptr, 0, size); @@ -456,8 +456,10 @@ Core::Platform::Platform() new (core_mem_alloc()) Rom_module(_rom_fs, rom_name, phys_addr, size); + + phys.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { warning("failed to export ", rom_name, " as ROM module"); } ); }; diff --git a/repos/base-foc/src/core/io_mem_session_support.cc b/repos/base-foc/src/core/io_mem_session_support.cc index 778ffb7e69..358f02d6e9 100644 --- a/repos/base-foc/src/core/io_mem_session_support.cc +++ b/repos/base-foc/src/core/io_mem_session_support.cc @@ -41,17 +41,17 @@ Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local( /* find appropriate region and map it locally */ return platform().region_alloc().alloc_aligned(size, (unsigned)alignment).convert( - [&] (void *local_base) { - if (!map_local_io(base, (addr_t)local_base, size >> get_page_size_log2())) { + [&] (Range_allocator::Allocation &local) { + if (!map_local_io(base, (addr_t)local.ptr, size >> get_page_size_log2())) { error("map_local_io failed ", Hex_range(base, size)); - platform().region_alloc().free(local_base, base); return Map_local_result(); } - return Map_local_result { .core_local_addr = addr_t(local_base), + local.deallocate = false; + return Map_local_result { .core_local_addr = addr_t(local.ptr), .success = true }; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("allocation of virtual memory for local I/O mapping failed"); return Map_local_result(); }); } diff --git a/repos/base-foc/src/core/irq_session_component.cc b/repos/base-foc/src/core/irq_session_component.cc index e5cac00253..1f72ef6ce4 100644 --- a/repos/base-foc/src/core/irq_session_component.cc +++ b/repos/base-foc/src/core/irq_session_component.cc @@ -203,10 +203,12 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, } msi_alloc().set(_irq_number, 1); } else { - if (irq_alloc.alloc_addr(1, _irq_number).failed()) { - error("unavailable IRQ ", _irq_number, " requested"); - throw Service_denied(); - } + irq_alloc.alloc_addr(1, _irq_number).with_result( + [&] (Range_allocator::Allocation &irq_number) { + irq_number.deallocate = false; }, + [&] (Alloc_error) { + error("unavailable interrupt ", _irq_number, " requested"); + throw Service_denied(); }); } if (_irq_object.associate(_irq_number, msi, irq_args.trigger(), diff --git a/repos/base-foc/src/core/platform.cc b/repos/base-foc/src/core/platform.cc index e56a0135e9..7b19c02d41 100644 --- a/repos/base-foc/src/core/platform.cc +++ b/repos/base-foc/src/core/platform.cc @@ -381,31 +381,31 @@ static void add_acpi_rsdp(auto ®ion_alloc, auto &xml) auto offset = desc[i].start() & 0xffful; auto pages = align_addr(offset + desc[i].size(), 12) >> 12; - region_alloc.alloc_aligned(pages * 4096, 12).with_result([&] (void *core_local_ptr) { + region_alloc.alloc_aligned(pages * 4096, 12).with_result( + [&] (Range_allocator::Allocation &core_local) { - if (!map_local_io(desc[i].start(), (addr_t)core_local_ptr, pages)) - return; + if (!map_local_io(desc[i].start(), (addr_t)core_local.ptr, pages)) + return; - Byte_range_ptr const ptr((char *)(addr_t(core_local_ptr) + offset), - pages * 4096 - offset); - auto const rsdp = Acpi_rsdp(ptr); + Byte_range_ptr const ptr((char *)(addr_t(core_local.ptr) + offset), + pages * 4096 - offset); + auto const rsdp = Acpi_rsdp(ptr); - if (!rsdp.valid()) - return; + if (!rsdp.valid()) + return; - xml.node("acpi", [&] { - xml.attribute("revision", rsdp.read()); - if (rsdp.read()) - xml.attribute("rsdt", String<32>(Hex(rsdp.read()))); - if (rsdp.read()) - xml.attribute("xsdt", String<32>(Hex(rsdp.read()))); - }); + xml.node("acpi", [&] { + xml.attribute("revision", rsdp.read()); + if (rsdp.read()) + xml.attribute("rsdt", String<32>(Hex(rsdp.read()))); + if (rsdp.read()) + xml.attribute("xsdt", String<32>(Hex(rsdp.read()))); + }); - unmap_local(addr_t(core_local_ptr), pages); - region_alloc.free(core_local_ptr); + unmap_local(addr_t(core_local.ptr), pages); - pages = 0; - }, [&] (Range_allocator::Alloc_error) { }); + pages = 0; + }, [&] (Alloc_error) { }); if (!pages) return; @@ -545,35 +545,31 @@ Core::Platform::Platform() size_t const bytes = pages << get_page_size_log2(); ram_alloc().alloc_aligned(bytes, align).with_result( - [&] (void *phys_ptr) { - - addr_t const phys_addr = reinterpret_cast(phys_ptr); + [&] (Range_allocator::Allocation &phys) { + addr_t const phys_addr = reinterpret_cast(phys.ptr); region_alloc().alloc_aligned(bytes, align).with_result( - [&] (void *core_local_ptr) { + [&] (Range_allocator::Allocation &core_local) { - if (!map_local(phys_addr, (addr_t)core_local_ptr, pages)) { + if (!map_local(phys_addr, (addr_t)core_local.ptr, pages)) { warning("map_local failed while exporting ", rom_name, " as ROM module"); - ram_alloc().free(phys_ptr, bytes); - region_alloc().free(core_local_ptr, bytes); - return; - } + return; } - memset(core_local_ptr, 0, bytes); - content_fn((char *)core_local_ptr, bytes); + memset(core_local.ptr, 0, bytes); + content_fn((char *)core_local.ptr, bytes); new (core_mem_alloc()) Rom_module(_rom_fs, rom_name, phys_addr, bytes); + + phys.deallocate = core_local.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { warning("failed allocate virtual memory to export ", - rom_name, " as ROM module"); - ram_alloc().free(phys_ptr, bytes); - } + rom_name, " as ROM module"); } ); }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { warning("failed to export ", rom_name, " as ROM module"); } ); }; diff --git a/repos/base-foc/src/core/rpc_cap_factory.cc b/repos/base-foc/src/core/rpc_cap_factory.cc index caf7a226a9..1bc541a9f5 100644 --- a/repos/base-foc/src/core/rpc_cap_factory.cc +++ b/repos/base-foc/src/core/rpc_cap_factory.cc @@ -200,10 +200,10 @@ Cap_id_allocator::id_t Cap_id_allocator::alloc() return _id_alloc.try_alloc(CAP_ID_OFFSET).convert( - [&] (void *id) -> id_t { - return (addr_t)id & ID_MASK; }, + [&] (Range_allocator::Allocation &id) -> id_t { + id.deallocate = false; return (addr_t)id.ptr & ID_MASK; }, - [&] (Range_allocator::Alloc_error) -> id_t { + [&] (Alloc_error) -> id_t { throw Out_of_ids(); }); } diff --git a/repos/base-hw/src/bootstrap/platform.cc b/repos/base-hw/src/bootstrap/platform.cc index 93c17f91fb..76f5019afa 100644 --- a/repos/base-hw/src/bootstrap/platform.cc +++ b/repos/base-hw/src/bootstrap/platform.cc @@ -36,8 +36,8 @@ void * Platform::Ram_allocator::alloc_aligned(size_t size, unsigned align) return Base::alloc_aligned(Hw::round_page(size), align).convert( - [&] (void *ptr) { return ptr; }, - [&] (Ram_allocator::Alloc_error e) -> void * + [&] (Range_allocator::Allocation &a) { a.deallocate = false; return a.ptr; }, + [&] (Alloc_error e) -> void * { error("bootstrap RAM allocation failed, error=", e); assert(false); diff --git a/repos/base-hw/src/core/core_region_map.cc b/repos/base-hw/src/core/core_region_map.cc index f56d302efb..84735efc4f 100644 --- a/repos/base-hw/src/core/core_region_map.cc +++ b/repos/base-hw/src/core/core_region_map.cc @@ -26,6 +26,8 @@ using namespace Core; Region_map::Attach_result Core_region_map::attach(Dataspace_capability ds_cap, Attr const &attr) { + using Virt_allocation = Range_allocator::Allocation; + return _ep.apply(ds_cap, [&] (Dataspace_component *ds_ptr) -> Attach_result { if (!ds_ptr) @@ -43,7 +45,7 @@ Core_region_map::attach(Dataspace_capability ds_cap, Attr const &attr) unsigned const align = get_page_size_log2(); /* allocate range in core's virtual address space */ - Allocator::Alloc_result const virt = + Allocator::Alloc_result virt = platform().region_alloc().alloc_aligned(page_rounded_size, align); if (virt.failed()) { @@ -68,15 +70,15 @@ Core_region_map::attach(Dataspace_capability ds_cap, Attr const &attr) return virt.convert( - [&] (void *virt_addr) -> Attach_result { - if (map_local(ds.phys_addr(), (addr_t)virt_addr, num_pages, flags)) - return Range { .start = addr_t(virt_addr), - .num_bytes = page_rounded_size }; + [&] (Virt_allocation &a) -> Attach_result { + if (!map_local(ds.phys_addr(), (addr_t)a.ptr, num_pages, flags)) + return Attach_error::REGION_CONFLICT; - platform().region_alloc().free(virt_addr, page_rounded_size); - return Attach_error::REGION_CONFLICT; }, - - [&] (Allocator::Alloc_error) { + a.deallocate = false; + return Range { .start = addr_t(a.ptr), + .num_bytes = page_rounded_size }; + }, + [&] (Alloc_error) { return Attach_error::REGION_CONFLICT; }); }); } diff --git a/repos/base-hw/src/core/cpu_thread_allocator.h b/repos/base-hw/src/core/cpu_thread_allocator.h index 885ef1b62d..ebeb0aa9c8 100644 --- a/repos/base-hw/src/core/cpu_thread_allocator.h +++ b/repos/base-hw/src/core/cpu_thread_allocator.h @@ -52,12 +52,24 @@ class Core::Cpu_thread_allocator : public Allocator Cpu_thread_allocator(Allocator &alloc) : _alloc(alloc) { } - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ - Alloc_result try_alloc(size_t size) override { - return _alloc.alloc(size); } + Alloc_result try_alloc(size_t size) override + { + return _alloc.try_alloc(size).convert( + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; return { *this, a }; }, + [&] (Alloc_error e) { return e; }); + } + + void _free(Allocation &a) override { _alloc.free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ void free(void *addr, size_t size) override { _alloc.free(addr, size); } diff --git a/repos/base-hw/src/core/guest_memory.h b/repos/base-hw/src/core/guest_memory.h index 96eba0a7a5..8e4a416103 100644 --- a/repos/base-hw/src/core/guest_memory.h +++ b/repos/base-hw/src/core/guest_memory.h @@ -72,11 +72,11 @@ class Core::Guest_memory Attach_attr attr, auto const &map_fn) { - /* + /* * unsupported - deny otherwise arbitrary physical - * memory can be mapped to a VM + * memory can be mapped to a VM */ - if (dsc.managed()) + if (dsc.managed()) return Attach_result::INVALID_DS; if (guest_phys & 0xffful || attr.offset & 0xffful || @@ -97,11 +97,9 @@ class Core::Guest_memory attr.offset > dsc.size() - attr.size) return Attach_result::INVALID_DS; - using Alloc_error = Range_allocator::Alloc_error; - Attach_result const retval = _map.alloc_addr(attr.size, guest_phys).convert( - [&] (void *) { + [&] (Range_allocator::Allocation &allocation) { Rm_region::Attr const region_attr { @@ -131,6 +129,7 @@ class Core::Guest_memory /* inform dataspace about attachment */ dsc.attached_to(region); + allocation.deallocate = false; return Attach_result::OK; }, diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc index daa4a71c96..780a03d9fa 100644 --- a/repos/base-hw/src/core/irq_session_component.cc +++ b/repos/base-hw/src/core/irq_session_component.cc @@ -77,8 +77,10 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, } /* allocate interrupt */ - if (_irq_alloc.alloc_addr(1, _irq_number).failed()) { - error("unavailable interrupt ", _irq_number, " requested"); - throw Service_denied(); - } + _irq_alloc.alloc_addr(1, _irq_number).with_result( + [&] (Range_allocator::Allocation &irq_number) { + irq_number.deallocate = false; }, + [&] (Alloc_error) { + error("unavailable interrupt ", _irq_number, " requested"); + throw Service_denied(); }); } diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index f749276bed..0a6ecf1414 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -35,8 +35,9 @@ using namespace Kernel; Thread::Ipc_alloc_result Thread::_ipc_alloc_recv_caps(unsigned cap_count) { - using Allocator = Genode::Allocator; - using Result = Ipc_alloc_result; + using Allocator = Genode::Allocator; + using Result = Ipc_alloc_result; + using Alloc_error = Genode::Alloc_error; Allocator &slab = pd().platform_pd().capability_slab(); for (unsigned i = 0; i < cap_count; i++) { @@ -46,11 +47,12 @@ Thread::Ipc_alloc_result Thread::_ipc_alloc_recv_caps(unsigned cap_count) Result const result = slab.try_alloc(sizeof(Object_identity_reference)).convert( - [&] (void *ptr) { - _obj_id_ref_ptr[i] = ptr; - return Result::OK; }, - - [&] (Allocator::Alloc_error e) { + [&] (Genode::Memory::Allocation &a) { + _obj_id_ref_ptr[i] = a.ptr; + a.deallocate = false; + return Result::OK; + }, + [&] (Alloc_error e) { /* * Conditions other than DENIED cannot happen because the slab @@ -58,7 +60,7 @@ Thread::Ipc_alloc_result Thread::_ipc_alloc_recv_caps(unsigned cap_count) * expanded by the client as response to the EXHAUSTED return * value. */ - if (e != Allocator::Alloc_error::DENIED) + if (e != Alloc_error::DENIED) Genode::raw("unexpected recv_caps allocation failure"); return Result::EXHAUSTED; diff --git a/repos/base-hw/src/core/platform.cc b/repos/base-hw/src/core/platform.cc index 5e2cf3a982..dcc2feec09 100644 --- a/repos/base-hw/src/core/platform.cc +++ b/repos/base-hw/src/core/platform.cc @@ -116,41 +116,26 @@ void Platform::_init_platform_info() size_t const rom_size = pages << get_page_size_log2(); const char *rom_name = "platform_info"; - struct Guard - { - Range_allocator &phys_alloc; - Range_allocator &virt_alloc; + Range_allocator::Result phys = ram_alloc().try_alloc(get_page_size()); + Range_allocator::Result virt = region_alloc().try_alloc(rom_size); - struct { - void *phys_ptr = nullptr; - void *virt_ptr = nullptr; - }; + if (phys.failed()) + error("could not setup platform_info ROM - RAM allocation error"); + if (virt.failed()) + error("could not setup platform_info ROM - region allocation error"); - Guard(Range_allocator &phys_alloc, Range_allocator &virt_alloc) - : phys_alloc(phys_alloc), virt_alloc(virt_alloc) { } - - ~Guard() - { - if (phys_ptr) phys_alloc.free(phys_ptr); - if (virt_ptr) virt_alloc.free(phys_ptr); - } - } guard { ram_alloc(), region_alloc() }; - - ram_alloc().try_alloc(get_page_size()).with_result( - [&] (void *ptr) { guard.phys_ptr = ptr; }, - [&] (Allocator::Alloc_error) { - error("could not setup platform_info ROM - RAM allocation error"); }); - - region_alloc().try_alloc(rom_size).with_result( - [&] (void *ptr) { guard.virt_ptr = ptr; }, - [&] (Allocator::Alloc_error) { - error("could not setup platform_info ROM - region allocation error"); }); - - if (!guard.phys_ptr || !guard.virt_ptr) + if (phys.failed() || virt.failed()) return; - addr_t const phys_addr = reinterpret_cast(guard.phys_ptr); - addr_t const virt_addr = reinterpret_cast(guard.virt_ptr); + auto start_addr = [&] (Range_allocator::Result &range) + { + return range.convert( + [&] (Range_allocator::Allocation &a) { return addr_t(a.ptr); }, + [] (Alloc_error) { return 0UL; }); + }; + + addr_t const phys_addr = start_addr(phys); + addr_t const virt_addr = start_addr(virt); if (!map_local(phys_addr, virt_addr, pages, Hw::PAGE_FLAGS_KERN_DATA)) { error("could not setup platform_info ROM - map error"); @@ -182,7 +167,8 @@ void Platform::_init_platform_info() new (core_mem_alloc()) Rom_module(_rom_fs, rom_name, phys_addr, rom_size); /* keep phys allocation but let guard revert virt allocation */ - guard.phys_ptr = nullptr; + phys.with_result([&] (auto &allocation) { allocation.deallocate = false; }, + [] (Alloc_error) { }); } @@ -226,32 +212,31 @@ Platform::Platform() /* core log as ROM module */ { - unsigned const pages = 1; - size_t const log_size = pages << get_page_size_log2(); - unsigned const align = get_page_size_log2(); + unsigned const pages = 1; + size_t const log_size = pages << get_page_size_log2(); + unsigned const align = get_page_size_log2(); + + using Allocation = Range_allocator::Allocation; ram_alloc().alloc_aligned(log_size, align).with_result( - - [&] (void *phys) { - addr_t const phys_addr = reinterpret_cast(phys); - + [&] (Allocation &phys) { region_alloc().alloc_aligned(log_size, align). with_result( + [&] (Allocation &virt) { + addr_t const phys_addr = addr_t(phys.ptr); + addr_t const virt_addr = addr_t(virt.ptr); - [&] (void *ptr) { - - map_local(phys_addr, (addr_t)ptr, pages); - memset(ptr, 0, log_size); + map_local(phys_addr, virt_addr, pages); + memset(virt.ptr, 0, log_size); new (core_mem_alloc()) Rom_module(_rom_fs, "core_log", phys_addr, log_size); - init_core_log(Core_log_range { (addr_t)ptr, log_size } ); + init_core_log(Core_log_range { virt_addr, log_size } ); + phys.deallocate = virt.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { /* ignored */ } - ); + [&] (Alloc_error) { }); }, - [&] (Range_allocator::Alloc_error) { } - ); + [&] (Alloc_error) { }); } unsigned const cpus = _boot_info().cpus; diff --git a/repos/base-hw/src/core/platform_pd.cc b/repos/base-hw/src/core/platform_pd.cc index 97d3e93977..c2f612739b 100644 --- a/repos/base-hw/src/core/platform_pd.cc +++ b/repos/base-hw/src/core/platform_pd.cc @@ -41,8 +41,8 @@ void *Hw::Address_space::_table_alloc() return _cma().alloc_aligned(sizeof(Page_table), align).convert( - [&] (void *ptr) { - return ptr; }, + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; return a.ptr; }, [&] (Range_allocator::Alloc_result) -> void * { /* XXX distinguish error conditions */ @@ -147,13 +147,11 @@ Cap_space::Cap_space() : _slab(nullptr, &_initial_sb) { } void Cap_space::upgrade_slab(Allocator &alloc) { alloc.try_alloc(SLAB_SIZE).with_result( - - [&] (void *ptr) { - _slab.insert_sb(ptr); }, - - [&] (Allocator::Alloc_error error) { - Allocator::throw_alloc_error(error); - }); + [&] (Memory::Allocation &a) { + a.deallocate = false; + _slab.insert_sb(a.ptr); + }, + [&] (Alloc_error e) { raise(e); }); } diff --git a/repos/base-hw/src/core/platform_thread.cc b/repos/base-hw/src/core/platform_thread.cc index 843f516444..d96a81dc41 100644 --- a/repos/base-hw/src/core/platform_thread.cc +++ b/repos/base-hw/src/core/platform_thread.cc @@ -58,12 +58,13 @@ static addr_t _alloc_core_local_utcb(addr_t core_addr) */ return platform().ram_alloc().try_alloc(sizeof(Native_utcb)).convert( - [&] (void *utcb_phys) { - map_local((addr_t)utcb_phys, core_addr, + [&] (Range_allocator::Allocation &utcb_phys) { + map_local((addr_t)utcb_phys.ptr, core_addr, sizeof(Native_utcb) / get_page_size()); - return addr_t(utcb_phys); + utcb_phys.deallocate = false; + return addr_t(utcb_phys.ptr); }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("failed to allocate UTCB for core/kernel thread!"); return 0ul; }); diff --git a/repos/base-hw/src/core/ram_dataspace_support.cc b/repos/base-hw/src/core/ram_dataspace_support.cc index 9b245a43a2..19523bdc14 100644 --- a/repos/base-hw/src/core/ram_dataspace_support.cc +++ b/repos/base-hw/src/core/ram_dataspace_support.cc @@ -12,6 +12,9 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ +#include + /* core includes */ #include #include @@ -29,28 +32,23 @@ void Ram_dataspace_factory::_revoke_ram_ds(Dataspace_component &) { } void Ram_dataspace_factory::_clear_ds (Dataspace_component &ds) { + using Virt_allocation = Range_allocator::Allocation; + size_t page_rounded_size = (ds.size() + get_page_size() - 1) & get_page_mask(); - struct Guard - { - Range_allocator &virt_alloc; - struct { void *virt_ptr = nullptr; }; - - Guard(Range_allocator &virt_alloc) : virt_alloc(virt_alloc) { } - - ~Guard() { if (virt_ptr) virt_alloc.free(virt_ptr); } - - } guard(platform().region_alloc()); - /* allocate range in core's virtual address space */ - platform().region_alloc().try_alloc(page_rounded_size).with_result( - [&] (void *ptr) { guard.virt_ptr = ptr; }, - [&] (Range_allocator::Alloc_error e) { - error("could not allocate virtual address range in core of size ", - page_rounded_size, ", error=", e); }); + Range_allocator::Result const virt = + platform().region_alloc().try_alloc(page_rounded_size); - if (!guard.virt_ptr) + if (virt.failed()) { + error("clear_ds could not allocate virtual address range of size ", + page_rounded_size); return; + } + + addr_t const virt_addr = virt.convert( + [&] (Virt_allocation const &a) { return addr_t(a.ptr); }, + [] (Alloc_error) { return 0UL; }); /* * Map and clear dataspaces in chucks of 128MiB max to prevent large @@ -62,22 +60,22 @@ void Ram_dataspace_factory::_clear_ds (Dataspace_component &ds) addr_t chunk_phys_addr = ds.phys_addr(); while (size_remaining) { - size_t chunk_size = min(size_remaining, max_chunk_size); - size_t num_pages = chunk_size >> get_page_size_log2(); + size_t const chunk_size = min(size_remaining, max_chunk_size); + size_t const num_pages = chunk_size >> get_page_size_log2(); /* map the dataspace's physical pages to corresponding virtual addresses */ - if (!map_local(chunk_phys_addr, (addr_t)guard.virt_ptr, num_pages)) { + if (!map_local(chunk_phys_addr, virt_addr, num_pages)) { error("core-local memory mapping failed"); return; } /* dependent on the architecture, cache maintainance might be necessary */ - Cpu::clear_memory_region((addr_t)guard.virt_ptr, chunk_size, + Cpu::clear_memory_region(virt_addr, chunk_size, ds.cacheability() != CACHED); /* unmap dataspace from core */ - if (!unmap_local((addr_t)guard.virt_ptr, num_pages)) - error("could not unmap core-local address range at ", guard.virt_ptr); + if (!unmap_local(virt_addr, num_pages)) + error("could not unmap core-local address range at ", Hex(virt_addr)); size_remaining -= chunk_size; chunk_phys_addr += chunk_size; diff --git a/repos/base-hw/src/core/rpc_cap_factory.h b/repos/base-hw/src/core/rpc_cap_factory.h index 078ecfc6a1..c41dfa1b86 100644 --- a/repos/base-hw/src/core/rpc_cap_factory.h +++ b/repos/base-hw/src/core/rpc_cap_factory.h @@ -86,10 +86,10 @@ class Core::Rpc_cap_factory return _slab.try_alloc(sizeof(Kobject)).convert( - [&] (void *ptr) { + [&] (Memory::Allocation &a) { /* create kernel object */ - Kobject &obj = *construct_at(ptr, ep); + Kobject &obj = *construct_at(a.ptr, ep); if (!obj.cap.valid()) { raw("Invalid entrypoint ", (addr_t)Capability_space::capid(ep), @@ -100,9 +100,10 @@ class Core::Rpc_cap_factory /* store it in the list and return result */ _list.insert(&obj); + a.deallocate = false; return obj.cap; }, - [&] (Allocator::Alloc_error) -> Native_capability { + [&] (Alloc_error) -> Native_capability { /* XXX distinguish error conditions */ throw Allocator::Out_of_memory(); }); diff --git a/repos/base-linux/src/core/include/platform.h b/repos/base-linux/src/core/include/platform.h index 4a24cd5c37..88671d867a 100644 --- a/repos/base-linux/src/core/include/platform.h +++ b/repos/base-linux/src/core/include/platform.h @@ -64,6 +64,7 @@ class Core::Platform : public Platform_generic struct Dummy_allocator : Range_allocator { + void _free(Allocation &) override { ASSERT_NEVER_CALLED; } void free(void *, size_t) override { ASSERT_NEVER_CALLED; } bool need_size_for_free() const override { ASSERT_NEVER_CALLED; } size_t consumed() const override { ASSERT_NEVER_CALLED; } @@ -87,9 +88,10 @@ class Core::Platform : public Platform_generic */ struct Pseudo_ram_allocator : Range_allocator { - Alloc_result try_alloc(size_t) override { return nullptr; } - Alloc_result alloc_aligned(size_t, unsigned, Range) override { return nullptr; } - Alloc_result alloc_addr(size_t, addr_t) override { return nullptr; } + void _free(Allocation &) override { } + Alloc_result try_alloc(size_t) override { return { *this, { } }; } + Alloc_result alloc_aligned(size_t, unsigned, Range) override { return { *this, { } }; } + Alloc_result alloc_addr(size_t, addr_t) override { return { *this, { } }; } Range_result add_range(addr_t, size_t) override { return Ok(); } Range_result remove_range(addr_t, size_t) override { return Ok(); } diff --git a/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc b/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc index e71b4a4a78..50b8d385f9 100644 --- a/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc +++ b/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc @@ -430,7 +430,10 @@ namespace { { using size_t = Genode::size_t; - Alloc_result try_alloc(size_t size) override { return malloc(size); } + Alloc_result try_alloc(size_t size) override { + return { *this, { malloc(size), size } }; } + + void _free(Allocation &a) override { ::free(a.ptr); } void free(void *addr, size_t) override { ::free(addr); } diff --git a/repos/base-linux/src/test/lx_rmap/main.cc b/repos/base-linux/src/test/lx_rmap/main.cc index 3307666426..ddd8baeb0a 100644 --- a/repos/base-linux/src/test/lx_rmap/main.cc +++ b/repos/base-linux/src/test/lx_rmap/main.cc @@ -52,8 +52,8 @@ Main::Main(Env &env) : heap(env.ram(), env.rm()) /* induce initial heap expansion to remove RM noise */ if (1) { heap.try_alloc(0x100000).with_result( - [&] (void *ptr) { heap.free(ptr, 0); }, - [&] (Allocator::Alloc_error) { }); + [&] (Heap::Allocation &) { /* deallocate == true */ }, + [&] (Alloc_error) { }); } addr_t beg((addr_t)&blob_beg); diff --git a/repos/base-nova/src/core/core_region_map.cc b/repos/base-nova/src/core/core_region_map.cc index 30a3551434..da11a8db98 100644 --- a/repos/base-nova/src/core/core_region_map.cc +++ b/repos/base-nova/src/core/core_region_map.cc @@ -28,6 +28,8 @@ using namespace Core; */ static inline void * alloc_region(Dataspace_component &ds, const size_t size) { + using Region_allocation = Range_allocator::Allocation; + /* * Allocate range in core's virtual address space * @@ -39,8 +41,8 @@ static inline void * alloc_region(Dataspace_component &ds, const size_t size) for (; align_log2 >= get_page_size_log2(); align_log2--) { platform().region_alloc().alloc_aligned(size, (unsigned)align_log2).with_result( - [&] (void *ptr) { virt_addr = ptr; }, - [&] (Allocator::Alloc_error) { }); + [&] (Region_allocation &a) { a.deallocate = false; virt_addr = a.ptr; }, + [&] (Alloc_error) { }); if (virt_addr) break; diff --git a/repos/base-nova/src/core/irq_session_component.cc b/repos/base-nova/src/core/irq_session_component.cc index 07db078422..570838bcb6 100644 --- a/repos/base-nova/src/core/irq_session_component.cc +++ b/repos/base-nova/src/core/irq_session_component.cc @@ -64,14 +64,16 @@ static void deassociate(addr_t irq_sel) static bool associate_msi(addr_t irq_sel, addr_t phys_mem, addr_t &msi_addr, addr_t &msi_data, Signal_context_capability sig_cap) { + using Virt_allocation = Range_allocator::Allocation; + if (!phys_mem) return irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(), Nova::Gsi_flags(), 0); return platform().region_alloc().alloc_aligned(4096, 12).convert( - [&] (void *virt_ptr) { + [&] (Virt_allocation &virt) { - addr_t const virt_addr = reinterpret_cast(virt_ptr); + addr_t const virt_addr = reinterpret_cast(virt.ptr); using Nova::Rights; using Nova::Utcb; @@ -81,20 +83,17 @@ static bool associate_msi(addr_t irq_sel, addr_t phys_mem, addr_t &msi_addr, Utcb &utcb = *reinterpret_cast(Thread::myself()->utcb()); - if (map_local_phys_to_virt(utcb, phys_crd, virt_crd, platform_specific().core_pd_sel())) { - platform().region_alloc().free(virt_ptr, 4096); + if (map_local_phys_to_virt(utcb, phys_crd, virt_crd, platform_specific().core_pd_sel())) return false; - } /* try to assign MSI to device */ bool res = irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(), Nova::Gsi_flags(), virt_addr); unmap_local(Nova::Mem_crd(virt_addr >> 12, 0, Rights(true, true, true))); - platform().region_alloc().free(virt_ptr, 4096); return res; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { return false; }); } @@ -231,10 +230,11 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, throw Service_denied(); } - if (irq_alloc.alloc_addr(1, irq_number).failed()) { - error("unavailable IRQ ", irq_number, " requested"); - throw Service_denied(); - } + irq_alloc.alloc_addr(1, irq_number).with_result( + [&] (Allocator::Allocation &a) { a.deallocate = false; }, + [&] (Alloc_error) { + error("unavailable IRQ ", irq_number, " requested"); + throw Service_denied(); }); _irq_number = (unsigned)irq_number; diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc index 64762f9c7b..d6a1a9a32d 100644 --- a/repos/base-nova/src/core/platform.cc +++ b/repos/base-nova/src/core/platform.cc @@ -77,23 +77,28 @@ extern unsigned _prog_img_beg, _prog_img_end; addr_t Core::Platform::_map_pages(addr_t const phys_addr, addr_t const pages, bool guard_page) { + using Region_allocation = Range_allocator::Allocation; + addr_t const size = pages << get_page_size_log2(); /* try to reserve contiguous virtual area */ return region_alloc().alloc_aligned(size + (guard_page ? get_page_size() : 0), get_page_size_log2()).convert( - [&] (void *core_local_ptr) { + [&] (Region_allocation &core_local) { - addr_t const core_local_addr = reinterpret_cast(core_local_ptr); + addr_t const core_local_addr = reinterpret_cast(core_local.ptr); int res = map_local(_core_pd_sel, *__main_thread_utcb, phys_addr, core_local_addr, pages, Nova::Rights(true, true, false), true); + if (res) + return 0UL; - return res ? 0 : core_local_addr; + core_local.deallocate = false; + return core_local_addr; }, - [&] (Allocator::Alloc_error) { + [&] (Alloc_error) { return 0UL; }); } @@ -619,17 +624,18 @@ Core::Platform::Platform() auto export_pages_as_rom_module = [&] (auto rom_name, size_t pages, auto content_fn) { + using Phys_allocation = Range_allocator::Allocation; + size_t const bytes = pages << get_page_size_log2(); ram_alloc().alloc_aligned(bytes, get_page_size_log2()).with_result( - [&] (void *phys_ptr) { + [&] (Phys_allocation &phys) { - addr_t const phys_addr = reinterpret_cast(phys_ptr); + addr_t const phys_addr = reinterpret_cast(phys.ptr); char * const core_local_ptr = (char *)_map_pages(phys_addr, pages); if (!core_local_ptr) { warning("failed to export ", rom_name, " as ROM module"); - ram_alloc().free(phys_ptr, bytes); return; } @@ -639,10 +645,12 @@ Core::Platform::Platform() new (core_mem_alloc()) Rom_module(_rom_fs, rom_name, phys_addr, bytes); + phys.deallocate = false; + /* leave the ROM backing store mapped within core */ }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { warning("failed to allocate physical memory for exporting ", rom_name, " as ROM module"); }); }; @@ -811,29 +819,29 @@ Core::Platform::Platform() unsigned index = first_index; for (unsigned i = 0; i < 32; i++) { - void * phys_ptr = nullptr; + using Phys_allocation = Range_allocator::Allocation; - ram_alloc().alloc_aligned(get_page_size(), get_page_size_log2()).with_result( - [&] (void *ptr) { phys_ptr = ptr; }, - [&] (Range_allocator::Alloc_error) { /* covered by nullptr test below */ }); + bool ok = ram_alloc().alloc_aligned(get_page_size(), + get_page_size_log2()).convert( + [&] (Phys_allocation &phys) { + addr_t phys_addr = reinterpret_cast(phys.ptr); + addr_t core_local_addr = _map_pages(phys_addr, 1); - if (phys_ptr == nullptr) + if (!core_local_addr) + return false; + + Cap_range &range = *reinterpret_cast(core_local_addr); + construct_at(&range, index); + + cap_map().insert(range); + index = (unsigned)(range.base() + range.elements()); + phys.deallocate = false; + return true; + }, + [&] (Alloc_error) { log("Alloc_error"); return false; }); + + if (!ok) break; - - addr_t phys_addr = reinterpret_cast(phys_ptr); - addr_t core_local_addr = _map_pages(phys_addr, 1); - - if (!core_local_addr) { - ram_alloc().free(phys_ptr); - break; - } - - Cap_range &range = *reinterpret_cast(core_local_addr); - construct_at(&range, index); - - cap_map().insert(range); - - index = (unsigned)(range.base() + range.elements()); } _max_caps = index - first_index; diff --git a/repos/base-nova/src/core/ram_dataspace_support.cc b/repos/base-nova/src/core/ram_dataspace_support.cc index fbc0cb1c62..cae47db8a2 100644 --- a/repos/base-nova/src/core/ram_dataspace_support.cc +++ b/repos/base-nova/src/core/ram_dataspace_support.cc @@ -31,6 +31,8 @@ void Ram_dataspace_factory::_revoke_ram_ds(Dataspace_component &) { } static inline void * alloc_region(Dataspace_component &ds, const size_t size) { + using Region_allocation = Range_allocator::Allocation; + /* * Allocate range in core's virtual address space * @@ -42,8 +44,8 @@ static inline void * alloc_region(Dataspace_component &ds, const size_t size) for (; align_log2 >= get_page_size_log2(); align_log2--) { platform().region_alloc().alloc_aligned(size, (unsigned)align_log2).with_result( - [&] (void *ptr) { virt_addr = ptr; }, - [&] (Range_allocator::Alloc_error) { /* try next iteration */ } + [&] (Region_allocation &a) { a.deallocate = false; virt_addr = a.ptr; }, + [&] (Alloc_error) { /* try next iteration */ } ); if (virt_addr) return virt_addr; diff --git a/repos/base-okl4/src/core/core_region_map.cc b/repos/base-okl4/src/core/core_region_map.cc index 81b17c2f20..01f407a15b 100644 --- a/repos/base-okl4/src/core/core_region_map.cc +++ b/repos/base-okl4/src/core/core_region_map.cc @@ -38,17 +38,18 @@ Core_region_map::attach(Dataspace_capability ds_cap, Attr const &attr) Range_allocator &virt_alloc = platform().region_alloc(); return virt_alloc.try_alloc(page_rounded_size).convert( - [&] (void *virt_addr) -> Attach_result { + [&] (Range_allocator::Allocation &virt) -> Attach_result { /* map the dataspace's physical pages to virtual memory */ unsigned num_pages = page_rounded_size >> get_page_size_log2(); - if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages)) + if (!map_local(ds->phys_addr(), (addr_t)virt.ptr, num_pages)) return Attach_error::INVALID_DATASPACE; - return Range { .start = addr_t(virt_addr), .num_bytes = page_rounded_size }; + virt.deallocate = false; + return Range { .start = addr_t(virt.ptr), .num_bytes = page_rounded_size }; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("could not allocate virtual address range in core of size ", page_rounded_size); return Attach_error::REGION_CONFLICT; diff --git a/repos/base-okl4/src/core/irq_session_component.cc b/repos/base-okl4/src/core/irq_session_component.cc index e8e2bce9e8..03ac94dccf 100644 --- a/repos/base-okl4/src/core/irq_session_component.cc +++ b/repos/base-okl4/src/core/irq_session_component.cc @@ -140,10 +140,12 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, if (msi) throw Service_denied(); - if (irq_alloc.alloc_addr(1, _irq_number).failed()) { - error("unavailable IRQ ", Hex(_irq_number), " requested"); - throw Service_denied(); - } + _irq_alloc.alloc_addr(1, _irq_number).with_result( + [&] (Range_allocator::Allocation &irq_number) { + irq_number.deallocate = false; }, + [&] (Alloc_error) { + error("unavailable interrupt ", _irq_number, " requested"); + throw Service_denied(); }); _irq_object.start(); } diff --git a/repos/base-okl4/src/core/platform.cc b/repos/base-okl4/src/core/platform.cc index 9f9dca1e91..072b9999c6 100644 --- a/repos/base-okl4/src/core/platform.cc +++ b/repos/base-okl4/src/core/platform.cc @@ -184,32 +184,31 @@ Core::Platform::Platform() /* core log as ROM module */ { - unsigned const pages = 1; - size_t const log_size = pages << get_page_size_log2(); - unsigned const align = get_page_size_log2(); + unsigned const pages = 1; + size_t const log_size = pages << get_page_size_log2(); + unsigned const align = get_page_size_log2(); ram_alloc().alloc_aligned(log_size, align).with_result( - [&] (void *phys) { - addr_t const phys_addr = reinterpret_cast(phys); + [&] (Range_allocator::Allocation &phys) { + addr_t const phys_addr = reinterpret_cast(phys.ptr); region_alloc().alloc_aligned(log_size, align). with_result( + [&] (Range_allocator::Allocation &virt) { - [&] (void *ptr) { - - map_local(phys_addr, (addr_t)ptr, pages); - memset(ptr, 0, log_size); + map_local(phys_addr, (addr_t)virt.ptr, pages); + memset(virt.ptr, 0, log_size); new (core_mem_alloc()) Rom_module(_rom_fs, "core_log", phys_addr, log_size); - init_core_log(Core_log_range { (addr_t)ptr, log_size } ); + init_core_log(Core_log_range { (addr_t)virt.ptr, log_size } ); + + phys.deallocate = virt.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { } - ); + [&] (Alloc_error) { }); }, - [&] (Range_allocator::Alloc_error) { } - ); + [&] (Alloc_error) { }); } /* export platform-specific infos */ @@ -219,14 +218,14 @@ Core::Platform::Platform() ram_alloc().alloc_aligned(size, get_page_size_log2()).with_result( - [&] (void *phys_ptr) { - addr_t const phys_addr = reinterpret_cast(phys_ptr); + [&] (Range_allocator::Allocation &phys) { + addr_t const phys_addr = reinterpret_cast(phys.ptr); /* let one page free after the log buffer */ region_alloc().alloc_aligned(size, get_page_size_log2()).with_result( - [&] (void *core_local_ptr) { - addr_t const core_local_addr = reinterpret_cast(core_local_ptr); + [&] (Range_allocator::Allocation &core_local) { + addr_t const core_local_addr = reinterpret_cast(core_local.ptr); if (map_local(phys_addr, core_local_addr, pages)) { @@ -237,13 +236,13 @@ Core::Platform::Platform() new (core_mem_alloc()) Rom_module(_rom_fs, "platform_info", phys_addr, size); + + phys.deallocate = core_local.deallocate = false; } }, - [&] (Range_allocator::Alloc_error) { } - ); + [&] (Alloc_error) { }); }, - [&] (Range_allocator::Alloc_error) { } - ); + [&] (Alloc_error) { }); } } diff --git a/repos/base-okl4/src/core/ram_dataspace_support.cc b/repos/base-okl4/src/core/ram_dataspace_support.cc index 37d8df0675..b2b60e68ab 100644 --- a/repos/base-okl4/src/core/ram_dataspace_support.cc +++ b/repos/base-okl4/src/core/ram_dataspace_support.cc @@ -38,41 +38,28 @@ void Ram_dataspace_factory::_clear_ds (Dataspace_component &ds) { size_t page_rounded_size = (ds.size() + get_page_size() - 1) & get_page_mask(); - struct Guard - { - Range_allocator &virt_alloc; - struct { void *virt_ptr = nullptr; }; - - Guard(Range_allocator &virt_alloc) : virt_alloc(virt_alloc) { } - - ~Guard() { if (virt_ptr) virt_alloc.free(virt_ptr); } - - } guard(platform().region_alloc()); - /* allocate range in core's virtual address space */ platform().region_alloc().try_alloc(page_rounded_size).with_result( - [&] (void *ptr) { guard.virt_ptr = ptr; }, - [&] (Range_allocator::Alloc_error e) { - error("could not allocate virtual address range in core of size ", - page_rounded_size, ", error=", e); }); + [&] (Range_allocator::Allocation &virt) { - if (!guard.virt_ptr) - return; + /* map the dataspace's physical pages to corresponding virtual addresses */ + size_t num_pages = page_rounded_size >> get_page_size_log2(); + if (!map_local(ds.phys_addr(), (addr_t)virt.ptr, num_pages)) { + error("core-local memory mapping failed"); + return; + } - /* map the dataspace's physical pages to corresponding virtual addresses */ - size_t num_pages = page_rounded_size >> get_page_size_log2(); - if (!map_local(ds.phys_addr(), (addr_t)guard.virt_ptr, num_pages)) { - error("core-local memory mapping failed"); - return; - } + /* clear dataspace */ + size_t num_longwords = page_rounded_size/sizeof(long); + for (long *dst = (long *)virt.ptr; num_longwords--;) + *dst++ = 0; - /* clear dataspace */ - size_t num_longwords = page_rounded_size/sizeof(long); - for (long *dst = (long *)guard.virt_ptr; num_longwords--;) - *dst++ = 0; - - /* unmap dataspace from core */ - if (!unmap_local((addr_t)guard.virt_ptr, num_pages)) - error("could not unmap core-local address range at ", guard.virt_ptr, ", " - "error=", Okl4::L4_ErrorCode()); + /* unmap dataspace from core */ + if (!unmap_local((addr_t)virt.ptr, num_pages)) + error("could not unmap core-local address range at ", virt.ptr, ", " + "error=", Okl4::L4_ErrorCode()); + }, + [&] (Alloc_error) { + error("could not allocate virtual address range of size ", page_rounded_size); + }); } diff --git a/repos/base-pistachio/src/core/io_mem_session_support.cc b/repos/base-pistachio/src/core/io_mem_session_support.cc index 29adba2149..a362cc0cc2 100644 --- a/repos/base-pistachio/src/core/io_mem_session_support.cc +++ b/repos/base-pistachio/src/core/io_mem_session_support.cc @@ -75,8 +75,9 @@ Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local( : log2(size); return platform().region_alloc().alloc_aligned(size, align).convert( - [&] (void *ptr) { return (addr_t)ptr; }, - [&] (Range_allocator::Alloc_error) -> addr_t { + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; return (addr_t)a.ptr; }, + [&] (Alloc_error) -> addr_t { error(__func__, ": alloc_aligned failed!"); return 0; }); }; diff --git a/repos/base-pistachio/src/core/irq_session_component.cc b/repos/base-pistachio/src/core/irq_session_component.cc index 35bd3be1ae..1af8a5d611 100644 --- a/repos/base-pistachio/src/core/irq_session_component.cc +++ b/repos/base-pistachio/src/core/irq_session_component.cc @@ -133,10 +133,12 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, if (msi) throw Service_denied(); - if (irq_alloc.alloc_addr(1, _irq_number).failed()) { - error("unavailable IRQ ", Hex(_irq_number), " requested"); - throw Service_denied(); - } + _irq_alloc.alloc_addr(1, _irq_number).with_result( + [&] (Range_allocator::Allocation &irq_number) { + irq_number.deallocate = false; }, + [&] (Alloc_error) { + error("unavailable interrupt ", _irq_number, " requested"); + throw Service_denied(); }); _irq_object.start(); } diff --git a/repos/base-pistachio/src/core/platform.cc b/repos/base-pistachio/src/core/platform.cc index 7c7e0c142a..d79a948876 100644 --- a/repos/base-pistachio/src/core/platform.cc +++ b/repos/base-pistachio/src/core/platform.cc @@ -602,11 +602,11 @@ Core::Platform::Platform() size_t const size = 1 << get_page_size_log2(); ram_alloc().alloc_aligned(size, get_page_size_log2()).with_result( - [&] (void *phys_ptr) { + [&] (Range_allocator::Allocation &phys) { /* core-local memory is one-to-one mapped physical RAM */ - addr_t const phys_addr = reinterpret_cast(phys_ptr); - void * const core_local_ptr = phys_ptr; + addr_t const phys_addr = reinterpret_cast(phys.ptr); + void * const core_local_ptr = phys.ptr; region_alloc().remove_range((addr_t)core_local_ptr, size); memset(core_local_ptr, 0, size); @@ -614,8 +614,10 @@ Core::Platform::Platform() new (core_mem_alloc()) Rom_module(_rom_fs, rom_name, phys_addr, size); + + phys.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { warning("failed to export ", rom_name, " as ROM module"); } ); }; diff --git a/repos/base-sel4/src/core/core_region_map.cc b/repos/base-sel4/src/core/core_region_map.cc index c0c70aab2c..55e07e745d 100644 --- a/repos/base-sel4/src/core/core_region_map.cc +++ b/repos/base-sel4/src/core/core_region_map.cc @@ -35,15 +35,16 @@ Core_region_map::attach(Dataspace_capability ds_cap, Attr const &attr) /* allocate range in core's virtual address space */ return platform().region_alloc().try_alloc(page_rounded_size).convert( - [&] (void *virt_ptr) { + [&] (Range_allocator::Allocation &virt) { /* map the dataspace's physical pages to core-local virtual addresses */ size_t num_pages = page_rounded_size >> get_page_size_log2(); - map_local(ds->phys_addr(), (addr_t)virt_ptr, num_pages); + map_local(ds->phys_addr(), (addr_t)virt.ptr, num_pages); - return Range { .start = addr_t(virt_ptr), .num_bytes = page_rounded_size }; + virt.deallocate = false; + return Range { .start = addr_t(virt.ptr), .num_bytes = page_rounded_size }; }, - [&] (Range_allocator::Alloc_error) -> Attach_result { + [&] (Alloc_error) -> Attach_result { error("could not allocate virtual address range in core of size ", page_rounded_size); return Attach_error::REGION_CONFLICT; diff --git a/repos/base-sel4/src/core/include/platform.h b/repos/base-sel4/src/core/include/platform.h index e91cf3f438..41d1c131f5 100644 --- a/repos/base-sel4/src/core/include/platform.h +++ b/repos/base-sel4/src/core/include/platform.h @@ -60,11 +60,13 @@ class Core::Static_allocator : public Allocator } try { - return &_elements[_used.alloc()]; } + return { *this, { &_elements[_used.alloc()], size } }; } catch (typename Bit_allocator::Out_of_indices) { return Alloc_error::DENIED; } } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + size_t overhead(size_t) const override { return 0; } void free(void *ptr, size_t) override diff --git a/repos/base-sel4/src/core/include/untyped_memory.h b/repos/base-sel4/src/core/include/untyped_memory.h index 9f89803af8..4b23c3abfd 100644 --- a/repos/base-sel4/src/core/include/untyped_memory.h +++ b/repos/base-sel4/src/core/include/untyped_memory.h @@ -39,10 +39,11 @@ struct Core::Untyped_memory return phys_alloc.alloc_aligned(size, align).convert( - [&] (void *ptr) { - return (addr_t)ptr; }, + [&] (Range_allocator::Allocation &phys) { + phys.deallocate = false; + return (addr_t)phys.ptr; }, - [&] (Range_allocator::Alloc_error) -> addr_t { + [&] (Alloc_error) -> addr_t { error(__PRETTY_FUNCTION__, ": allocation of untyped memory failed"); throw Phys_alloc_failed(); }); } diff --git a/repos/base-sel4/src/core/irq_session_component.cc b/repos/base-sel4/src/core/irq_session_component.cc index be5beeb975..e6358be90f 100644 --- a/repos/base-sel4/src/core/irq_session_component.cc +++ b/repos/base-sel4/src/core/irq_session_component.cc @@ -107,10 +107,12 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, { Irq_args const irq_args(args); - if (irq_alloc.alloc_addr(1, _irq_number).failed()) { - error("unavailable IRQ ", _irq_number, " requested"); - throw Service_denied(); - } + _irq_alloc.alloc_addr(1, _irq_number).with_result( + [&] (Range_allocator::Allocation &irq_number) { + irq_number.deallocate = false; }, + [&] (Alloc_error) { + error("unavailable interrupt ", _irq_number, " requested"); + throw Service_denied(); }); if (!_irq_object.associate(irq_args)) { error("could not associate with IRQ ", irq_args.irq_number()); diff --git a/repos/base-sel4/src/core/platform.cc b/repos/base-sel4/src/core/platform.cc index 2bd987fdbc..d6449846eb 100644 --- a/repos/base-sel4/src/core/platform.cc +++ b/repos/base-sel4/src/core/platform.cc @@ -295,8 +295,9 @@ void Core::Platform::_init_rom_modules() size_t const align = get_page_size_log2(); return _unused_phys_alloc.alloc_aligned(size, align).convert( - [&] (void *ptr) { return (addr_t)ptr; }, - [&] (Range_allocator::Alloc_error) -> addr_t { + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; return (addr_t)a.ptr; }, + [&] (Alloc_error) -> addr_t { error("could not reserve phys CNode space for boot modules"); struct Init_rom_modules_failed { }; throw Init_rom_modules_failed(); @@ -476,7 +477,7 @@ void Core::Platform::_init_rom_modules() addr_t const addr = Untyped_memory::alloc_page(_alloc); - bool keep = false; + bool deallocate = true; Phys_alloc_guard(Range_allocator &alloc) :_alloc(alloc) { @@ -485,10 +486,8 @@ void Core::Platform::_init_rom_modules() ~Phys_alloc_guard() { - if (keep) - return; - - Untyped_memory::free_page(_alloc, addr); + if (deallocate) + Untyped_memory::free_page(_alloc, addr); } } phys { ram_alloc() }; @@ -497,24 +496,23 @@ void Core::Platform::_init_rom_modules() region_alloc().alloc_aligned(size, align).with_result( - [&] (void *core_local_ptr) { + [&] (Range_allocator::Allocation &core_local) { - if (!map_local(phys.addr, (addr_t)core_local_ptr, pages, this)) { + if (!map_local(phys.addr, (addr_t)core_local.ptr, pages, this)) { error("could not setup platform_info ROM - map error"); - region_alloc().free(core_local_ptr); return; } - memset(core_local_ptr, 0, size); - content_fn((char *)core_local_ptr, size); + memset(core_local.ptr, 0, size); + content_fn((char *)core_local.ptr, size); new (core_mem_alloc()) Rom_module(_rom_fs, rom_name, phys.addr, size); - phys.keep = true; + phys.deallocate = core_local.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("could not setup platform_info ROM - region allocation error"); } ); @@ -588,17 +586,19 @@ Core::Platform::Platform() addr_t const virt_size = 32 * 1024 * 1024; _unused_virt_alloc.alloc_aligned(virt_size, get_page_size_log2()).with_result( - [&] (void *virt_ptr) { - addr_t const virt_addr = (addr_t)virt_ptr; + [&] (Range_allocator::Allocation &virt) { + addr_t const virt_addr = (addr_t)virt.ptr; /* add to available virtual region of core */ _core_mem_alloc.virt_alloc().add_range(virt_addr, virt_size); /* back region by page tables */ _core_vm_space.unsynchronized_alloc_page_tables(virt_addr, virt_size); + + virt.deallocate = false; }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { warning("failed to reserve core virtual memory for dynamic use"); } ); diff --git a/repos/base-sel4/src/core/platform_thread.cc b/repos/base-sel4/src/core/platform_thread.cc index ecb302ba1d..5f805645cc 100644 --- a/repos/base-sel4/src/core/platform_thread.cc +++ b/repos/base-sel4/src/core/platform_thread.cc @@ -105,29 +105,24 @@ static void prepopulate_ipc_buffer(Ipc_buffer_phys const ipc_buffer_phys, /* allocate range in core's virtual address space */ platform().region_alloc().try_alloc(page_rounded_size).with_result( - [&] (void *virt_ptr) { + [&] (Range_allocator::Allocation &virt) { /* map the IPC buffer to core-local virtual addresses */ - map_local(ipc_buffer_phys.addr, (addr_t)virt_ptr, 1); + map_local(ipc_buffer_phys.addr, (addr_t)virt.ptr, 1); /* populate IPC buffer with thread information */ - Native_utcb &utcb = *(Native_utcb *)virt_ptr; + Native_utcb &utcb = *(Native_utcb *)virt.ptr; utcb.ep_sel (ep_sel .value()); utcb.lock_sel(lock_sel.value()); utcb.ipcbuffer(utcb_virt); /* unmap IPC buffer from core */ - if (!unmap_local((addr_t)virt_ptr, 1)) { + if (!unmap_local((addr_t)virt.ptr, 1)) error("could not unmap core virtual address ", - virt_ptr, " in ", __PRETTY_FUNCTION__); - return; - } - - /* free core's virtual address space */ - platform().region_alloc().free(virt_ptr, page_rounded_size); + virt.ptr, " in ", __PRETTY_FUNCTION__); }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("could not allocate virtual address range in core of size ", page_rounded_size); } diff --git a/repos/base-sel4/src/core/ram_dataspace_support.cc b/repos/base-sel4/src/core/ram_dataspace_support.cc index 660eecb1de..adda4e2c06 100644 --- a/repos/base-sel4/src/core/ram_dataspace_support.cc +++ b/repos/base-sel4/src/core/ram_dataspace_support.cc @@ -45,8 +45,9 @@ void Ram_dataspace_factory::_clear_ds (Dataspace_component &ds) auto alloc_one_virt_page = [&] () -> void * { return platform().region_alloc().try_alloc(get_page_size()).convert( - [&] (void *ptr) { return ptr; }, - [&] (Range_allocator::Alloc_error) -> void * { + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; return a.ptr; }, + [&] (Alloc_error) -> void * { ASSERT_NEVER_CALLED; }); }; diff --git a/repos/base/include/base/allocator.h b/repos/base/include/base/allocator.h index 17a47b66fb..9110e6bf52 100644 --- a/repos/base/include/base/allocator.h +++ b/repos/base/include/base/allocator.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -58,30 +59,12 @@ struct Genode::Deallocator : Interface }; -struct Genode::Allocator : Deallocator +struct Genode::Allocator : Deallocator, Memory::Constrained_allocator { using Out_of_memory = Out_of_ram; using Denied = Genode::Denied; - - /** - * Return type of 'try_alloc' - */ - using Alloc_error = Genode::Alloc_error; - using Alloc_result = Attempt; - - /** - * Destructor - */ - virtual ~Allocator() { } - - /** - * Allocate block - * - * \param size block size to allocate - * \param out_addr resulting pointer to the new block, - * undefined in the error case - */ - virtual Alloc_result try_alloc(size_t size) = 0; + using Alloc_result = Memory::Constrained_allocator::Result; + using Allocation = Memory::Allocation; /** * Return total amount of backing store consumed by the allocator @@ -118,7 +101,7 @@ struct Genode::Allocator : Deallocator void *alloc(size_t size) { return try_alloc(size).convert( - [&] (void *ptr) { return ptr; }, + [&] (Allocation &a) { a.deallocate = false; return a.ptr; }, [&] (Alloc_error e) -> void * { raise(e); }); } }; @@ -126,10 +109,7 @@ struct Genode::Allocator : Deallocator struct Genode::Range_allocator : Allocator { - /** - * Destructor - */ - virtual ~Range_allocator() { } + using Allocation = Allocator::Allocation; /** * Return type of range-management operations @@ -156,12 +136,12 @@ struct Genode::Range_allocator : Allocator * as the power of two * \param range address-range constraint for the allocation */ - virtual Alloc_result alloc_aligned(size_t size, unsigned align, Range range) = 0; + virtual Result alloc_aligned(size_t size, unsigned align, Range range) = 0; /** * Allocate block without constraining the address range */ - Alloc_result alloc_aligned(size_t size, unsigned align) + Result alloc_aligned(size_t size, unsigned align) { return alloc_aligned(size, align, Range { .start = 0, .end = ~0UL }); } @@ -172,7 +152,7 @@ struct Genode::Range_allocator : Allocator * \param size size of new block * \param addr desired address of block */ - virtual Alloc_result alloc_addr(size_t size, addr_t addr) = 0; + virtual Result alloc_addr(size_t size, addr_t addr) = 0; /** * Free a previously allocated block @@ -299,15 +279,4 @@ void Genode::destroy(auto && dealloc, T *obj) operator delete (obj, dealloc); } - -namespace Genode { - - void static inline print(Output &out, Allocator::Alloc_result result) - { - result.with_result( - [&] (void *ptr) { Genode::print(out, ptr); }, - [&] (auto error) { Genode::print(out, error); }); - } -} - #endif /* _INCLUDE__BASE__ALLOCATOR_H_ */ diff --git a/repos/base/include/base/allocator_avl.h b/repos/base/include/base/allocator_avl.h index 60524803bb..d0ad9badbb 100644 --- a/repos/base/include/base/allocator_avl.h +++ b/repos/base/include/base/allocator_avl.h @@ -280,15 +280,22 @@ class Genode::Allocator_avl_base : public Range_allocator using Range_allocator::alloc_aligned; /* import overloads */ - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ Alloc_result try_alloc(size_t size) override { return Allocator_avl_base::alloc_aligned(size, (unsigned)log2(sizeof(addr_t))); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ + void free(void *addr, size_t) override { free(addr); } /** diff --git a/repos/base/include/base/heap.h b/repos/base/include/base/heap.h index 1abd508bdb..10f19193fb 100644 --- a/repos/base/include/base/heap.h +++ b/repos/base/include/base/heap.h @@ -155,12 +155,19 @@ class Genode::Heap : public Allocator fn(ds->local_addr, ds->size); } + /********************************* + ** Memory::Allocator interface ** + *********************************/ - /************************* - ** Allocator interface ** - *************************/ + Alloc_result try_alloc(size_t) override; + + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ - Alloc_result try_alloc(size_t) override; void free(void *, size_t) override; size_t consumed() const override { return _quota_used; } size_t overhead(size_t size) const override { return _alloc->overhead(size); } @@ -211,11 +218,19 @@ class Genode::Sliced_heap : public Allocator ~Sliced_heap(); - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ + + Alloc_result try_alloc(size_t size) override; + + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ - Alloc_result try_alloc(size_t) override; void free(void *, size_t) override; size_t consumed() const override { return _consumed; } size_t overhead(size_t size) const override; diff --git a/repos/base/include/base/memory.h b/repos/base/include/base/memory.h new file mode 100644 index 0000000000..d174650467 --- /dev/null +++ b/repos/base/include/base/memory.h @@ -0,0 +1,62 @@ +/* + * \brief Interfaces for byte-wise local memory allocations + * \author Norman Feske + * \date 2025-04-05 + */ + +/* + * Copyright (C) 2025 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__BASE__MEMORY_H_ +#define _INCLUDE__BASE__MEMORY_H_ + +#include +#include + +namespace Genode::Memory { struct Constrained_allocator; } + + +/** + * Allocator of bytes that reflects allocation errors + */ +struct Genode::Memory::Constrained_allocator : Interface, Noncopyable +{ + struct Attr + { + void *ptr; size_t num_bytes; + + void print(Output &out) const + { + Genode::print(out, "ptr=", ptr, " num_bytes=", num_bytes); + } + }; + + using Error = Alloc_error; + using Allocation = Genode::Allocation; + using Result = Allocation::Attempt; + + /** + * Allocate memory block + */ + virtual Result try_alloc(size_t num_bytes) = 0; + + /** + * Release allocation + * + * \noapi + */ + virtual void _free(Allocation &) = 0; +}; + + +namespace Genode::Memory { + + /* shortcut for the most commonly used type allocation */ + using Allocation = Constrained_allocator::Allocation; +} + +#endif /* _INCLUDE__BASE__MEMORY_H_ */ diff --git a/repos/base/include/base/slab.h b/repos/base/include/base/slab.h index d3a9d545b2..b955279642 100644 --- a/repos/base/include/base/slab.h +++ b/repos/base/include/base/slab.h @@ -145,9 +145,9 @@ class Genode::Slab : public Allocator void free_empty_blocks(); - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ /** * Allocate slab entry @@ -156,6 +156,14 @@ class Genode::Slab : public Allocator * preconfigured slab-entry size are allocated. */ Alloc_result try_alloc(size_t size) override; + + void _free(Allocation &a) override { _free(a.ptr); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ + void free(void *addr, size_t) override { _free(addr); } size_t consumed() const override; size_t overhead(size_t) const override { return _block_size/_entries_per_block; } diff --git a/repos/base/include/base/synced_allocator.h b/repos/base/include/base/synced_allocator.h index 084e060e03..9547fa65ea 100644 --- a/repos/base/include/base/synced_allocator.h +++ b/repos/base/include/base/synced_allocator.h @@ -51,13 +51,20 @@ class Genode::Synced_allocator : public Allocator Guard operator () () const { return _synced_object(); } - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ Alloc_result try_alloc(size_t size) override { return _synced_object()->try_alloc(size); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ + void free(void *addr, size_t size) override { _synced_object()->free(addr, size); } diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 001f7da2fb..e111db4692 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -367,15 +367,15 @@ _ZTSN6Genode6ThreadE R 17 _ZTSN6Genode7ConsoleE R 18 _ZTVN5Timer10ConnectionE D 320 _ZTVN6Genode10Vm_sessionE D 56 -_ZTVN6Genode11Sliced_heapE D 72 +_ZTVN6Genode11Sliced_heapE D 128 _ZTVN6Genode14Rpc_entrypointE D 80 _ZTVN6Genode14Signal_contextE D 32 _ZTVN6Genode17Region_map_clientE D 72 _ZTVN6Genode17Rm_session_clientE D 48 _ZTVN6Genode17Timeout_schedulerE D 112 -_ZTVN6Genode18Allocator_avl_baseE D 128 -_ZTVN6Genode4HeapE D 72 -_ZTVN6Genode4SlabE D 72 +_ZTVN6Genode18Allocator_avl_baseE D 184 +_ZTVN6Genode4HeapE D 128 +_ZTVN6Genode4SlabE D 128 _ZTVN6Genode5Child14Initial_threadE D 48 _ZTVN6Genode5ChildE D 440 _ZTVN6Genode6OutputE D 48 @@ -383,11 +383,22 @@ _ZTVN6Genode6ThreadE D 48 _ZTVN6Genode7ConsoleE D 48 _ZThn104_N5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handlerE T _ZThn104_N5Timer10Connection9curr_timeEv T +_ZThn4_N6Genode11Sliced_heap9try_allocEm T +_ZThn4_N6Genode4Heap9try_allocEm T +_ZThn4_N6Genode4HeapD0Ev T +_ZThn4_N6Genode4HeapD1Ev T +_ZThn4_N6Genode4Slab9try_allocEm T +_ZThn4_N6Genode4SlabD0Ev T +_ZThn4_N6Genode4SlabD1Ev T _ZThn52_N5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handlerE T _ZThn52_N5Timer10Connection9curr_timeEv T +_ZThn8_N6Genode11Sliced_heap9try_allocEm T _ZThn8_N6Genode17Timeout_scheduler14handle_timeoutENS_8DurationE T _ZThn8_N6Genode17Timeout_schedulerD0Ev T _ZThn8_N6Genode17Timeout_schedulerD1Ev T +_ZThn8_N6Genode18Allocator_avl_base9try_allocEm T +_ZThn8_N6Genode4Heap9try_allocEm T +_ZThn8_N6Genode4Slab9try_allocEm T _ZdlPvPN6Genode11DeallocatorE T _ZdlPvPN6Genode9AllocatorE W _ZdlPvRN6Genode11DeallocatorE T diff --git a/repos/base/src/core/core_mem_alloc.cc b/repos/base/src/core/core_mem_alloc.cc index cbad2f1f61..293a629a73 100644 --- a/repos/base/src/core/core_mem_alloc.cc +++ b/repos/base/src/core/core_mem_alloc.cc @@ -42,28 +42,27 @@ Mapped_mem_allocator::alloc_aligned(size_t size, unsigned align, Range range) return _phys_alloc->alloc_aligned(page_rounded_size, align, range) .convert( - [&] (void *phys_addr) -> Alloc_result { + [&] (Allocation &phys) -> Alloc_result { /* allocate range in core's virtual address space */ return _virt_alloc->alloc_aligned(page_rounded_size, align) .convert( - [&] (void *virt_addr) { + [&] (Allocation &virt) -> Alloc_result { - _phys_alloc->metadata(phys_addr, { virt_addr }); - _virt_alloc->metadata(virt_addr, { phys_addr }); + _phys_alloc->metadata(phys.ptr, { virt.ptr }); + _virt_alloc->metadata(virt.ptr, { phys.ptr }); /* make physical page accessible at the designated virtual address */ - _map_local((addr_t)virt_addr, (addr_t)phys_addr, page_rounded_size); + _map_local((addr_t)virt.ptr, (addr_t)phys.ptr, page_rounded_size); - return virt_addr; + phys.deallocate = false; + virt.deallocate = false; + return { *this, { virt.ptr, page_rounded_size } }; }, [&] (Alloc_error e) { error("Could not allocate virtual address range in core of size ", page_rounded_size, " (error ", (int)e, ")"); - - /* revert physical allocation */ - _phys_alloc->free(phys_addr); return e; }); }, diff --git a/repos/base/src/core/include/accounted_core_ram.h b/repos/base/src/core/include/accounted_core_ram.h index 39e8c6d777..8184994bf8 100644 --- a/repos/base/src/core/include/accounted_core_ram.h +++ b/repos/base/src/core/include/accounted_core_ram.h @@ -1,6 +1,5 @@ /* - * \brief Quota-bounds-checking implementation of the 'Ram_allocator' - * interface specifically for core + * \brief Quota-bounds-checking implementation of the 'Allocator' for core * \author Norman Feske * \date 2017-05-02 */ @@ -63,16 +62,19 @@ class Core::Accounted_core_ram : public Allocator return _core_mem.try_alloc(page_aligned_size).convert( - [&] (void *ptr) { + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; ram.acknowledge(); caps.acknowledge(); core_mem_allocated += page_aligned_size; - return ptr; }, + return { *this, { a.ptr, page_aligned_size } }; }, [&] (Alloc_error error) { return error; }); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *ptr, size_t const size) override { size_t const page_aligned_size = align_addr(size, 12); diff --git a/repos/base/src/core/include/core_mem_alloc.h b/repos/base/src/core/include/core_mem_alloc.h index 783772b71c..77d62bad0c 100644 --- a/repos/base/src/core/include/core_mem_alloc.h +++ b/repos/base/src/core/include/core_mem_alloc.h @@ -123,7 +123,6 @@ class Core::Mapped_mem_allocator : public Core_mem_translator * \param phys_alloc allocator of physical memory * \param virt_alloc allocator of core-local virtual memory ranges */ - Mapped_mem_allocator(Synced_mapped_allocator &phys_alloc, Synced_mapped_allocator &virt_alloc) : _phys_alloc(&phys_alloc._alloc), _virt_alloc(&virt_alloc._alloc) { } @@ -178,12 +177,20 @@ class Core::Mapped_mem_allocator : public Core_mem_translator using Range_allocator::alloc_aligned; /* import overloads */ - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ Alloc_result try_alloc(size_t size) override { return alloc_aligned(size, (unsigned)log2(sizeof(addr_t))); } + + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ + void free(void *addr, size_t) override; size_t consumed() const override { return _phys_alloc->consumed(); } size_t overhead(size_t size) const override { @@ -301,15 +308,22 @@ class Core::Core_mem_allocator : public Core_mem_translator using Range_allocator::alloc_aligned; /* import overloads */ - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ Alloc_result try_alloc(size_t size) override { return alloc_aligned(size, (unsigned)log2(sizeof(addr_t))); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ + void free(void *addr, size_t size) override { Mutex::Guard lock_guard(_mutex); diff --git a/repos/base/src/core/include/synced_range_allocator.h b/repos/base/src/core/include/synced_range_allocator.h index 1ca37e1f0d..d8f2ca190a 100644 --- a/repos/base/src/core/include/synced_range_allocator.h +++ b/repos/base/src/core/include/synced_range_allocator.h @@ -63,13 +63,20 @@ class Core::Synced_range_allocator : public Range_allocator void print(Output &out) const { _synced_object()->print(out); } - /************************* - ** Allocator interface ** - *************************/ + /********************************* + ** Memory::Allocator interface ** + *********************************/ Alloc_result try_alloc(size_t size) override { return _synced_object()->try_alloc(size); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /**************************************** + ** Legacy Genode::Allocator interface ** + ****************************************/ + void free(void *addr, size_t size) override { _synced_object()->free(addr, size); } diff --git a/repos/base/src/core/io_mem_session_component.cc b/repos/base/src/core/io_mem_session_component.cc index aa33e2edbc..d62ed6f8d0 100644 --- a/repos/base/src/core/io_mem_session_component.cc +++ b/repos/base/src/core/io_mem_session_component.cc @@ -69,9 +69,19 @@ Io_mem_session_component::_prepare_io_mem(const char *args, (req_base == 0xfd6e0000ull && req_size == 4096); /* allocate region */ - if (!skip_iomem_check && _io_mem_alloc.alloc_addr(req_size, req_base).failed()) { - error("I/O memory ", Hex_range(req_base, req_size), " not available"); - return Dataspace_attr(); + if (!skip_iomem_check) { + + bool const ok = _io_mem_alloc.alloc_addr(req_size, req_base).convert( + + [&] (Range_allocator::Allocation &io_mem) { + io_mem.deallocate = false; return true; }, + + [&] (Alloc_error) { return false; }); + + if (!ok) { + error("I/O memory ", Hex_range(req_base, req_size), " not available"); + return Dataspace_attr(); + } } /* request local mapping */ diff --git a/repos/base/src/core/ram_dataspace_factory.cc b/repos/base/src/core/ram_dataspace_factory.cc index 2328489878..1fa693cd33 100644 --- a/repos/base/src/core/ram_dataspace_factory.cc +++ b/repos/base/src/core/ram_dataspace_factory.cc @@ -20,6 +20,8 @@ using namespace Core; Ram_dataspace_factory::Alloc_ram_result Ram_dataspace_factory::alloc_ram(size_t ds_size, Cache cache) { + using Range_allocation = Range_allocator::Allocation; + /* zero-sized dataspaces are not allowed */ if (!ds_size) return Alloc_ram_error::DENIED; @@ -35,7 +37,7 @@ Ram_dataspace_factory::alloc_ram(size_t ds_size, Cache cache) * If this does not work, we subsequently weaken the alignment constraint * until the allocation succeeds. */ - Range_allocator::Alloc_result allocated_range = Allocator::Alloc_error::DENIED; + Range_allocator::Alloc_result allocated_range = Alloc_error::DENIED; /* apply constraints */ if (_phys_range.start != 0 || _phys_range.end != ~0UL) { @@ -82,36 +84,15 @@ Ram_dataspace_factory::alloc_ram(size_t ds_size, Cache cache) error("out of physical memory while allocating ", ds_size, " bytes ", "in range [", Hex(_phys_range.start), "-", Hex(_phys_range.end), "]"); - if (allocated_range == Allocator::Alloc_error::OUT_OF_RAM) + if (allocated_range == Alloc_error::OUT_OF_RAM) return Alloc_ram_error::OUT_OF_RAM; - if (allocated_range == Allocator::Alloc_error::OUT_OF_CAPS) + if (allocated_range == Alloc_error::OUT_OF_CAPS) return Alloc_ram_error::OUT_OF_CAPS; return Alloc_ram_error::DENIED; } - /* - * Helper to release the allocated physical memory whenever we leave the - * scope via an exception. - */ - struct Phys_alloc_guard - { - Range_allocator &phys_alloc; - struct { void * ds_addr = nullptr; }; - bool keep = false; - - Phys_alloc_guard(Range_allocator &phys_alloc) - : phys_alloc(phys_alloc) { } - - ~Phys_alloc_guard() { if (!keep && ds_addr) phys_alloc.free(ds_addr); } - - } phys_alloc_guard(_phys_alloc); - - allocated_range.with_result( - [&] (void *ptr) { phys_alloc_guard.ds_addr = ptr; }, - [&] (Allocator::Alloc_error) { /* already checked above */ }); - /* * For non-cached RAM dataspaces, we mark the dataspace as write * combined and expect the pager to evaluate this dataspace property @@ -119,9 +100,12 @@ Ram_dataspace_factory::alloc_ram(size_t ds_size, Cache cache) */ Dataspace_component *ds_ptr = nullptr; try { - ds_ptr = new (_ds_slab) - Dataspace_component(ds_size, (addr_t)phys_alloc_guard.ds_addr, - cache, true, this); + allocated_range.with_result( + [&] (Range_allocation &range) { + ds_ptr = new (_ds_slab) + Dataspace_component(ds_size, (addr_t)range.ptr, + cache, true, this); }, + [] (Alloc_error) { }); } catch (Out_of_ram) { return Alloc_ram_error::OUT_OF_RAM; } catch (Out_of_caps) { return Alloc_ram_error::OUT_OF_CAPS; } @@ -148,7 +132,9 @@ Ram_dataspace_factory::alloc_ram(size_t ds_size, Cache cache) Dataspace_capability ds_cap = _ep.manage(&ds); - phys_alloc_guard.keep = true; + allocated_range.with_result( + [&] (Range_allocation &a) { a.deallocate = false; }, + [] (Alloc_error) { }); return static_cap_cast(ds_cap); } diff --git a/repos/base/src/core/region_map_component.cc b/repos/base/src/core/region_map_component.cc index 2c7f13c539..1953663e4a 100644 --- a/repos/base/src/core/region_map_component.cc +++ b/repos/base/src/core/region_map_component.cc @@ -165,6 +165,8 @@ void Rm_faulter::continue_after_resolved_fault() Region_map::Attach_result Region_map_component::_attach(Dataspace_capability ds_cap, Attach_attr const core_attr) { + using Region_allocation = Range_allocator::Allocation; + Attr const attr = core_attr.attr; /* serialize access */ @@ -176,8 +178,6 @@ Region_map_component::_attach(Dataspace_capability ds_cap, Attach_attr const cor auto lambda = [&] (Dataspace_component *dsc) -> Attach_result { - using Alloc_error = Range_allocator::Alloc_error; - /* check dataspace validity */ if (!dsc) return Attach_error::INVALID_DATASPACE; @@ -204,7 +204,10 @@ Region_map_component::_attach(Dataspace_capability ds_cap, Attach_attr const cor if (attr.use_at) { Alloc_error error = Alloc_error::DENIED; _map.alloc_addr(size, attr.at).with_result( - [&] (void *ptr) { at = addr_t(ptr); at_defined = true; }, + [&] (Region_allocation &a) { + a.deallocate = false; + at = addr_t(a.ptr); + at_defined = true; }, [&] (Alloc_error e) { error = e; }); if (error == Alloc_error::OUT_OF_RAM) return Attach_error::OUT_OF_RAM; @@ -234,7 +237,10 @@ Region_map_component::_attach(Dataspace_capability ds_cap, Attach_attr const cor /* try allocating the aligned region */ Alloc_error error = Alloc_error::DENIED; _map.alloc_aligned(size, unsigned(align_log2)).with_result( - [&] (void *ptr) { at = addr_t(ptr); at_defined = true; }, + [&] (Region_allocation &a) { + a.deallocate = false; + at = addr_t(a.ptr); + at_defined = true; }, [&] (Alloc_error e) { error = e; }); if (error == Alloc_error::OUT_OF_RAM) return Attach_error::OUT_OF_RAM; diff --git a/repos/base/src/core/spec/x86/io_port_session_component.cc b/repos/base/src/core/spec/x86/io_port_session_component.cc index 10c1874098..0d5cdebcef 100644 --- a/repos/base/src/core/spec/x86/io_port_session_component.cc +++ b/repos/base/src/core/spec/x86/io_port_session_component.cc @@ -32,18 +32,18 @@ Io_port_session_component::Io_port_session_component(Range_allocator &io_port_al /* allocate region (also checks out-of-bounds regions) */ io_port_alloc.alloc_addr(size, base).with_error( - [&] (Allocator::Alloc_error e) { + [&] (Alloc_error e) { switch (e) { - case Range_allocator::Alloc_error::DENIED: + case Alloc_error::DENIED: error("I/O port ", Hex_range(base, size), " not available"); throw Service_denied(); - case Range_allocator::Alloc_error::OUT_OF_RAM: + case Alloc_error::OUT_OF_RAM: error("I/O port allocator ran out of RAM"); throw Service_denied(); - case Range_allocator::Alloc_error::OUT_OF_CAPS: + case Alloc_error::OUT_OF_CAPS: error("I/O port allocator ran out of caps"); throw Service_denied(); } diff --git a/repos/base/src/core/stack_area.cc b/repos/base/src/core/stack_area.cc index 98a474bcba..4fc97789e5 100644 --- a/repos/base/src/core/stack_area.cc +++ b/repos/base/src/core/stack_area.cc @@ -67,6 +67,8 @@ class Stack_area_region_map : public Region_map */ Attach_result attach(Dataspace_capability, Attr const &attr) override { + using Phys_allocation = Range_allocator::Allocation; + /* allocate physical memory */ size_t const size = round_page(attr.size); @@ -74,10 +76,10 @@ class Stack_area_region_map : public Region_map return phys.alloc_aligned(size, get_page_size_log2()).convert( - [&] (void *phys_ptr) -> Attach_result { + [&] (Phys_allocation &phys) -> Attach_result { try { - addr_t const phys_base = (addr_t)phys_ptr; + addr_t const phys_base = (addr_t)phys.ptr; Dataspace_component &ds = *new (&_ds_slab) Dataspace_component(size, 0, (addr_t)phys_base, CACHED, true, 0); @@ -90,18 +92,18 @@ class Stack_area_region_map : public Region_map error("could not map phys ", Hex(ds.phys_addr()), " at local ", Hex(core_local_addr)); - phys.free(phys_ptr); return Attach_error::INVALID_DATASPACE; } ds.assign_core_local_addr((void*)core_local_addr); + phys.deallocate = false; return Range { .start = attr.at, .num_bytes = size }; } catch (Out_of_ram) { return Attach_error::OUT_OF_RAM; } catch (Out_of_caps) { return Attach_error::OUT_OF_CAPS; } }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { error("could not allocate backing store for new stack"); return Attach_error::REGION_CONFLICT; }); } diff --git a/repos/base/src/core/vm_session_common.cc b/repos/base/src/core/vm_session_common.cc index 23c71f5fa0..479eee77f9 100644 --- a/repos/base/src/core/vm_session_common.cc +++ b/repos/base/src/core/vm_session_common.cc @@ -63,13 +63,13 @@ void Vm_session_component::attach(Dataspace_capability const cap, attribute.offset > dsc.size() - attribute.size) throw Invalid_dataspace(); - using Alloc_error = Range_allocator::Alloc_error; - Region_map_detach &rm_detach = *this; + using Guest_phys_allocation = Range_allocator::Allocation; + _map.alloc_addr(attribute.size, guest_phys).with_result( - [&] (void *) { + [&] (Guest_phys_allocation &allocation) { Rm_region::Attr const region_attr { @@ -93,6 +93,8 @@ void Vm_session_component::attach(Dataspace_capability const cap, Rm_region ®ion = *_map.metadata((void *)guest_phys); + allocation.deallocate = false; + /* inform dataspace about attachment */ dsc.attached_to(region); }, diff --git a/repos/base/src/lib/base/allocator_avl.cc b/repos/base/src/lib/base/allocator_avl.cc index cef4814b23..5dd25548b0 100644 --- a/repos/base/src/lib/base/allocator_avl.cc +++ b/repos/base/src/lib/base/allocator_avl.cc @@ -98,8 +98,9 @@ void Allocator_avl_base::Block::recompute() Allocator_avl_base::Alloc_md_result Allocator_avl_base::_alloc_block_metadata() { return _md_alloc.try_alloc(sizeof(Block)).convert( - [&] (void *ptr) { - return construct_at(ptr, 0U, 0U, 0); }, + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return construct_at(a.ptr, 0U, 0U, 0); }, [&] (Alloc_error error) { return error; }); } @@ -337,10 +338,10 @@ Allocator_avl_base::_allocate(size_t const size, unsigned align, Range range, /* create allocated block */ return _alloc_block_metadata().convert( - [&] (Block *new_block_ptr) { + [&] (Block *new_block_ptr) -> Alloc_result { _add_block(*new_block_ptr, new_addr, size, Block::USED); - return reinterpret_cast(new_addr); }, - + return { *this, { reinterpret_cast(new_addr), size } }; + }, [&] (Alloc_error error) { return error; }); }, diff --git a/repos/base/src/lib/base/heap.cc b/repos/base/src/lib/base/heap.cc index 0083e322ea..d42679b354 100644 --- a/repos/base/src/lib/base/heap.cc +++ b/repos/base/src/lib/base/heap.cc @@ -145,8 +145,9 @@ Heap::_allocate_dataspace(size_t size, bool enforce_separate_metadata) } return metadata.convert( - [&] (void *md_ptr) -> Result { - Dataspace &ds = *construct_at(md_ptr, allocation.cap, + [&] (Allocation &md) -> Result { + md.deallocate = false; + Dataspace &ds = *construct_at(md.ptr, allocation.cap, (void *)attach_guard.range.start, size); _ds_pool.insert(&ds); return &ds; @@ -163,9 +164,10 @@ Allocator::Alloc_result Heap::_try_local_alloc(size_t size) { return _alloc->alloc_aligned(size, log2(16U)).convert( - [&] (void *ptr) { + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; _quota_used += size; - return ptr; }, + return { *this, { a.ptr, size } }; }, [&] (Alloc_error error) { return error; }); @@ -188,9 +190,9 @@ Allocator::Alloc_result Heap::_unsynchronized_alloc(size_t size) return _allocate_dataspace(dataspace_size, true).convert( - [&] (Dataspace *ds_ptr) { + [&] (Dataspace *ds_ptr) -> Alloc_result { _quota_used += ds_ptr->size; - return ds_ptr->local_addr; }, + return { *this, { ds_ptr->local_addr, size } }; }, [&] (Alloc_error error) { return error; }); @@ -200,7 +202,11 @@ Allocator::Alloc_result Heap::_unsynchronized_alloc(size_t size) { Alloc_result result = _try_local_alloc(size); if (result.ok()) - return result; + return result.convert( + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; + return { *this, a }; }, + [&] (Alloc_error e) { return e; }); } size_t dataspace_size = size diff --git a/repos/base/src/lib/base/slab.cc b/repos/base/src/lib/base/slab.cc index e156ba4949..ac8cf6fb0a 100644 --- a/repos/base/src/lib/base/slab.cc +++ b/repos/base/src/lib/base/slab.cc @@ -255,8 +255,9 @@ Slab::New_slab_block_result Slab::_new_slab_block() Slab &this_slab = *this; return _backing_store->try_alloc(_block_size).convert( - [&] (void *sb) { - return construct_at(sb, this_slab); }, + [&] (Allocation &sb) { + sb.deallocate = false; + return construct_at(sb.ptr, this_slab); }, [&] (Alloc_error error) { return error; }); } @@ -408,7 +409,7 @@ Allocator::Alloc_result Slab::try_alloc(size_t size) _total_avail--; - return ptr; + return { *this, { ptr, _slab_size } }; } diff --git a/repos/base/src/lib/base/sliced_heap.cc b/repos/base/src/lib/base/sliced_heap.cc index 4988b93de4..c1dfcb4120 100644 --- a/repos/base/src/lib/base/sliced_heap.cc +++ b/repos/base/src/lib/base/sliced_heap.cc @@ -38,10 +38,10 @@ Sliced_heap::~Sliced_heap() } -Allocator::Alloc_result Sliced_heap::try_alloc(size_t size) +Allocator::Alloc_result Sliced_heap::try_alloc(size_t requested_size) { /* allocation includes space for block meta data and is page-aligned */ - size = align_addr(size + sizeof(Block), 12); + size_t const size = align_addr(requested_size + sizeof(Block), 12); return _ram_alloc.try_alloc(size).convert( @@ -93,8 +93,7 @@ Allocator::Alloc_result Sliced_heap::try_alloc(size_t size) attach_guard.keep = true; /* skip meta data prepended to the payload portion of the block */ - void *ptr = block + 1; - return ptr; + return { *this, { .ptr = block + 1, .num_bytes = requested_size } }; }, [&] (Ram::Error e) { return e; }); } diff --git a/repos/base/src/lib/cxx/emutls.cc b/repos/base/src/lib/cxx/emutls.cc index 36b4ac0602..9761e01f43 100644 --- a/repos/base/src/lib/cxx/emutls.cc +++ b/repos/base/src/lib/cxx/emutls.cc @@ -177,10 +177,9 @@ extern "C" void *__emutls_get_address(void *obj) void *address = nullptr; cxx_heap().try_alloc(emutls_object->size).with_result( - [&] (void *ptr) { address = ptr; }, - [&] (Allocator::Alloc_error e) { - error(__func__, - ": could not allocate thread-local variable, error ", (int)e); }); + [&] (Memory::Allocation &a) { a.deallocate = false; address = a.ptr; }, + [&] (Alloc_error e) { + error(__func__, ": could not allocate thread-local variable, ", e); }); if (!address) return nullptr; diff --git a/repos/base/src/lib/cxx/malloc_free.cc b/repos/base/src/lib/cxx/malloc_free.cc index 7a0a487246..b4f1f9e04b 100644 --- a/repos/base/src/lib/cxx/malloc_free.cc +++ b/repos/base/src/lib/cxx/malloc_free.cc @@ -80,10 +80,9 @@ extern "C" void *malloc(size_t size) void *addr = nullptr; cxx_heap().try_alloc(real_size).with_result( - [&] (void *ptr) { addr = ptr; }, - [&] (Allocator::Alloc_error error) { - Genode::error(__func__, - ": cxx_heap allocation failed with error ", (int)error); }); + [&] (Memory::Allocation &a) { a.deallocate = false; addr = a.ptr; }, + [&] (Alloc_error e) { + Genode::error(__func__, ": cxx_heap allocation failed with ", e); }); if (!addr) return nullptr; diff --git a/repos/base/src/lib/ldso/include/region_map.h b/repos/base/src/lib/ldso/include/region_map.h index bbec312610..8b95c479c5 100644 --- a/repos/base/src/lib/ldso/include/region_map.h +++ b/repos/base/src/lib/ldso/include/region_map.h @@ -84,6 +84,7 @@ class Linker::Region_map using Alloc_region_result = Attempt; using Attach_result = Genode::Region_map::Attach_result; using Attr = Genode::Region_map::Attr; + using Range_allocation = Range_allocator::Allocation; /** * Allocate region anywhere within the region map @@ -91,8 +92,11 @@ class Linker::Region_map Alloc_region_result alloc_region(size_t size) { return _range.alloc_aligned(size, get_page_size_log2()).convert( - [&] (void *ptr) { return (addr_t)ptr; }, - [&] (Allocator::Alloc_error e) { return e; }); + [&] (Range_allocation &a) { + a.deallocate = false; + return (addr_t)a.ptr; + }, + [&] (Alloc_error e) { return e; }); } /** @@ -101,8 +105,11 @@ class Linker::Region_map Alloc_region_result alloc_region_at(size_t size, addr_t vaddr) { return _range.alloc_addr(size, vaddr).convert( - [&] (void *ptr) { return (addr_t)ptr; }, - [&] (Allocator::Alloc_error e) { return e; }); + [&] (Range_allocation &a) { + a.deallocate = false; + return (addr_t)a.ptr; + }, + [&] (Alloc_error e) { return e; }); } Alloc_region_result alloc_region_at_end(size_t size) diff --git a/repos/base/src/test/new_delete/main.cc b/repos/base/src/test/new_delete/main.cc index 4e548579c4..8f5466e17e 100644 --- a/repos/base/src/test/new_delete/main.cc +++ b/repos/base/src/test/new_delete/main.cc @@ -41,34 +41,33 @@ struct E : C, D struct Allocator : Genode::Allocator { - Genode::Heap heap; - Genode::Allocator & a { heap }; + Genode::Heap _heap; + Genode::Allocator &_a { _heap }; - Allocator(Genode::Env & env) : heap(env.ram(), env.rm()) { } + Allocator(Genode::Env &env) : _heap(env.ram(), env.rm()) { } virtual ~Allocator() { } Genode::size_t consumed() const override { - return a.consumed(); } + return _a.consumed(); } Genode::size_t overhead(Genode::size_t size) const override { - return a.overhead(size); } + return _a.overhead(size); } bool need_size_for_free() const override { - return a.need_size_for_free(); } + return _a.need_size_for_free(); } Alloc_result try_alloc(Genode::size_t size) override { - Alloc_result const result = a.try_alloc(size); - log("Allocator::alloc()"); - - return result; + return _a.try_alloc(size); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *p, Genode::size_t size) override { log("Allocator::free()"); - a.free(p, size); + _a.free(p, size); } }; diff --git a/repos/dde_bsd/src/lib/audio/pci.cc b/repos/dde_bsd/src/lib/audio/pci.cc index 838c11dfed..98e800025d 100644 --- a/repos/dde_bsd/src/lib/audio/pci.cc +++ b/repos/dde_bsd/src/lib/audio/pci.cc @@ -227,8 +227,10 @@ class Pci_driver using namespace Genode; return _alloc.alloc_aligned(size, align).convert( - [&] (void *ptr) { return (addr_t)ptr; }, - [&] (Allocator_avl::Alloc_error) { return 0UL; }); + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return (addr_t)a.ptr; }, + [&] (Alloc_error) { return 0UL; }); } void free(Genode::addr_t virt, Genode::size_t size) { diff --git a/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc b/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc index f75bbaa80e..0d1bbfb150 100644 --- a/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc +++ b/repos/dde_ipxe/src/lib/dde_ipxe/dde_support.cc @@ -321,9 +321,10 @@ extern "C" void *dde_dma_alloc(dde_size_t size, dde_size_t align, { return allocator().alloc_aligned(size, Genode::log2(align)).convert( - [&] (void *ptr) { return ptr; }, + [&] (Genode::Allocator::Allocation &a) { + a.deallocate = false; return a.ptr; }, - [&] (Genode::Range_allocator::Alloc_error) -> void * { + [&] (Genode::Alloc_error) -> void * { Genode::error("memory allocation failed in alloc_memblock (" "size=", size, " " "align=", Genode::Hex(align), " " @@ -467,21 +468,32 @@ struct Slab_backend_alloc : public Genode::Allocator, Genode::addr_t start() const { return _base; } Genode::addr_t end() const { return _base + VM_SIZE - 1; } - /************************* - ** Allocator interface ** - *************************/ + + /********************************* + ** Memory::Allocator interface ** + *********************************/ Alloc_result try_alloc(Genode::size_t size) override { - Alloc_result result = _range.try_alloc(size); - if (result.ok()) - return result; - - return _extend_one_block().convert( - [&] (Ok) { return _range.try_alloc(size); }, - [&] (Alloc_error e) { return e; }); + return _range.try_alloc(size).convert( + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; + return { *this, a }; + }, + [&] (Alloc_error) { + return _extend_one_block().convert( + [&] (Ok) { return _range.try_alloc(size); }, + [&] (Alloc_error e) { return e; }); + }); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + + + /************************* + ** Allocator interface ** + *************************/ + void free(void *addr, Genode::size_t size) { _range.free(addr, size); } Genode::size_t overhead(Genode::size_t size) const { return 0; } bool need_size_for_free() const { return false; } @@ -511,7 +523,8 @@ class Slab_alloc : public Genode::Slab Genode::addr_t alloc() { return Slab::try_alloc(_object_size).convert( - [&] (void *ptr) { return (Genode::addr_t)ptr; }, + [&] (Allocator::Allocation &a) { + a.deallocate = false; return (Genode::addr_t)a.ptr; }, [&] (Alloc_error) -> Genode::addr_t { return 0; }); } diff --git a/repos/dde_linux/src/lib/lx_kit/memory.cc b/repos/dde_linux/src/lib/lx_kit/memory.cc index e56d758bbd..c271b665f3 100644 --- a/repos/dde_linux/src/lib/lx_kit/memory.cc +++ b/repos/dde_linux/src/lib/lx_kit/memory.cc @@ -71,9 +71,11 @@ void * Lx_kit::Mem_allocator::alloc(size_t const size, size_t const align, return _mem.alloc_aligned(size, (unsigned)log2(align)).convert( - [&] (void *ptr) { return cleared_allocation(ptr, size); }, + [&] (Allocator::Allocation &a) { + a.deallocate = false; + return cleared_allocation(a.ptr, size); }, - [&] (Range_allocator::Alloc_error) { + [&] (Alloc_error) { /* * Restrict the minimum buffer size to avoid the creation of @@ -97,9 +99,11 @@ void * Lx_kit::Mem_allocator::alloc(size_t const size, size_t const align, /* re-try allocation */ void * const virt_addr = _mem.alloc_aligned(size, (unsigned)log2(align)).convert( - [&] (void *ptr) { return cleared_allocation(ptr, size); }, + [&] (Allocator::Allocation &a) { + a.deallocate = false; + return cleared_allocation(a.ptr, size); }, - [&] (Range_allocator::Alloc_error) -> void * { + [&] (Alloc_error) -> void * { error("memory allocation failed for ", size, " align ", align); return nullptr; } ); diff --git a/repos/dde_rump/src/include/util/allocator_fap.h b/repos/dde_rump/src/include/util/allocator_fap.h index 8a27447b05..3f51c301e2 100644 --- a/repos/dde_rump/src/include/util/allocator_fap.h +++ b/repos/dde_rump/src/include/util/allocator_fap.h @@ -103,7 +103,7 @@ namespace Allocator { _ds_cap[_index] = Rump::env().env().ram().try_alloc(BLOCK_SIZE, _cache) .template convert( [&] (Ram::Allocation &a) { a.deallocate = false; return a.cap; }, - [&] (Allocator::Alloc_error) { return Ram_dataspace_capability(); } + [&] (Alloc_error) { return Ram_dataspace_capability(); } ); if (!_ds_cap[_index].valid()) { @@ -147,27 +147,34 @@ namespace Allocator { _range(&Rump::env().heap()) { } - /** - * Allocate - */ Alloc_result try_alloc(size_t size) override { - Alloc_result result = _range.try_alloc(size); - if (result.ok()) - return result; + return _range.try_alloc(size).convert( + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; + return { *this, a }; + }, + [&] (Alloc_error) -> Alloc_result { + if (!_alloc_block()) + return Alloc_error::DENIED; - if (!_alloc_block()) - return Alloc_error::DENIED; - - return _range.try_alloc(size); + return _range.try_alloc(size).convert( + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; + return { *this, a }; + }, + [&] (Alloc_error e) { return e; }); + }); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void *alloc_aligned(size_t size, unsigned align = 0) { Alloc_result result = _range.alloc_aligned(size, align); if (result.ok()) return result.convert( - [&] (void *ptr) { return ptr; }, + [&] (Allocation &a) { a.deallocate = false; return a.ptr; }, [&] (Alloc_error) -> void * { return nullptr; }); if (!_alloc_block()) @@ -175,8 +182,9 @@ namespace Allocator { return _range.alloc_aligned(size, align).convert( - [&] (void *ptr) { - return ptr; }, + [&] (Allocation &a) { + a.deallocate = false; + return a.ptr; }, [&] (Alloc_error e) -> void * { error("backend allocator: Unable to allocate memory " diff --git a/repos/demo/src/lib/mini_c/malloc_free.cc b/repos/demo/src/lib/mini_c/malloc_free.cc index 14d082dfa8..27f5add359 100644 --- a/repos/demo/src/lib/mini_c/malloc_free.cc +++ b/repos/demo/src/lib/mini_c/malloc_free.cc @@ -44,12 +44,12 @@ extern "C" void *malloc(size_t size) return alloc().try_alloc(real_size).convert( - [&] (void *ptr) { + [&] (Allocator::Allocation &a) { + a.deallocate = false; + *(unsigned long *)a.ptr = real_size; + return (unsigned long *)a.ptr + 1; }, - *(unsigned long *)ptr = real_size; - return (unsigned long *)ptr + 1; }, - - [&] (Allocator::Alloc_error) { + [&] (Alloc_error) { return nullptr; }); } diff --git a/repos/gems/include/gems/cached_font.h b/repos/gems/include/gems/cached_font.h index 5da7bc930c..7bf01638b5 100644 --- a/repos/gems/include/gems/cached_font.h +++ b/repos/gems/include/gems/cached_font.h @@ -79,15 +79,17 @@ class Genode::Cached_font : public Text_painter::Font return _alloc.try_alloc(size).convert( - [&] (void *ptr) { - memset(ptr, 0, size); + [&] (Allocation &a) -> Result { + memset(a.ptr, 0, size); _consumed_bytes += size + overhead(size); - return ptr; }, + a.deallocate = false; + return { *this, { a.ptr, size } }; }, - [&] (Alloc_error error) { - return error; }); + [&] (Error e) { return e; }); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + size_t consumed() const override { return _alloc.consumed(); } size_t overhead(size_t size) const override { return _alloc.overhead(size); }; diff --git a/repos/gems/include/gems/dynamic_array.h b/repos/gems/include/gems/dynamic_array.h index cc1582a154..488f738254 100644 --- a/repos/gems/include/gems/dynamic_array.h +++ b/repos/gems/include/gems/dynamic_array.h @@ -92,9 +92,9 @@ struct Genode::Dynamic_array _alloc.try_alloc(sizeof(Element)*new_capacity).with_result( - [&] (void *ptr) { + [&] (Allocator::Allocation &a) { - Element *new_array = (Element *)ptr; + Element *new_array = (Element *)a.ptr; for (unsigned i = 0; i < new_capacity; i++) construct_at(&new_array[i]); @@ -108,9 +108,10 @@ struct Genode::Dynamic_array _array = new_array; _capacity = new_capacity; + + a.deallocate = false; }, - [&] (Allocator::Alloc_error e) { - Allocator::throw_alloc_error(e); } + [&] (Alloc_error e) { raise(e); } ); } diff --git a/repos/libports/include/libc/allocator.h b/repos/libports/include/libc/allocator.h index db8eb0d83e..3bb1633b00 100644 --- a/repos/libports/include/libc/allocator.h +++ b/repos/libports/include/libc/allocator.h @@ -27,7 +27,12 @@ struct Libc::Allocator : Genode::Allocator { typedef Genode::size_t size_t; - Alloc_result try_alloc(size_t size) override { return malloc(size); } + Alloc_result try_alloc(size_t size) override + { + return { *this, { malloc(size), size } }; + } + + void _free(Allocation &a) override { ::free(a.ptr); } void free(void *addr, size_t size) override { ::free(addr); } diff --git a/repos/libports/ports/sanitizer.hash b/repos/libports/ports/sanitizer.hash index 29fc5f46ea..f7ec2cc789 100644 --- a/repos/libports/ports/sanitizer.hash +++ b/repos/libports/ports/sanitizer.hash @@ -1 +1 @@ -235417ce6c12f84a121ac094c155b883b7abaf68 +12ee36349c907f2c90d59bb3717ced1d9ff5b78a diff --git a/repos/libports/src/lib/gcov/libc/libc.cc b/repos/libports/src/lib/gcov/libc/libc.cc index 2a05768336..60d7d58c5c 100644 --- a/repos/libports/src/lib/gcov/libc/libc.cc +++ b/repos/libports/src/lib/gcov/libc/libc.cc @@ -384,8 +384,8 @@ extern "C" int getpid() extern "C" void *malloc(size_t size) { return gcov_env->heap.try_alloc(size).convert( - [&] (void *ptr) { return ptr; }, - [&] (Allocator::Alloc_error) -> void * { return nullptr; }); + [&] (Allocator::Allocation &a) { a.deallocate = false; return a.ptr; }, + [&] (Alloc_error) -> void * { return nullptr; }); } diff --git a/repos/libports/src/lib/libc/libc_mem_alloc.cc b/repos/libports/src/lib/libc/libc_mem_alloc.cc index 34ab88b3e3..91b172a373 100644 --- a/repos/libports/src/lib/libc/libc_mem_alloc.cc +++ b/repos/libports/src/lib/libc/libc_mem_alloc.cc @@ -99,13 +99,14 @@ int Libc::Mem_alloc_impl::Dataspace_pool::expand(size_t size, Range_allocator *a /* now that we have new backing store, allocate Dataspace structure */ return alloc->alloc_aligned(sizeof(Dataspace), 2).convert( - [&] (void *ptr) { + [&] (Range_allocator::Allocation &a) { /* add dataspace information to list of dataspaces */ - Dataspace *ds = construct_at(ptr, new_ds_cap, range); + Dataspace *ds = construct_at(a.ptr, new_ds_cap, range); insert(ds); + a.deallocate = false; return 0; }, - [&] (Allocator::Alloc_error) { + [&] (Alloc_error) { warning("libc: could not allocate meta data - this should never happen"); return -1; }); } @@ -116,13 +117,16 @@ void *Libc::Mem_alloc_impl::alloc(size_t size, size_t align_log2) /* serialize access of heap functions */ Mutex::Guard guard(_mutex); - void *out_addr = nullptr; + auto alloc_or_nullptr = [&] + { + return _alloc.alloc_aligned(size, align_log2).convert( + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; return a.ptr; }, + [&] (Alloc_error) { return nullptr; }); + }; /* try allocation at our local allocator */ - _alloc.alloc_aligned(size, align_log2).with_result( - [&] (void *ptr) { out_addr = ptr; }, - [&] (Allocator::Alloc_error) { }); - + void * const out_addr = alloc_or_nullptr(); if (out_addr) return out_addr; @@ -151,11 +155,7 @@ void *Libc::Mem_alloc_impl::alloc(size_t size, size_t align_log2) } /* allocate originally requested block */ - _alloc.alloc_aligned(size, align_log2).with_result( - [&] (void *ptr) { out_addr = ptr; }, - [&] (Allocator::Alloc_error) { }); - - return out_addr; + return alloc_or_nullptr(); } diff --git a/repos/libports/src/lib/libc/malloc.cc b/repos/libports/src/lib/libc/malloc.cc index 2998070d42..6a506e8c7e 100644 --- a/repos/libports/src/lib/libc/malloc.cc +++ b/repos/libports/src/lib/libc/malloc.cc @@ -61,8 +61,8 @@ class Libc::Slab_alloc : public Slab void *alloc() { return Slab::try_alloc(_object_size).convert( - [&] (void *ptr) { return ptr; }, - [&] (Alloc_error) { return nullptr; }); + [&] (Allocation &a) { a.deallocate = false; return a.ptr; }, + [&] (Alloc_error) { return nullptr; }); } void free(void *ptr) { Slab::free(ptr, _object_size); } @@ -166,8 +166,9 @@ class Libc::Malloc /* use backing store if requested memory is larger than largest slab */ if (msb > SLAB_STOP) _backing_store.try_alloc(real_size).with_result( - [&] (void *ptr) { alloc_addr = ptr; }, - [&] (Allocator::Alloc_error) { }); + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; alloc_addr = a.ptr; }, + [&] (Alloc_error) { }); else alloc_addr = _slabs[msb - SLAB_START]->alloc(); diff --git a/repos/libports/src/lib/libdrm/ioctl_iris.cc b/repos/libports/src/lib/libdrm/ioctl_iris.cc index f5723227b7..a61987e953 100644 --- a/repos/libports/src/lib/libdrm/ioctl_iris.cc +++ b/repos/libports/src/lib/libdrm/ioctl_iris.cc @@ -245,10 +245,11 @@ struct Gpu::Vram Allocation alloc(Genode::size_t size) { return _alloc.alloc_aligned(size, 12).convert( - [&] (void *offset) { - return Allocation { _elem.id(), _cap, Genode::off_t(offset), size }; + [&] (Genode::Range_allocator::Allocation &a) { + a.deallocate = false; + return Allocation { _elem.id(), _cap, Genode::off_t(a.ptr), size }; }, - [&] (Genode::Allocator::Alloc_error err) -> Allocation { + [&] (Genode::Alloc_error err) -> Allocation { return Allocation(); }); } diff --git a/repos/libports/src/lib/libdrm/ioctl_lima.cc b/repos/libports/src/lib/libdrm/ioctl_lima.cc index b71203d833..b82dbe00c0 100644 --- a/repos/libports/src/lib/libdrm/ioctl_lima.cc +++ b/repos/libports/src/lib/libdrm/ioctl_lima.cc @@ -309,8 +309,11 @@ class Lima::Call Gpu::Virtual_address alloc(uint32_t size) { return Gpu::Virtual_address { _alloc.alloc_aligned(size, 12).convert<::uint64_t>( - [&] (void *ptr) { return (::uint64_t)ptr; }, - [&] (Range_allocator::Alloc_error) -> ::uint64_t { + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return ::uint64_t(a.ptr); + }, + [&] (Alloc_error) -> ::uint64_t { error("Could not allocate GPU virtual address for size: ", size); return 0; }) }; diff --git a/repos/libports/src/lib/lwip/sys_arch.cc b/repos/libports/src/lib/lwip/sys_arch.cc index 99a0731a8b..76a154c215 100644 --- a/repos/libports/src/lib/lwip/sys_arch.cc +++ b/repos/libports/src/lib/lwip/sys_arch.cc @@ -83,8 +83,9 @@ extern "C" { void *genode_malloc(unsigned long size) { return Lwip::_heap->try_alloc(size).convert( - [&] (void *ptr) { return ptr; }, - [&] (Genode::Allocator::Alloc_error) -> void * { return nullptr; }); + [&] (Genode::Allocator::Allocation &a) { + a.deallocate = false; return a.ptr; }, + [&] (Genode::Alloc_error) -> void * { return nullptr; }); } void *genode_calloc(unsigned long number, unsigned long size) diff --git a/repos/libports/src/lib/sanitizer/sanitizer.patch b/repos/libports/src/lib/sanitizer/sanitizer.patch index 6766ac451b..0d65cd368d 100644 --- a/repos/libports/src/lib/sanitizer/sanitizer.patch +++ b/repos/libports/src/lib/sanitizer/sanitizer.patch @@ -183,12 +183,12 @@ index 0000000..78ee830 + + return heap().try_alloc(size).convert( + -+ [&] (void *ptr) { ++ [&] (Genode::Range_allocator::Allocation &a) { + IncreaseTotalMmap(size); -+ return ptr; ++ a.deallocate = false; return a.ptr; + }, + -+ [&] (Genode::Allocator::Alloc_error) -> void * { ++ [&] (Genode::Alloc_error) -> void * { + ReportMmapFailureAndDie(size, mem_type, "allocate", 0, raw_report); + return nullptr; + } diff --git a/repos/libports/src/lib/vfs/legacy_lwip/sys_arch.cc b/repos/libports/src/lib/vfs/legacy_lwip/sys_arch.cc index 8c29a74e6e..8b9a3cf275 100644 --- a/repos/libports/src/lib/vfs/legacy_lwip/sys_arch.cc +++ b/repos/libports/src/lib/vfs/legacy_lwip/sys_arch.cc @@ -83,8 +83,9 @@ extern "C" { void *genode_malloc(unsigned long size) { return Lwip::_heap->try_alloc(size).convert( - [&] (void *ptr) { return ptr; }, - [&] (Genode::Allocator::Alloc_error) -> void * { return nullptr; }); + [&] (Genode::Allocator::Allocation &a) { + a.deallocate = false; return a.ptr; }, + [&] (Genode::Alloc_error) -> void * { return nullptr; }); } void *genode_calloc(unsigned long number, unsigned long size) diff --git a/repos/os/include/nic/packet_allocator.h b/repos/os/include/nic/packet_allocator.h index a562778bea..ffbcc73081 100644 --- a/repos/os/include/nic/packet_allocator.h +++ b/repos/os/include/nic/packet_allocator.h @@ -57,32 +57,30 @@ struct Nic::Packet_allocator : Genode::Packet_allocator Packet_allocator(Genode::Allocator *md_alloc) : Genode::Packet_allocator(md_alloc, DEFAULT_PACKET_SIZE) {} - Alloc_result try_alloc(size_t size) override + Result try_alloc(size_t size) override { if (!size || size > OFFSET_PACKET_SIZE) { Genode::error("unsupported NIC packet size ", size); - return Alloc_result { Alloc_error::DENIED }; + return Error::DENIED; } - Alloc_result result = Genode::Packet_allocator::try_alloc(size + OFFSET); - - result.with_result( - [&] (void *content) { + return Genode::Packet_allocator::try_alloc(size + OFFSET).convert( + [&] (Allocation &a) -> Result { /* assume word-aligned packet buffer and offset packet by 2 bytes */ - if ((Genode::addr_t)content & 0b11) { + if ((Genode::addr_t)a.ptr & 0b11) { Genode::error("NIC packet allocation not word-aligned"); - result = { Alloc_error::DENIED }; - } else { - result = Alloc_result { - reinterpret_cast((Genode::uint8_t *)content + OFFSET) }; + return Error::DENIED; } + a.deallocate = false; + return { *this, { + .ptr = reinterpret_cast((Genode::uint8_t *)a.ptr + OFFSET), + .num_bytes = size } }; }, - [] (Alloc_error) { } - ); - - return result; + [] (Error e) { return e; }); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *addr, size_t size) override { if (!size || size > OFFSET_PACKET_SIZE) { diff --git a/repos/os/include/os/packet_allocator.h b/repos/os/include/os/packet_allocator.h index 3f048f5470..84455187e7 100644 --- a/repos/os/include/os/packet_allocator.h +++ b/repos/os/include/os/packet_allocator.h @@ -157,8 +157,10 @@ class Genode::Packet_allocator : public Genode::Range_allocator _array->set(i, cnt); _next = i + cnt; - return reinterpret_cast(i * _block_size - + _base); + return { *this, { + .ptr = reinterpret_cast(i * _block_size + _base), + .num_bytes = size } }; + } } catch (typename Bit_array_base::Invalid_index_access) { } @@ -170,6 +172,8 @@ class Genode::Packet_allocator : public Genode::Range_allocator return Alloc_error::DENIED; } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *addr, size_t size) override { addr_t i = (((addr_t)addr) - _base) / _block_size; diff --git a/repos/os/include/os/packet_stream.h b/repos/os/include/os/packet_stream.h index 20bbcdec20..6f705a162f 100644 --- a/repos/os/include/os/packet_stream.h +++ b/repos/os/include/os/packet_stream.h @@ -699,10 +699,11 @@ class Genode::Packet_stream_source : private Packet_stream_base return _packet_alloc.alloc_aligned(size, align).convert( - [&] (void *base) { - return Packet_descriptor((Genode::off_t)base, size); }, + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return Packet_descriptor((Genode::off_t)a.ptr, size); }, - [&] (Allocator::Alloc_error) -> Packet_descriptor { + [&] (Alloc_error) -> Packet_descriptor { throw Packet_alloc_failed(); }); } @@ -722,10 +723,11 @@ class Genode::Packet_stream_source : private Packet_stream_base return _packet_alloc.alloc_aligned(size, align).convert( - [&] (void *base) { - return Packet_descriptor((Genode::off_t)base, size); }, + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return Packet_descriptor((Genode::off_t)a.ptr, size); }, - [&] (Allocator::Alloc_error) { + [&] (Alloc_error) { return Alloc_packet_error::FAILED; }); } diff --git a/repos/os/src/driver/acpi/memory.h b/repos/os/src/driver/acpi/memory.h index 8ef5d7c844..6064079bb2 100644 --- a/repos/os/src/driver/acpi/memory.h +++ b/repos/os/src/driver/acpi/memory.h @@ -176,7 +176,10 @@ class Acpi::Memory } /* allocate ACPI range as I/O memory */ - _range.alloc_addr(loop_region.size(), loop_region.base()); + _range.alloc_addr(loop_region.size(), loop_region.base()).with_result( + [&] (Range_allocator::Allocation &a) { a.deallocate = false; }, + [&] (Alloc_error e) { raise(e); }); + _range.construct_metadata((void *)loop_region.base(), _env, loop_region); /* diff --git a/repos/os/src/driver/gpu/intel/ppgtt_allocator.h b/repos/os/src/driver/gpu/intel/ppgtt_allocator.h index 0460ee7dc1..2d5102653d 100644 --- a/repos/os/src/driver/gpu/intel/ppgtt_allocator.h +++ b/repos/os/src/driver/gpu/intel/ppgtt_allocator.h @@ -63,8 +63,17 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator Alloc_result try_alloc(size_t size) override { - Alloc_result result = _range.alloc_aligned(size, 12); - if (result.ok()) return result; + return _range.alloc_aligned(size, 12).convert( + [&] (Allocation &a) -> Alloc_result { + a.deallocate = false; + return { *this, a }; }, + [&] (Genode::Alloc_error) { + return _grow_and_alloc(size); }); + } + + Alloc_result _grow_and_alloc(size_t size) + { + using Alloc_error = Genode::Alloc_error; Genode::Ram_dataspace_capability ds { }; @@ -117,6 +126,8 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator ); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *addr, size_t size) override { if (addr == nullptr) { return; } diff --git a/repos/os/src/driver/platform/dma_allocator.cc b/repos/os/src/driver/platform/dma_allocator.cc index b491fbd844..11efd0186a 100644 --- a/repos/os/src/driver/platform/dma_allocator.cc +++ b/repos/os/src/driver/platform/dma_allocator.cc @@ -23,14 +23,14 @@ addr_t Dma_allocator::_alloc_dma_addr(addr_t const phys_addr, size_t const size, bool const force_phys_addr) { - using Alloc_error = Allocator::Alloc_error; - /* * 1:1 mapping (allocate at specified range from DMA memory allocator) */ if (force_phys_addr || !_remapping) { return _dma_alloc.alloc_addr(size, phys_addr).convert( - [&] (void *) -> addr_t { return phys_addr; }, + [&] (Range_allocator::Allocation &a) -> addr_t { + a.deallocate = false; + return addr_t(a.ptr); }, [&] (Alloc_error err) -> addr_t { switch (err) { case Alloc_error::OUT_OF_RAM: throw Out_of_ram(); @@ -57,7 +57,9 @@ addr_t Dma_allocator::_alloc_dma_addr(addr_t const phys_addr, guarded_size += 0x1000; /* 4 kB */ return _dma_alloc.alloc_aligned(guarded_size, size_align_log2).convert( - [&] (void *ptr) { return (addr_t)ptr; }, + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return (addr_t)a.ptr; }, [&] (Alloc_error err) -> addr_t { switch (err) { case Alloc_error::OUT_OF_RAM: throw Out_of_ram(); diff --git a/repos/os/src/test/fb_bench/main.cc b/repos/os/src/test/fb_bench/main.cc index 11f92c2c69..4a730465dd 100644 --- a/repos/os/src/test/fb_bench/main.cc +++ b/repos/os/src/test/fb_bench/main.cc @@ -42,8 +42,11 @@ struct Test log("\nTEST ", id, ": ", brief, "\n"); for (unsigned i = 0; i < 2; i++) { heap.try_alloc(fb_ds.size()).with_result( - [&] (void *ptr) { buf[i] = (char *)ptr; }, - [&] (Allocator::Alloc_error e) { + [&] (Heap::Allocation &a) { + buf[i] = (char *)a.ptr; + a.deallocate = false; + }, + [&] (Alloc_error e) { env.parent().exit(-1); Allocator::throw_alloc_error(e); } diff --git a/repos/os/src/test/ram_fs_chunk/main.cc b/repos/os/src/test/ram_fs_chunk/main.cc index ce6baf5428..05942dc1ac 100644 --- a/repos/os/src/test/ram_fs_chunk/main.cc +++ b/repos/os/src/test/ram_fs_chunk/main.cc @@ -71,18 +71,18 @@ struct Allocator_tracer : Allocator { return wrapped.try_alloc(size).convert( - [&] (void *ptr) { + [&] (Allocation &a) -> Alloc_result { sum += size; - new (wrapped) Alloc(allocs, Alloc::Id { (addr_t)ptr }, size); - return ptr; + new (wrapped) Alloc(allocs, Alloc::Id { (addr_t)a.ptr }, size); + a.deallocate = false; + return { *this, { a.ptr, size } }; }, - - [&] (Allocator::Alloc_error error) { - return error; - } + [&] (Alloc_error error) { return error; } ); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *addr, size_t size) override { allocs.apply(Alloc::Id { (addr_t)addr }, [&] (Alloc &alloc) { diff --git a/repos/os/src/test/slab/main.cc b/repos/os/src/test/slab/main.cc index 0b4e4c7a46..569be284a2 100644 --- a/repos/os/src/test/slab/main.cc +++ b/repos/os/src/test/slab/main.cc @@ -49,10 +49,11 @@ struct Array_of_slab_elements for (size_t i = 0; i < num_elem; i++) { slab.try_alloc(slab_size).with_result( - [&] (void *ptr) { - elem[i] = ptr; }, + [&] (Genode::Allocator::Allocation &a) { + a.deallocate = false; + elem[i] = a.ptr; }, - [&] (Genode::Allocator::Alloc_error) { + [&] (Genode::Alloc_error) { throw Alloc_failed(); } ); } @@ -96,14 +97,17 @@ void Component::construct(Genode::Env & env) Alloc_result try_alloc(size_t size) override { - Alloc_result const result = _alloc.try_alloc(size); - - if (result.ok()) - _consumed += size; - - return result; + return _alloc.try_alloc(size).convert( + [&] (Allocation &a) -> Alloc_result { + _consumed += size; + a.deallocate = false; + return { *this, { a.ptr, size } }; + }, + [&] (Error e) { return e; }); } + void _free(Allocation &a) override { free(a.ptr, a.num_bytes); } + void free(void *addr, size_t size) override { _alloc.free(addr, size); diff --git a/repos/pc/src/driver/platform/pc/expanding_page_table_allocator.h b/repos/pc/src/driver/platform/pc/expanding_page_table_allocator.h index 0aa022ce72..1732af7cd4 100644 --- a/repos/pc/src/driver/platform/pc/expanding_page_table_allocator.h +++ b/repos/pc/src/driver/platform/pc/expanding_page_table_allocator.h @@ -38,7 +38,7 @@ class Driver::Expanding_page_table_allocator private: using Alloc_result = Allocator::Alloc_result; - using Alloc_error = Allocator::Alloc_error; + using Alloc_error = Genode::Alloc_error; enum { MAX_CHUNK_SIZE = 2*1024*1024 }; @@ -237,7 +237,9 @@ Genode::addr_t Driver::Expanding_page_table_allocator::_alloc() } return result.convert( - [&] (void * ptr) -> addr_t { return (addr_t)ptr; }, + [&] (Allocator::Allocation &a) -> addr_t { + a.deallocate = false; + return (addr_t)a.ptr; }, [&] (Alloc_error) -> addr_t { throw Alloc_failed(); }); } diff --git a/repos/ports/src/virtualbox6/sup_gmm.cc b/repos/ports/src/virtualbox6/sup_gmm.cc index d90a1a9e1c..15b73efe2b 100644 --- a/repos/ports/src/virtualbox6/sup_gmm.cc +++ b/repos/ports/src/virtualbox6/sup_gmm.cc @@ -101,10 +101,11 @@ Sup::Gmm::Vmm_addr Sup::Gmm::_alloc_pages(Pages pages) return _alloc.alloc_aligned(bytes, align).convert( - [&] (void *ptr) { - return Vmm_addr { _map.base.value + (addr_t)ptr }; }, + [&] (Range_allocator::Allocation &a) { + a.deallocate = false; + return Vmm_addr { _map.base.value + (addr_t)a.ptr }; }, - [&] (Range_allocator::Alloc_error) -> Vmm_addr { + [&] (Alloc_error) -> Vmm_addr { error("Gmm allocation failed"); throw Allocation_failed(); }