diff --git a/repos/base-linux/src/core/include/core_env.h b/repos/base-linux/src/core/include/core_env.h index 7d8691cbbd..41cfda2082 100644 --- a/repos/base-linux/src/core/include/core_env.h +++ b/repos/base-linux/src/core/include/core_env.h @@ -115,8 +115,6 @@ namespace Genode { Ram_session_component _ram_session; Synced_ram_session _synced_ram_session { _ram_session }; - Ram_session_capability const _ram_session_cap; - /* * The core-local PD session is provided by a real RPC object * dispatched by the same entrypoint as the signal-source RPC @@ -133,6 +131,14 @@ namespace Genode { Core_parent _core_parent { _heap, _services }; + typedef String<100> Ram_args; + + static Session::Resources _ram_resources() + { + return { Ram_quota { platform()->ram_alloc()->avail() }, + Cap_quota { 1000 } }; + } + public: /** @@ -143,13 +149,18 @@ namespace Genode { Platform_env_base(Ram_session_capability(), Cpu_session_capability(), Pd_session_capability()), - _ram_session(&_entrypoint, &_entrypoint, - platform()->ram_alloc(), platform()->core_mem_alloc(), - "ram_quota=4M", platform()->ram_alloc()->avail()), - _ram_session_cap(_entrypoint.manage(&_ram_session)), + _ram_session(_entrypoint, + _ram_resources(), + Session::Label("core"), + Session::Diag{false}, + *platform()->ram_alloc(), + *Platform_env_base::rm_session(), + Ram_session_component::any_phys_range()), _pd_session_component(_entrypoint), _pd_session_client(_entrypoint.manage(&_pd_session_component)) - { } + { + _ram_session.init_ram_account(); + } /** * Destructor @@ -165,7 +176,7 @@ namespace Genode { ******************************/ Parent *parent() override { return &_core_parent; } - Ram_session *ram_session() override { return &_synced_ram_session; } + Ram_session *ram_session() override { return &_ram_session; } Ram_session_capability ram_session_cap() override { return _ram_session.cap(); } Pd_session *pd_session() override { return &_pd_session_client; } Allocator *heap() override { log(__func__, ": not implemented"); return nullptr; } diff --git a/repos/base-nova/src/core/native_pd_component.cc b/repos/base-nova/src/core/native_pd_component.cc index 5d88011e7f..31c23efd87 100644 --- a/repos/base-nova/src/core/native_pd_component.cc +++ b/repos/base-nova/src/core/native_pd_component.cc @@ -26,8 +26,7 @@ Native_capability Native_pd_component::alloc_rpc_cap(Native_capability ep, try { return _pd_session._rpc_cap_factory.alloc(ep, entry, mtd); } - catch (Allocator::Out_of_memory) { - throw Pd_session::Out_of_metadata(); } + catch (Allocator::Out_of_memory) { throw Out_of_ram(); } } diff --git a/repos/base-nova/src/core/ram_session_support.cc b/repos/base-nova/src/core/ram_session_support.cc index fc55fdd4b3..be54ed027a 100644 --- a/repos/base-nova/src/core/ram_session_support.cc +++ b/repos/base-nova/src/core/ram_session_support.cc @@ -81,7 +81,7 @@ void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { /* allocate the virtual region contiguous for the dataspace */ void * virt_ptr = alloc_region(ds, page_rounded_size); if (!virt_ptr) - throw Out_of_metadata(); + throw Core_virtual_memory_exhausted(); /* map it writeable for _clear_ds */ Nova::Utcb * const utcb = reinterpret_cast(Thread::myself()->utcb()); @@ -90,7 +90,7 @@ void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { if (map_local(utcb, ds->phys_addr(), reinterpret_cast(virt_ptr), page_rounded_size >> get_page_size_log2(), rights_rw, true)) { platform()->region_alloc()->free(virt_ptr, page_rounded_size); - throw Out_of_metadata(); + throw Core_virtual_memory_exhausted(); } /* assign virtual address to the dataspace to be used by clear_ds */ diff --git a/repos/base/include/base/allocator.h b/repos/base/include/base/allocator.h index d6a43ca307..2deead4aa1 100644 --- a/repos/base/include/base/allocator.h +++ b/repos/base/include/base/allocator.h @@ -16,6 +16,7 @@ #include #include +#include namespace Genode { @@ -59,7 +60,7 @@ struct Genode::Allocator : Deallocator /** * Exception type */ - class Out_of_memory : public Exception { }; + typedef Out_of_ram Out_of_memory; /** * Destructor @@ -72,6 +73,9 @@ struct Genode::Allocator : Deallocator * \param size block size to allocate * \param out_addr resulting pointer to the new block, * undefined in the error case + * + * \throw Out_of_ram + * * \return true on success */ virtual bool alloc(size_t size, void **out_addr) = 0; @@ -83,6 +87,8 @@ struct Genode::Allocator : Deallocator * a non-void type. By providing this method, we prevent the * compiler from warning us about "dereferencing type-punned * pointer will break strict-aliasing rules". + * + * \throw Out_of_ram */ template bool alloc(size_t size, T **out_addr) { @@ -105,9 +111,11 @@ struct Genode::Allocator : Deallocator /** * Allocate block and signal error as an exception * - * \param size block size to allocate - * \return pointer to the new block - * \throw Out_of_memory + * \param size block size to allocate + * + * \throw Out_of_ram + * + * \return pointer to the new block */ void *alloc(size_t size) { diff --git a/repos/base/include/base/attached_io_mem_dataspace.h b/repos/base/include/base/attached_io_mem_dataspace.h index e9fa44d703..0b6050293b 100644 --- a/repos/base/include/base/attached_io_mem_dataspace.h +++ b/repos/base/include/base/attached_io_mem_dataspace.h @@ -48,6 +48,7 @@ class Genode::Attached_io_mem_dataspace * \throw Parent::Service_denied * \throw Insufficient_ram_quota * \throw Parent::Unavailable + * \throw Out_of_ram * \throw Rm_session::Attach_failed */ Attached_io_mem_dataspace(Env &env, Genode::addr_t base, Genode::size_t size, diff --git a/repos/base/include/base/attached_ram_dataspace.h b/repos/base/include/base/attached_ram_dataspace.h index 96124bd82e..dc0b0f634a 100644 --- a/repos/base/include/base/attached_ram_dataspace.h +++ b/repos/base/include/base/attached_ram_dataspace.h @@ -90,7 +90,7 @@ class Genode::Attached_ram_dataspace /** * Constructor * - * \throw Ram_session::Alloc_failed + * \throw Out_of_ram * \throw Rm_session::Attach_failed */ Attached_ram_dataspace(Ram_session &ram, Region_map &rm, diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index df422693a3..78612b2b1e 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -392,7 +392,7 @@ class Genode::Child : protected Rpc_object, * \throw Missing_dynamic_linker * \throw Invalid_executable * \throw Region_map::Attach_failed - * \throw Ram_session::Alloc_failed + * \throw Out_of_ram * * The other arguments correspond to those of 'Child::Child'. * diff --git a/repos/base/include/base/env.h b/repos/base/include/base/env.h index 52fdfac161..5cb66a5462 100644 --- a/repos/base/include/base/env.h +++ b/repos/base/include/base/env.h @@ -115,7 +115,7 @@ struct Genode::Env * \param id ID of recipient session * \param args description of the amount of quota to transfer * - * \throw Quota_exceeded quota could not be transferred + * \throw Out_of_ram * * The 'args' argument has the same principle format as the 'args' * argument of the 'session' operation. @@ -135,7 +135,7 @@ struct Genode::Env * constructors in the binary and shared libraries the binary depends on. If * the component requires static construction it needs to call this function * at construction time explicitly. For example, the libc implementation - * executes this function before constructing libc components. + * executes this function before constructing libc components. */ virtual void exec_static_constructors() = 0; }; diff --git a/repos/base/include/base/ram_allocator.h b/repos/base/include/base/ram_allocator.h index 32933b7998..1569f5afd1 100644 --- a/repos/base/include/base/ram_allocator.h +++ b/repos/base/include/base/ram_allocator.h @@ -33,11 +33,6 @@ namespace Genode { struct Genode::Ram_allocator { - class Alloc_failed : public Exception { }; - class Quota_exceeded : public Alloc_failed { }; - class Out_of_metadata : public Alloc_failed { }; - - /** * Allocate RAM dataspace * @@ -45,8 +40,8 @@ struct Genode::Ram_allocator * \param cached selects cacheability attributes of the memory, * uncached memory, i.e., for DMA buffers * - * \throw Quota_exceeded - * \throw Out_of_metadata + * \throw Out_of_ram + * \throw Out_of_caps * * \return capability to new RAM dataspace */ diff --git a/repos/base/include/base/session_object.h b/repos/base/include/base/session_object.h index 78943e211e..e06c19c875 100644 --- a/repos/base/include/base/session_object.h +++ b/repos/base/include/base/session_object.h @@ -65,14 +65,12 @@ class Genode::Session_object : public Ram_quota_guard, Cap_quota_guard(resources.cap_quota), _ep(ep), _diag(diag), _label(label) { - Cap_quota_guard::withdraw(Cap_quota{1}); _ep.manage(this); } ~Session_object() { _ep.dissolve(this); - Cap_quota_guard::replenish(Cap_quota{1}); } /** diff --git a/repos/base/include/ram_session/ram_session.h b/repos/base/include/ram_session/ram_session.h index 80d71780a0..e1aebb7bda 100644 --- a/repos/base/include/ram_session/ram_session.h +++ b/repos/base/include/ram_session/ram_session.h @@ -45,6 +45,8 @@ struct Genode::Ram_session : Session, Ram_allocator class Invalid_session : public Exception { }; class Undefined_ref_account : public Exception { }; + /* deprecated */ + typedef Out_of_ram Quota_exceeded; /** * Destructor @@ -100,7 +102,7 @@ struct Genode::Ram_session : Session, Ram_allocator *********************/ GENODE_RPC_THROW(Rpc_alloc, Ram_dataspace_capability, alloc, - GENODE_TYPE_LIST(Quota_exceeded, Out_of_metadata, Undefined_ref_account), + GENODE_TYPE_LIST(Out_of_ram, Out_of_caps, Undefined_ref_account), size_t, Cache_attribute); GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability); GENODE_RPC(Rpc_ref_account, void, ref_account, Capability); diff --git a/repos/base/include/root/component.h b/repos/base/include/root/component.h index ffdb743f8d..c9bc079670 100644 --- a/repos/base/include/root/component.h +++ b/repos/base/include/root/component.h @@ -164,10 +164,7 @@ class Genode::Root_component : public Rpc_object >, SESSION_TYPE *s = 0; try { s = _create_session(adjusted_args, affinity); } - catch (Allocator::Out_of_memory) { - error("out of memory for session creation, '", args, "'"); - throw Root::Unavailable(); - } + catch (Out_of_ram) { throw Insufficient_ram_quota(); } /* * Consider that the session-object constructor may already have diff --git a/repos/base/src/core/include/account.h b/repos/base/src/core/include/account.h new file mode 100644 index 0000000000..3e0c68b6db --- /dev/null +++ b/repos/base/src/core/include/account.h @@ -0,0 +1,175 @@ +/* + * \brief Resource account handling + * \author Norman Feske + * \date 2017-04-24 + */ + +/* + * Copyright (C) 2017 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 _CORE__INCLUDE__ACCOUNT_H_ +#define _CORE__INCLUDE__ACCOUNT_H_ + +#include +#include +#include + +namespace Genode { template class Account; } + + +template +class Genode::Account +{ + private: + + Quota_guard &_quota_guard; + + Session::Label const &_label; + + UNIT const _initial_used = _quota_guard.used(); + + Lock mutable _lock; + + /* + * Reference account + */ + Account *_ref_account = nullptr; + + /* + * Registry of accounts that have this account as their reference + * account. + */ + Registry _ref_account_members; + + /* + * Role as reference-account user + */ + Constructible::Element> _ref_account_member; + + /** + * Assign 'this' as reference account of 'account' + */ + void _adopt(Account &account) + { + account._ref_account_member.construct(_ref_account_members, account); + account._ref_account = this; + } + + public: + + typedef typename Quota_guard::Limit_exceeded Limit_exceeded; + + class Unrelated_account : Exception { }; + + /** + * Constructor for creating a regular account that is rechargeable by + * the specified reference account + */ + Account(Quota_guard "a_guard, Session_label const &label, + Account &ref_account) + : _quota_guard(quota_guard), _label(label) { ref_account._adopt(*this); } + + /** + * Constructor used for creating the initial account + */ + Account(Quota_guard "a_guard, Session_label const &label) + : _quota_guard(quota_guard), _label(label) { } + + ~Account() + { + if (!_ref_account) return; + + Lock::Guard guard(_lock); + + if (_quota_guard.used().value > _initial_used.value) { + UNIT const dangling { _quota_guard.used().value - _initial_used.value }; + warning("destroying account with allocated (possibly leaking?) " + "resources (", dangling, " ", UNIT::name(),")"); + _quota_guard.replenish(dangling); + } + + /* transfer remaining quota to our reference account */ + _ref_account->_quota_guard.upgrade(_quota_guard.limit()); + + /* assign all sub accounts to our reference account */ + _ref_account_members.for_each([&] (Account &orphan) { + _ref_account->_adopt(orphan); }); + } + + /** + * Transfer quota to/from other account + * + * \throw Unrelated_account + * \throw Limit_exceeded + */ + void transfer_quota(Account &other, UNIT amount) + { + { + Lock::Guard guard(_lock); + + /* transfers are permitted only from/to the reference account */ + if (_ref_account != &other && other._ref_account != this) + throw Unrelated_account(); + + /* downgrade from this account */ + if (!_quota_guard.try_downgrade(amount)) + throw Limit_exceeded(); + } + + /* credit to 'other' */ + Lock::Guard guard(other._lock); + other._quota_guard.upgrade(amount); + } + + UNIT limit() const + { + Lock::Guard guard(_lock); + return _quota_guard.limit(); + } + + UNIT used() const + { + Lock::Guard guard(_lock); + return _quota_guard.used(); + } + + UNIT avail() const + { + Lock::Guard guard(_lock); + return _quota_guard.avail(); + } + + /** + * Withdraw quota from account + * + * Called when allocating physical resources + * + * \throw Limit_exceeded + */ + void withdraw(UNIT amount) + { + Lock::Guard guard(_lock); + _quota_guard.withdraw(amount); + } + + /** + * Replenish quota to account + * + * Called when releasing physical resources + */ + void replenish(UNIT amount) + { + Lock::Guard guard(_lock); + _quota_guard.replenish(amount); + } + + void print(Output &out) const { Genode::print(out, _quota_guard); } + + Session::Label label() const { return _label; } +}; + +#endif /* _CORE__INCLUDE__ACCOUNT_H_ */ diff --git a/repos/base/src/core/include/core_env.h b/repos/base/src/core/include/core_env.h index 069eef2278..397396cd23 100644 --- a/repos/base/src/core/include/core_env.h +++ b/repos/base/src/core/include/core_env.h @@ -134,6 +134,14 @@ namespace Genode { Core_parent _core_parent { _heap, _services }; + typedef String<100> Ram_args; + + static Session::Resources _ram_resources() + { + return { Ram_quota { platform()->ram_alloc()->avail() }, + Cap_quota { platform()->max_caps() } }; + } + public: /** @@ -143,13 +151,18 @@ namespace Genode { : _entrypoint(nullptr, ENTRYPOINT_STACK_SIZE, "entrypoint"), _region_map(_entrypoint), - _ram_session(&_entrypoint, &_entrypoint, - platform()->ram_alloc(), platform()->core_mem_alloc(), - "ram_quota=4M", platform()->ram_alloc()->avail()), - _ram_session_cap(_entrypoint.manage(&_ram_session)), + _ram_session(_entrypoint, + _ram_resources(), + Session::Label("core"), + Session::Diag{false}, + *platform()->ram_alloc(), + _region_map, + Ram_session_component::any_phys_range()), _pd_session_component(_entrypoint), _pd_session_client(_entrypoint.manage(&_pd_session_component)) - { } + { + _ram_session.init_ram_account(); + } /** * Destructor diff --git a/repos/base/src/core/include/ram_root.h b/repos/base/src/core/include/ram_root.h index 4b92ff26f8..e15b978576 100644 --- a/repos/base/src/core/include/ram_root.h +++ b/repos/base/src/core/include/ram_root.h @@ -24,41 +24,50 @@ namespace Genode { { private: - Range_allocator *_ram_alloc; - Rpc_entrypoint *_ds_ep; + Rpc_entrypoint &_ep; + Range_allocator &_phys_alloc; + Region_map &_local_rm; + + static Ram_session_component::Phys_range phys_range_from_args(char const *args) + { + addr_t const start = Arg_string::find_arg(args, "phys_start").ulong_value(0); + addr_t const size = Arg_string::find_arg(args, "phys_size").ulong_value(0); + addr_t const end = start + size - 1; + + return (start <= end) ? Ram_session_component::Phys_range { start, end } + : Ram_session_component::any_phys_range(); + } protected: Ram_session_component *_create_session(const char *args) { return new (md_alloc()) - Ram_session_component(_ds_ep, ep(), _ram_alloc, - md_alloc(), args); + Ram_session_component(_ep, + session_resources_from_args(args), + session_label_from_args(args), + session_diag_from_args(args), + _phys_alloc, _local_rm, + phys_range_from_args(args)); } void _upgrade_session(Ram_session_component *ram, const char *args) { - size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0); - ram->upgrade_ram_quota(ram_quota); + ram->Ram_quota_guard::upgrade(ram_quota_from_args(args)); + ram->Cap_quota_guard::upgrade(cap_quota_from_args(args)); + ram->session_quota_upgraded(); } public: - /** - * Constructor - * - * \param session_ep entry point for managing ram session objects - * \param ds_ep entry point for managing dataspaces - * \param ram_alloc pool of memory to be assigned to ram sessions - * \param md_alloc meta-data allocator to be used by root component - */ - Ram_root(Rpc_entrypoint *session_ep, - Rpc_entrypoint *ds_ep, - Range_allocator *ram_alloc, - Allocator *md_alloc) + Ram_root(Rpc_entrypoint &ep, + Range_allocator &phys_alloc, + Region_map &local_rm, + Allocator &md_alloc) : - Root_component(session_ep, md_alloc), - _ram_alloc(ram_alloc), _ds_ep(ds_ep) { } + Root_component(&ep, &md_alloc), + _ep(ep), _phys_alloc(phys_alloc), _local_rm(local_rm) + { } }; } diff --git a/repos/base/src/core/include/ram_session_component.h b/repos/base/src/core/include/ram_session_component.h index e07b87eed1..025db5c633 100644 --- a/repos/base/src/core/include/ram_session_component.h +++ b/repos/base/src/core/include/ram_session_component.h @@ -18,25 +18,28 @@ #include #include #include -#include +#include #include #include +#include /* core includes */ #include #include +#include -namespace Genode { - - class Ram_session_component; - typedef List Ram_ref_account_members; -} +namespace Genode { class Ram_session_component; } -class Genode::Ram_session_component : public Rpc_object, - public Ram_ref_account_members::Element, +class Genode::Ram_session_component : public Session_object, public Dataspace_owner { + public: + + struct Phys_range { addr_t start, end; }; + + static Phys_range any_phys_range() { return { 0UL, ~0UL }; } + private: class Invalid_dataspace : public Exception { }; @@ -47,61 +50,46 @@ class Genode::Ram_session_component : public Rpc_object, */ static constexpr size_t SBS = get_page_size() - Sliced_heap::meta_data_size(); - using Ds_slab = Synced_allocator >; + using Ds_slab = Tslab; - Rpc_entrypoint *_ds_ep; - Rpc_entrypoint *_ram_session_ep; - Range_allocator *_ram_alloc; - size_t _quota_limit; - size_t _payload; /* quota used for payload */ - Allocator_guard _md_alloc; /* guarded meta-data allocator */ - Ds_slab _ds_slab; /* meta-data allocator */ - Ram_session_component *_ref_account; /* reference ram session */ - addr_t _phys_start; - addr_t _phys_end; + Rpc_entrypoint &_ep; - enum { MAX_LABEL_LEN = 64 }; - char _label[MAX_LABEL_LEN]; + Range_allocator &_phys_alloc; - /** - * List of RAM sessions that use us as their reference account + Constrained_ram_allocator _constrained_md_ram_alloc; + + Constructible _sliced_heap; + + /* + * Statically allocated initial slab block for '_ds_slab', needed to + * untangle the hen-and-egg problem of allocating the meta data for + * core's RAM allocator from itself. I also saves the allocation + * of one dataspace (along with a dataspace capability) per session. */ - Ram_ref_account_members _ref_members; - Lock _ref_members_lock; /* protect '_ref_members' */ + uint8_t _initial_sb[SBS]; - /** - * Register RAM session to use us as reference account - */ - void _register_ref_account_member(Ram_session_component *new_member); + Constructible _ds_slab; - /** - * Dissolve reference-account relationship of a member account - */ - void _remove_ref_account_member(Ram_session_component *member); - void _unsynchronized_remove_ref_account_member(Ram_session_component *member); + Phys_range const _phys_range; - /** - * Return portion of RAM quota that is currently in use - */ - size_t used_quota() { return _payload; } + Constructible > _ram_account; /** * Free dataspace */ void _free_ds(Dataspace_capability ds_cap); - /** - * Transfer quota to another RAM session - */ - void _transfer_quota(Ram_session_component *dst, size_t amount); - /******************************************** ** Platform-implemented support functions ** ********************************************/ + struct Core_virtual_memory_exhausted : Exception { }; + /** * Export RAM dataspace as shared memory block + * + * \throw Core_virtual_memory_exhausted */ void _export_ram_ds(Dataspace_component *ds); @@ -117,44 +105,24 @@ class Genode::Ram_session_component : public Rpc_object, public: - /** - * Constructor - * - * \param ds_ep server entry point to manage the - * dataspaces created by the Ram session - * \param ram_session_ep entry point that manages Ram sessions, - * used for looking up another ram session - * in transfer_quota() - * \param ram_alloc memory pool to manage - * \param md_alloc meta-data allocator - * \param md_ram_quota limit of meta-data backing store - * \param quota_limit initial quota limit - * - * The 'quota_limit' parameter is only used for the very - * first ram session in the system. All other ram session - * load their quota via 'transfer_quota'. - */ - Ram_session_component(Rpc_entrypoint *ds_ep, - Rpc_entrypoint *ram_session_ep, - Range_allocator *ram_alloc, - Allocator *md_alloc, - const char *args, - size_t quota_limit = 0); + Ram_session_component(Rpc_entrypoint &ep, + Resources resources, + Session_label const &label, + Diag diag, + Range_allocator &phys_alloc, + Region_map &local_rm, + Phys_range phys_range); - /** - * Destructor - */ ~Ram_session_component(); /** - * Accessors + * Initialize RAM account without providing a reference account + * + * This method is solely used to set up the initial RAM session within + * core. The RAM accounts of regular RAM session are initialized via + * 'ref_account'. */ - Ram_session_component *ref_account() { return _ref_account; } - - /** - * Register quota donation at allocator guard - */ - void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); } + void init_ram_account() { _ram_account.construct(*this, _label); } /** * Get physical address of the RAM that backs a dataspace @@ -181,10 +149,19 @@ class Genode::Ram_session_component : public Rpc_object, ** RAM Session interface ** ***************************/ - void ref_account(Ram_session_capability); - void transfer_quota(Ram_session_capability, Ram_quota); - Ram_quota ram_quota() const override { return { _quota_limit}; } - Ram_quota used_ram() const override { return { _payload}; } + void ref_account(Ram_session_capability) override; + + void transfer_quota(Ram_session_capability, Ram_quota) override; + + Ram_quota ram_quota() const override + { + return _ram_account.constructed() ? _ram_account->limit() : Ram_quota { 0 }; + } + + Ram_quota used_ram() const override + { + return _ram_account.constructed() ? _ram_account->used() : Ram_quota { 0 }; + } }; #endif /* _CORE__INCLUDE__RAM_SESSION_COMPONENT_H_ */ diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 4a479c3a18..7d01cba58a 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -140,9 +140,10 @@ class Core_child : public Child_policy /** * Constructor */ - Core_child(Registry &services, Ram_session &core_ram, - Capability core_ram_cap, Ram_quota ram_quota, - Cpu_session &core_cpu, Capability core_cpu_cap) + Core_child(Registry &services, + Ram_session &core_ram, Capability core_ram_cap, + Cpu_session &core_cpu, Capability core_cpu_cap, + Ram_quota ram_quota) : _entrypoint(nullptr, STACK_SIZE, "init_child", false), _services(services), @@ -249,11 +250,14 @@ int main() Registry &services = core_env()->services(); + static Ram_allocator &core_ram_alloc = *core_env()->ram_session(); + static Region_map &local_rm = *core_env()->rm_session(); + /* * Allocate session meta data on distinct dataspaces to enable independent * destruction (to enable quota trading) of session component objects. */ - static Sliced_heap sliced_heap(env_deprecated()->ram_session(), env_deprecated()->rm_session()); + static Sliced_heap sliced_heap(core_ram_alloc, local_rm); /* * Factory for creating RPC capabilities within core @@ -262,7 +266,7 @@ int main() static Pager_entrypoint pager_ep(rpc_cap_factory); - static Ram_root ram_root (e, e, platform()->ram_alloc(), &sliced_heap); + static Ram_root ram_root (*e, *platform()->ram_alloc(), local_rm, sliced_heap); static Rom_root rom_root (e, e, platform()->rom_fs(), &sliced_heap); static Rm_root rm_root (e, &sliced_heap, pager_ep); static Cpu_root cpu_root (e, e, &pager_ep, &sliced_heap, @@ -309,8 +313,10 @@ int main() "assigned to init"); static Reconstructible - init(services, *env_deprecated()->ram_session(), env_deprecated()->ram_session_cap(), - Ram_quota{avail_ram_quota}, core_cpu, core_cpu_cap); + init(services, + *env_deprecated()->ram_session(), env_deprecated()->ram_session_cap(), + core_cpu, core_cpu_cap, + Ram_quota{avail_ram_quota}); platform()->wait_for_exit(); diff --git a/repos/base/src/core/ram_session_component.cc b/repos/base/src/core/ram_session_component.cc index 4fedddb44e..ae8024773b 100644 --- a/repos/base/src/core/ram_session_component.cc +++ b/repos/base/src/core/ram_session_component.cc @@ -28,14 +28,14 @@ addr_t Ram_session_component::phys_addr(Ram_dataspace_capability ds) return dsc->phys_addr(); }; - return _ds_ep->apply(ds, lambda); + return _ep.apply(ds, lambda); } void Ram_session_component::_free_ds(Dataspace_capability ds_cap) { Dataspace_component *ds = nullptr; - _ds_ep->apply(ds_cap, [&] (Dataspace_component *c) + _ep.apply(ds_cap, [&] (Dataspace_component *c) { if (!c) return; if (!c->owner(this)) return; @@ -45,7 +45,7 @@ void Ram_session_component::_free_ds(Dataspace_capability ds_cap) size_t ds_size = ds->size(); /* tell entry point to forget the dataspace */ - _ds_ep->dissolve(ds); + _ep.dissolve(ds); /* remove dataspace from all RM sessions */ ds->detach_from_rm_sessions(); @@ -54,64 +54,14 @@ void Ram_session_component::_free_ds(Dataspace_capability ds_cap) _revoke_ram_ds(ds); /* free physical memory that was backing the dataspace */ - _ram_alloc->free((void *)ds->phys_addr(), ds_size); + _phys_alloc.free((void *)ds->phys_addr(), ds_size); - /* adjust payload */ - Lock::Guard lock_guard(_ref_members_lock); - _payload -= ds_size; + _ram_account->replenish(Ram_quota{ds_size}); }); /* call dataspace destructors and free memory */ if (ds) - destroy(&_ds_slab, ds); -} - - -void Ram_session_component::_transfer_quota(Ram_session_component *dst, size_t amount) -{ - /* check if recipient is a valid Ram_session_component */ - if (!dst) - throw Invalid_session(); - - /* check for reference account relationship */ - if ((ref_account() != dst) && (dst->ref_account() != this)) - throw Invalid_session(); - - /* decrease quota limit of this session - check against used quota */ - if (_quota_limit < amount + _payload) { - warning("insufficient quota for transfer: " - "'", Cstring(_label), "' to '", Cstring(dst->_label), "' " - "have ", (_quota_limit - _payload)/1024, " KiB, " - "need ", amount/1024, " KiB"); - throw Out_of_ram(); - } - - _quota_limit -= amount; - - /* increase quota_limit of recipient */ - dst->_quota_limit += amount; -} - - -void Ram_session_component::_register_ref_account_member(Ram_session_component *new_member) -{ - Lock::Guard lock_guard(_ref_members_lock); - _ref_members.insert(new_member); - new_member->_ref_account = this; -} - - -void Ram_session_component::_unsynchronized_remove_ref_account_member(Ram_session_component *member) -{ - member->_ref_account = 0; - _ref_members.remove(member); -} - - -void Ram_session_component::_remove_ref_account_member(Ram_session_component *member) -{ - Lock::Guard lock_guard(_ref_members_lock); - _unsynchronized_remove_ref_account_member(member); + destroy(*_ds_slab, ds); } @@ -124,14 +74,23 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr ds_size = align_addr(ds_size, 12); /* - * Check quota! + * Track quota usage * - * In the worst case, we need to allocate a new slab block for the - * meta data of the dataspace to be created - therefore, we add - * the slab block size here. + * We use a guard to roll back the withdrawal of the quota whenever + * we leave the method scope via an exception. The withdrawal is + * acknowledge just before successfully leaving the method. */ - if (used_quota() + SBS + ds_size > _quota_limit) - throw Quota_exceeded(); + Ram_quota_guard::Reservation dataspace_ram_costs(*this, Ram_quota{ds_size}); + + /* + * In the worst case, we need to allocate a new slab block for the + * meta data of the dataspace to be created. Therefore, we temporarily + * withdraw the slab block size here to trigger an exception if the + * account does not have enough room for the meta data. + */ + { + Ram_quota_guard::Reservation sbs_ram_costs(*this, Ram_quota{SBS}); + } /* * Allocate physical backing store @@ -150,11 +109,11 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr * preserve lower physical regions for device drivers, which may have DMA * constraints. */ - if (_phys_start == 0 && _phys_end == ~0UL) { + if (_phys_range.start == 0 && _phys_range.end == ~0UL) { addr_t const high_start = (sizeof(void *) == 4 ? 3UL : 4UL) << 30; for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) { - if (_ram_alloc->alloc_aligned(ds_size, &ds_addr, align_log2, - high_start, _phys_end).ok()) { + if (_phys_alloc.alloc_aligned(ds_size, &ds_addr, align_log2, + high_start, _phys_range.end).ok()) { alloc_succeeded = true; break; } @@ -164,14 +123,31 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr /* apply constraints or re-try because higher memory allocation failed */ if (!alloc_succeeded) { for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) { - if (_ram_alloc->alloc_aligned(ds_size, &ds_addr, align_log2, - _phys_start, _phys_end).ok()) { + if (_phys_alloc.alloc_aligned(ds_size, &ds_addr, align_log2, + _phys_range.start, _phys_range.end).ok()) { alloc_succeeded = true; break; } } } + /* + * Helper to release the allocated physical memory whenever we leave the + * scope via an exception. + */ + struct Phys_alloc_guard + { + Range_allocator &phys_alloc; + void * const ds_addr; + bool ack = false; + + Phys_alloc_guard(Range_allocator &phys_alloc, void *ds_addr) + : phys_alloc(phys_alloc), ds_addr(ds_addr) { } + + ~Phys_alloc_guard() { if (!ack) phys_alloc.free(ds_addr); } + + } phys_alloc_guard(_phys_alloc, ds_addr); + /* * Normally, init's quota equals the size of physical memory and this quota * is distributed among the processes. As we check the quota before @@ -180,38 +156,29 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr */ if (!alloc_succeeded) { error("out of physical memory while allocating ", ds_size, " bytes ", - "in range [", Hex(_phys_start), "-", Hex(_phys_end), "] - label ", - Cstring(_label)); - throw Quota_exceeded(); + "in range [", Hex(_phys_range.start), "-", Hex(_phys_range.end), "]"); + throw Out_of_ram(); } - Dataspace_component *ds; - try { - /* - * For non-cached RAM dataspaces, we mark the dataspace as write - * combined and expect the pager to evaluate this dataspace property - * when resolving page faults. - */ - ds = new (&_ds_slab) - Dataspace_component(ds_size, (addr_t)ds_addr, cached, true, this); - } catch (Allocator::Out_of_memory) { - warning("could not allocate metadata"); - /* cleanup unneeded resources */ - _ram_alloc->free(ds_addr); - - throw Out_of_metadata(); - } + /* + * For non-cached RAM dataspaces, we mark the dataspace as write + * combined and expect the pager to evaluate this dataspace property + * when resolving page faults. + * + * \throw Out_of_ram + * \throw Out_of_caps + */ + Dataspace_component *ds = new (*_ds_slab) + Dataspace_component(ds_size, (addr_t)ds_addr, cached, true, this); /* create native shared memory representation of dataspace */ - try { - _export_ram_ds(ds); - } catch (Out_of_metadata) { + try { _export_ram_ds(ds); } + catch (Core_virtual_memory_exhausted) { warning("could not export RAM dataspace of size ", ds->size()); - /* cleanup unneeded resources */ - destroy(&_ds_slab, ds); - _ram_alloc->free(ds_addr); - throw Quota_exceeded(); + /* cleanup unneeded resources */ + destroy(*_ds_slab, ds); + throw Out_of_ram(); } /* @@ -221,18 +188,19 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr */ _clear_ds(ds); - Dataspace_capability result = _ds_ep->manage(ds); + Dataspace_capability result = _ep.manage(ds); - Lock::Guard lock_guard(_ref_members_lock); - /* keep track of the used quota for actual payload */ - _payload += ds_size; + dataspace_ram_costs.acknowledge(); + phys_alloc_guard.ack = true; return static_cap_cast(result); } -void Ram_session_component::free(Ram_dataspace_capability ds_cap) { - _free_ds(ds_cap); } +void Ram_session_component::free(Ram_dataspace_capability ds_cap) +{ + _free_ds(ds_cap); +} size_t Ram_session_component::dataspace_size(Ram_dataspace_capability ds_cap) const @@ -241,7 +209,7 @@ size_t Ram_session_component::dataspace_size(Ram_dataspace_capability ds_cap) co return 0; size_t result = 0; - _ds_ep->apply(ds_cap, [&] (Dataspace_component *c) { + _ep.apply(ds_cap, [&] (Dataspace_component *c) { if (c && c->owner(this)) result = c->size(); }); @@ -251,102 +219,76 @@ size_t Ram_session_component::dataspace_size(Ram_dataspace_capability ds_cap) co void Ram_session_component::ref_account(Ram_session_capability ram_session_cap) { - /* the reference account cannot be defined twice */ - if (_ref_account) + /* the reference account can be defined only once */ + if (_ram_account.constructed()) return; if (this->cap() == ram_session_cap) return; - auto lambda = [this] (Ram_session_component *ref) { + _ep.apply(ram_session_cap, [&] (Ram_session_component *ram) { - /* check if recipient is a valid Ram_session_component */ - if (!ref) + if (!ram || !ram->_ram_account.constructed()) { + error("invalid RAM session specified as ref account"); throw Invalid_session(); + } - _ref_account = ref; - _ref_account->_register_ref_account_member(this); - }; - - _ram_session_ep->apply(ram_session_cap, lambda); + _ram_account.construct(*this, _label, *ram->_ram_account); + }); } void Ram_session_component::transfer_quota(Ram_session_capability ram_session_cap, Ram_quota amount) { - auto lambda = [&] (Ram_session_component *dst) { - _transfer_quota(dst, amount.value); }; + /* the reference account can be defined only once */ + if (!_ram_account.constructed()) + throw Undefined_ref_account(); if (this->cap() == ram_session_cap) return; - return _ram_session_ep->apply(ram_session_cap, lambda); + _ep.apply(ram_session_cap, [&] (Ram_session_component *ram) { + + if (!ram || !ram->_ram_account.constructed()) + throw Invalid_session(); + + try { + _ram_account->transfer_quota(*ram->_ram_account, amount); } + catch (Account::Unrelated_account) { + warning("attempt to transfer RAM quota to unrelated RAM session"); + throw Invalid_session(); } + catch (Account::Limit_exceeded) { + warning("RAM limit (", *_ram_account, ") exceeded " + "during transfer_quota(", amount, ")"); + throw Out_of_ram(); } + }); } -Ram_session_component::Ram_session_component(Rpc_entrypoint *ds_ep, - Rpc_entrypoint *ram_session_ep, - Range_allocator *ram_alloc, - Allocator *md_alloc, - const char *args, - size_t quota_limit) +Ram_session_component::Ram_session_component(Rpc_entrypoint &ep, + Resources resources, + Label const &label, + Diag diag, + Range_allocator &phys_alloc, + Region_map &local_rm, + Phys_range phys_range) : - _ds_ep(ds_ep), _ram_session_ep(ram_session_ep), _ram_alloc(ram_alloc), - _quota_limit(quota_limit), _payload(0), - _md_alloc(md_alloc, Arg_string::find_arg(args, "ram_quota").ulong_value(0)), - _ds_slab(&_md_alloc), _ref_account(0), - _phys_start(Arg_string::find_arg(args, "phys_start").ulong_value(0)) + Session_object(ep, resources, label, diag), + _ep(ep), + _phys_alloc(phys_alloc), + _constrained_md_ram_alloc(*this, *this, *this), + _phys_range(phys_range) { - Arg_string::find_arg(args, "label").string(_label, sizeof(_label), ""); - - size_t phys_size = Arg_string::find_arg(args, "phys_size").ulong_value(0); - /* sanitize overflow and interpret phys_size==0 as maximum phys address */ - if (_phys_start + phys_size <= _phys_start) - _phys_end = ~0UL; - else - _phys_end = _phys_start + phys_size - 1; + _sliced_heap.construct(_constrained_md_ram_alloc, local_rm); + _ds_slab.construct(*_sliced_heap, _initial_sb); } Ram_session_component::~Ram_session_component() { /* destroy all dataspaces */ - for (Dataspace_component *ds; (ds = _ds_slab()->first_object()); + Ds_slab &ds_slab = *_ds_slab; + for (Dataspace_component *ds; (ds = ds_slab.first_object()); _free_ds(ds->cap())); - - if (_payload != 0) - warning("remaining payload of ", _payload, " in ram session to destroy"); - - if (!_ref_account) return; - - /* transfer remaining quota to reference account */ - try { _transfer_quota(_ref_account, _quota_limit); } catch (...) { } - - /* remember our original reference account */ - Ram_session_component *orig_ref_account = _ref_account; - - /* remove reference to us from the reference account */ - _ref_account->_remove_ref_account_member(this); - - /* - * Now, the '_ref_account' member has become invalid. - */ - - Lock::Guard lock_guard(_ref_members_lock); - - /* assign all sub accounts to our original reference account */ - for (Ram_session_component *rsc; (rsc = _ref_members.first()); ) { - - _unsynchronized_remove_ref_account_member(rsc); - - /* - * This function grabs the '_ref_account_lock' of the '_ref_account', - * which is never identical to ourself. Hence, deadlock cannot happen - * here. - */ - orig_ref_account->_register_ref_account_member(rsc); - } - - _ref_account = 0; } diff --git a/repos/base/src/include/base/internal/expanding_parent_client.h b/repos/base/src/include/base/internal/expanding_parent_client.h index 989a7120c6..273fc9a495 100644 --- a/repos/base/src/include/base/internal/expanding_parent_client.h +++ b/repos/base/src/include/base/internal/expanding_parent_client.h @@ -108,8 +108,8 @@ class Genode::Expanding_parent_client : public Parent_client * immediately. The second upgrade attempt may fail too if the * parent handles the resource request asynchronously. In this * case, we escalate the problem to caller by propagating the - * 'Parent::Quota_exceeded' exception. Now, it is the job of the - * caller to issue (and respond to) a resource request. + * 'Out_of_ram' exception. Now, it is the job of the caller to + * issue (and respond to) a resource request. */ enum { NUM_ATTEMPTS = 2 }; return retry( diff --git a/repos/base/src/include/base/internal/expanding_ram_session_client.h b/repos/base/src/include/base/internal/expanding_ram_session_client.h index 60b216f2c1..979d8216ef 100644 --- a/repos/base/src/include/base/internal/expanding_ram_session_client.h +++ b/repos/base/src/include/base/internal/expanding_ram_session_client.h @@ -41,16 +41,8 @@ struct Genode::Expanding_ram_session_client : Upgradeable_client( - [&] () { - /* - * If the RAM session runs out of meta data, upgrade the - * session quota and retry. - */ - return retry( - [&] () { return Ram_session_client::alloc(size, cached); }, - [&] () { upgrade_ram(8*1024); }); - }, + return retry( + [&] () { return Ram_session_client::alloc(size, cached); }, [&] () { /* * The RAM service withdraws the meta data for the allocator diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 1c2474abe1..2b2e694901 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -87,6 +87,7 @@ void Child::session_sigh(Signal_context_capability sigh) /** * Create session-state object for a dynamically created session * + * \throw Out_of_ram * \throw Insufficient_ram_quota * \throw Parent::Service_denied */ @@ -648,7 +649,6 @@ void Child::_try_construct_env_dependent_members() _parent_cap); } catch (Out_of_ram) { _error("out of RAM during ELF loading"); } - catch (Ram_session::Alloc_failed) { _error("RAM allocation failed during ELF loading"); } catch (Cpu_session::Thread_creation_failed) { _error("unable to create initial thread"); } catch (Cpu_session::Out_of_metadata) { _error("CPU session quota exhausted"); } catch (Process::Missing_dynamic_linker) { _error("dynamic linker unavailable"); } diff --git a/repos/base/src/lib/base/child_process.cc b/repos/base/src/lib/base/child_process.cc index ccdcb1123c..dfe1c34d95 100644 --- a/repos/base/src/lib/base/child_process.cc +++ b/repos/base/src/lib/base/child_process.cc @@ -102,7 +102,7 @@ Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds /* alloc dataspace */ Dataspace_capability ds_cap; try { ds_cap = ram.alloc(size); } - catch (Ram_session::Alloc_failed) { + catch (Out_of_ram) { error("allocation of read-write segment failed"); throw; }; /* attach dataspace */ diff --git a/repos/base/src/lib/base/heap.cc b/repos/base/src/lib/base/heap.cc index 91e32be3b8..aa0a1d7602 100644 --- a/repos/base/src/lib/base/heap.cc +++ b/repos/base/src/lib/base/heap.cc @@ -89,9 +89,9 @@ Heap::Dataspace *Heap::_allocate_dataspace(size_t size, bool enforce_separate_me try { new_ds_cap = _ds_pool.ram_alloc->alloc(size); ds_addr = _ds_pool.region_map->attach(new_ds_cap); - } catch (Ram_session::Alloc_failed) { - return 0; - } catch (Region_map::Attach_failed) { + } + catch (Out_of_ram) { return nullptr; } + catch (Region_map::Attach_failed) { warning("could not attach dataspace"); _ds_pool.ram_alloc->free(new_ds_cap); return 0; diff --git a/repos/base/src/lib/base/sliced_heap.cc b/repos/base/src/lib/base/sliced_heap.cc index dacb74ad4c..d48b88c262 100644 --- a/repos/base/src/lib/base/sliced_heap.cc +++ b/repos/base/src/lib/base/sliced_heap.cc @@ -49,11 +49,13 @@ bool Sliced_heap::alloc(size_t size, void **out_addr) try { ds_cap = _ram_alloc.alloc(size); block = _region_map.attach(ds_cap); - } catch (Region_map::Attach_failed) { + } + catch (Region_map::Attach_failed) { error("could not attach dataspace to local address space"); _ram_alloc.free(ds_cap); return false; - } catch (Ram_allocator::Alloc_failed) { + } + catch (Out_of_ram) { error("could not allocate dataspace with size ", size); return false; } diff --git a/repos/base/src/lib/base/thread.cc b/repos/base/src/lib/base/thread.cc index 7e5a5cccab..ba810465ae 100644 --- a/repos/base/src/lib/base/thread.cc +++ b/repos/base/src/lib/base/thread.cc @@ -65,9 +65,7 @@ void Stack::size(size_t const size) if (ds_addr != (addr_t)attach_addr) throw Thread::Out_of_stack_space(); } - catch (Ram_session::Alloc_failed) { - throw Thread::Stack_alloc_failed(); - } + catch (Out_of_ram) { throw Thread::Stack_alloc_failed(); } /* update stack information */ _base -= ds_size; @@ -110,7 +108,7 @@ Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread) if (attach_addr != (addr_t)env_stack_area_region_map->attach_at(ds_cap, attach_addr, ds_size)) throw Stack_alloc_failed(); } - catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); } + catch (Out_of_ram) { throw Stack_alloc_failed(); } /* * Now the stack is backed by memory, so it is safe to access its members. diff --git a/repos/dde_rump/include/util/allocator_fap.h b/repos/dde_rump/include/util/allocator_fap.h index 793475caa9..333a2dea68 100644 --- a/repos/dde_rump/include/util/allocator_fap.h +++ b/repos/dde_rump/include/util/allocator_fap.h @@ -90,7 +90,7 @@ namespace Allocator { Region_map_client::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0); /* lookup phys. address */ _ds_phys[_index] = Genode::Dataspace_client(_ds_cap[_index]).phys_addr(); - } catch (Genode::Ram_session::Quota_exceeded) { + } catch (Genode::Out_of_ram) { warning("backend allocator exhausted"); _quota_exceeded = true; return false; diff --git a/repos/libports/src/lib/libc/libc_mem_alloc.cc b/repos/libports/src/lib/libc/libc_mem_alloc.cc index 8a6c3a6110..f817be715c 100644 --- a/repos/libports/src/lib/libc/libc_mem_alloc.cc +++ b/repos/libports/src/lib/libc/libc_mem_alloc.cc @@ -55,9 +55,10 @@ int Libc::Mem_alloc_impl::Dataspace_pool::expand(size_t size, Range_allocator *a try { new_ds_cap = _ram_session->alloc(size); local_addr = _region_map->attach(new_ds_cap); - } catch (Ram_session::Alloc_failed) { - return -2; - } catch (Region_map::Attach_failed) { + } + catch (Out_of_ram) { return -2; } + catch (Out_of_caps) { return -4; } + catch (Region_map::Attach_failed) { _ram_session->free(new_ds_cap); return -3; } diff --git a/repos/os/include/os/dynamic_rom_session.h b/repos/os/include/os/dynamic_rom_session.h index dc5fe82710..510e840606 100644 --- a/repos/os/include/os/dynamic_rom_session.h +++ b/repos/os/include/os/dynamic_rom_session.h @@ -83,9 +83,9 @@ class Genode::Dynamic_rom_session : public Rpc_object ds_reallocated = true; } } - catch (Ram_session::Quota_exceeded) { + catch (Out_of_ram) { - error("ouf of child quota while delivering dynamic ROM"); + error("ouf of child RAM quota while delivering dynamic ROM"); /* * XXX We may try to generate a resource request on @@ -98,10 +98,6 @@ class Genode::Dynamic_rom_session : public Rpc_object */ return true; } - catch (Ram_session::Out_of_metadata) { - error("ouf of RAM session quota while delivering dynamic ROM"); - return true; - } try { _content_producer.produce_content(_ds->local_addr(), diff --git a/repos/os/include/os/ram_session_guard.h b/repos/os/include/os/ram_session_guard.h index 7124bf817b..33ea69e8c2 100644 --- a/repos/os/include/os/ram_session_guard.h +++ b/repos/os/include/os/ram_session_guard.h @@ -96,7 +96,7 @@ class Genode::Ram_session_guard : public Genode::Ram_session Cache_attribute cached = CACHED) override { if (_used + size <= _used || _used + size > _quota) - throw Quota_exceeded(); + throw Out_of_ram(); Ram_dataspace_capability cap = _session.alloc(size, cached); diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index 9425c0593e..1b508d1f8d 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -330,7 +330,7 @@ class Platform::Session_component : public Genode::Rpc_object /* thrown by 'Quota_reservation' */ catch (Out_of_metadata) { throw; } /* thrown by 'Device_pd_policy' or 'Child' */ - catch (Genode::Ram_session::Alloc_failed) { throw Out_of_metadata(); } + catch (Genode::Out_of_ram) { throw Out_of_metadata(); } /* throw by 'Slave::Connection' */ catch (Genode::Insufficient_ram_quota) { throw Out_of_metadata(); } @@ -373,7 +373,7 @@ class Platform::Session_component : public Genode::Rpc_object } /* thrown by '_md_alloc' */ - catch (Genode::Allocator::Out_of_memory) { throw Out_of_metadata(); } + catch (Genode::Out_of_ram) { throw Out_of_metadata(); } /* thrown by 'Device_pd' */ catch (Out_of_metadata) { throw; } @@ -944,25 +944,25 @@ class Platform::Session_component : public Genode::Rpc_object /* transfer ram quota to session specific ram session */ try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{size}); } + catch (Genode::Out_of_ram) { throw Out_of_metadata(); } catch (...) { throw Fatal(); } enum { UPGRADE_QUOTA = 4096 }; /* allocate dataspace from session specific ram session */ - Ram_capability ram_cap = Genode::retry( + Ram_capability ram_cap = Genode::retry( [&] () { - Ram_capability ram = Genode::retry( - [&] () { return _ram.alloc(size, Genode::UNCACHED); }, - [&] () { - if (!_env_ram.withdraw(UPGRADE_QUOTA)) { - _rollback(size); - } + try { + return _ram.alloc(size, Genode::UNCACHED); + } + catch (Genode::Out_of_ram) { - /* upgrade meta-data quota */ - _ram.upgrade_ram(UPGRADE_QUOTA); - }); + if (!_env_ram.withdraw(UPGRADE_QUOTA)) + _rollback(size); + + throw; + } - return ram; }, [&] () { /* @@ -973,7 +973,7 @@ class Platform::Session_component : public Genode::Rpc_object * UPGRADE_QUOTA steps. */ try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{UPGRADE_QUOTA}); } - catch (...) { throw Out_of_metadata(); } + catch (...) { throw Genode::Out_of_ram(); } }); if (!ram_cap.valid()) diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc index 03cdc2d448..5d8816e33d 100644 --- a/repos/os/src/init/main.cc +++ b/repos/os/src/init/main.cc @@ -297,7 +297,7 @@ void Init::Main::_handle_config() if (used_ram.value > avail_ram.value) { error("RAM exhausted while starting childen"); - throw Ram_session::Alloc_failed(); + throw Out_of_ram(); } try { @@ -326,8 +326,6 @@ void Init::Main::_handle_config() } catch (Out_of_ram) { warning("memory exhausted during child creation"); } - catch (Ram_session::Alloc_failed) { - warning("failed to allocate memory during child construction"); } catch (Child::Missing_name_attribute) { warning("skipped startup of nameless child"); } catch (Region_map::Attach_failed) { diff --git a/repos/os/src/server/nic_bridge/component.h b/repos/os/src/server/nic_bridge/component.h index 70009b3c24..0141c83208 100644 --- a/repos/os/src/server/nic_bridge/component.h +++ b/repos/os/src/server/nic_bridge/component.h @@ -220,7 +220,7 @@ class Net::Root : public Genode::Root_component } catch (Mac_allocator::Alloc_failed) { Genode::warning("Mac address allocation failed!"); throw Root::Unavailable(); - } catch(Ram_session::Quota_exceeded) { + } catch (Out_of_ram) { Genode::warning("insufficient 'ram_quota'"); throw Insufficient_ram_quota(); }