Introduce new 'Ram' API types

The new types in base/ram.h model different allocation scenarios and
error cases by mere C++ types without using exceptions. They are meant
to replace the former 'Ram_allocator' interface. As of now, the
'Unmapped_allocator' closely captures the former 'Ram_allocator'
semantics. The 'Constrained_allocator' is currently an alias for
'Unmapped_allocator' but is designated for eventually allocating
mapped RAM.

In contrast to the 'Ram_allocator' interface, which talked about
dataspace capabilites but left the lifetime management of the
allocated RAM to the caller, the new API represents an allocation
as a guard type 'Allocation', which deallocates on destruction by
default.

Allocation errors are captured by a 'Result' type that follows
the 'Attempt' pattern.

As a transitionary feature, the patch largely maintains API
compatibility with the original 'Ram_allocator' by providing
the original (exception-based) 'Ram_allocator::alloc' and
'Ram_allocator::free' methods as a wrapper around the new
'Ram::Constrained_allocator'. So components can be gradually
updated to the new 'Ram::' interface.

Issue #5502
This commit is contained in:
Norman Feske
2025-04-02 11:11:01 +02:00
parent e9558a36f9
commit 689fc1eb93
40 changed files with 593 additions and 502 deletions

View File

@ -417,30 +417,30 @@ struct Genode::Pd_ram_allocator : Ram_allocator
{
Pd_session &_pd;
Alloc_result try_alloc(size_t size, Cache cache) override
using Pd_error = Pd_session::Alloc_ram_error;
static Ram::Error ram_error(Pd_error e)
{
using Pd_error = Pd_session::Alloc_ram_error;
switch (e) {
case Pd_error::OUT_OF_CAPS: return Ram::Error::OUT_OF_CAPS;
case Pd_error::OUT_OF_RAM: return Ram::Error::OUT_OF_RAM;;
case Pd_error::DENIED: break;
}
return Ram::Error::DENIED;
}
Result try_alloc(size_t size, Cache cache) override
{
using Capability = Ram::Capability;
return _pd.alloc_ram(size, cache).convert<Alloc_result>(
[&] (Ram_dataspace_capability cap) { return cap; },
[&] (Pd_error e) {
switch (e) {
case Pd_error::OUT_OF_CAPS: return Alloc_error::OUT_OF_CAPS;
case Pd_error::OUT_OF_RAM: return Alloc_error::OUT_OF_RAM;;
case Pd_error::DENIED:
break;
}
return Alloc_error::DENIED;
});
[&] (Capability ds) -> Result { return { *this, { ds, size } }; },
[&] (Pd_error e) -> Result { return ram_error(e); });
}
void free(Ram_dataspace_capability ds) override
void _free(Ram::Allocation &allocation) override
{
_pd.free_ram(ds);
}
size_t dataspace_size(Ram_dataspace_capability ds) override
{
return _pd.ram_size(ds);
_pd.free_ram(allocation.cap);
}
Pd_ram_allocator(Pd_session &pd) : _pd(pd) { }