From cf9610a9582d40f72d528b7ca29b6a4dd9829b48 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Wed, 2 May 2012 14:42:47 +0200 Subject: [PATCH] Implement RAM accounting --- base/include/ram_session/ram_session.h | 2 +- os/src/server/loader/child.h | 11 ++- os/src/server/loader/main.cc | 56 ++++++----- .../server/loader/ram_session_client_guard.h | 94 +++++++++++++++++++ 4 files changed, 133 insertions(+), 30 deletions(-) create mode 100644 os/src/server/loader/ram_session_client_guard.h diff --git a/base/include/ram_session/ram_session.h b/base/include/ram_session/ram_session.h index 4e65bddf4..15a8adf81 100644 --- a/base/include/ram_session/ram_session.h +++ b/base/include/ram_session/ram_session.h @@ -77,7 +77,7 @@ namespace Genode { virtual int ref_account(Ram_session_capability ram_session) = 0; /** - * Transfer quota the another ram session + * Transfer quota to another RAM session * * \param ram_session receiver of quota donation * \param amount amount of quota to donate diff --git a/os/src/server/loader/child.h b/os/src/server/loader/child.h index 13c0192c4..d1602add2 100644 --- a/os/src/server/loader/child.h +++ b/os/src/server/loader/child.h @@ -44,7 +44,9 @@ namespace Loader { Cpu_connection cpu; Rm_connection rm; - Resources(char const *label, size_t ram_quota) + Resources(char const *label, + Ram_session_client &ram_session_client, + size_t ram_quota) : ram(label), cpu(label) { /* deduce session costs from usable ram quota */ @@ -56,8 +58,8 @@ namespace Loader { ram_quota -= session_donations; else ram_quota = 0; - ram.ref_account(env()->ram_session_cap()); - env()->ram_session()->transfer_quota(ram.cap(), ram_quota); + ram.ref_account(ram_session_client); + ram_session_client.transfer_quota(ram.cap(), ram_quota); } } _resources; @@ -87,6 +89,7 @@ namespace Loader { Child(const char *binary_name, const char *label, Rpc_entrypoint &ep, + Ram_session_client &ram_session_client, size_t ram_quota, Service_registry &parent_services, Service &local_rom_service, @@ -95,7 +98,7 @@ namespace Loader { : _label(label), _ep(ep), - _resources(_label.string, ram_quota), + _resources(_label.string, ram_session_client, ram_quota), _parent_services(parent_services), _local_nitpicker_service(local_nitpicker_service), _local_rom_service(local_rom_service), diff --git a/os/src/server/loader/main.cc b/os/src/server/loader/main.cc index bc03576c2..81e3945b8 100644 --- a/os/src/server/loader/main.cc +++ b/os/src/server/loader/main.cc @@ -13,6 +13,7 @@ /* Genode includes */ #include +#include #include #include #include @@ -24,6 +25,7 @@ /* local includes */ #include #include +#include #include @@ -39,6 +41,7 @@ namespace Loader { struct Local_rom_service : Service { Rpc_entrypoint &_ep; + Allocator &_md_alloc; Parent_service _parent_rom_service; Rom_module_registry &_rom_modules; Lock _lock; @@ -47,15 +50,17 @@ namespace Loader { void _close(Rom_session_component *rom) { _ep.dissolve(rom); - destroy(env()->heap(), rom); + destroy(&_md_alloc, rom); _rom_sessions.remove(rom); } Local_rom_service(Rpc_entrypoint &ep, + Allocator &md_alloc, Rom_module_registry &rom_modules) : Service("virtual_rom"), _ep(ep), + _md_alloc(md_alloc), _parent_rom_service(Rom_session::service_name()), _rom_modules(rom_modules) { } @@ -82,7 +87,7 @@ namespace Loader { Rom_module &module = _rom_modules.lookup_and_lock(name); - Rom_session_component *rom = new (env()->heap()) + Rom_session_component *rom = new (&_md_alloc) Rom_session_component(module); _rom_sessions.insert(rom); @@ -118,14 +123,19 @@ namespace Loader { struct Local_nitpicker_service : Service { Rpc_entrypoint &ep; + Allocator &_md_alloc; Signal_context_capability view_ready_sigh; Nitpicker::Session_component *open_session; - Local_nitpicker_service(Rpc_entrypoint &ep) + Local_nitpicker_service(Rpc_entrypoint &ep, + Allocator &md_alloc) : - Service("virtual_nitpicker"), ep(ep), open_session(0) + Service("virtual_nitpicker"), + ep(ep), + _md_alloc(md_alloc), + open_session(0) { } ~Local_nitpicker_service() @@ -134,7 +144,7 @@ namespace Loader { return; ep.dissolve(open_session); - destroy(env()->heap(), open_session); + destroy(&_md_alloc, open_session); } Genode::Session_capability session(const char *args) @@ -142,11 +152,7 @@ namespace Loader { if (open_session) throw Unavailable(); - /* - * XXX replace allocation from 'env()->heap()' with - * use of session-specific allocator - */ - open_session = new (env()->heap()) + open_session = new (&_md_alloc) Nitpicker::Session_component(ep, view_ready_sigh, args); return ep.manage(open_session); @@ -158,6 +164,8 @@ namespace Loader { enum { STACK_SIZE = 2*4096 }; size_t _ram_quota; + Ram_session_client_guard _ram_session_client; + Heap _md_alloc; size_t _subsystem_ram_quota_limit; int _width, _height; Rpc_entrypoint _ep; @@ -186,19 +194,21 @@ namespace Loader { Session_component(size_t quota, Ram_session &ram, Cap_session &cap) : _ram_quota(quota), - _subsystem_ram_quota_limit(~0), + _ram_session_client(env()->ram_session_cap(), _ram_quota), + _md_alloc(&_ram_session_client, env()->rm_session()), + _subsystem_ram_quota_limit(0), _width(-1), _height(-1), _ep(&cap, STACK_SIZE, "session_ep"), - _rom_modules(ram, *env()->heap()), /* XXX remove env()->heap() */ - _rom_service(_ep, _rom_modules), - _nitpicker_service(_ep), + _rom_modules(_ram_session_client, _md_alloc), + _rom_service(_ep, _md_alloc, _rom_modules), + _nitpicker_service(_ep, _md_alloc), _child(0) { } ~Session_component() { if (_child) - destroy(env()->heap(), _child); + destroy(&_md_alloc, _child); } @@ -241,18 +251,14 @@ namespace Loader { return; } - /* - * XXX account for ROM modules - */ - size_t const ram_quota = _subsystem_ram_quota_limit; + size_t const ram_quota = (_subsystem_ram_quota_limit > 0) ? + min(_subsystem_ram_quota_limit, _ram_session_client.avail()) : + _ram_session_client.avail(); - /* - * XXX don't use 'env()->heap()' - */ - _child = new (env()->heap()) + _child = new (&_md_alloc) Child(binary_name.string(), label.string(), _ep, - ram_quota, _parent_services, _rom_service, - _nitpicker_service, _width, _height); + _ram_session_client, ram_quota, _parent_services, + _rom_service, _nitpicker_service, _width, _height); } Nitpicker::View_capability view() diff --git a/os/src/server/loader/ram_session_client_guard.h b/os/src/server/loader/ram_session_client_guard.h new file mode 100644 index 000000000..e97d39a5d --- /dev/null +++ b/os/src/server/loader/ram_session_client_guard.h @@ -0,0 +1,94 @@ +/* + * \brief A guard for RAM session clients to limit memory exhaustion + * \author Christian Prochaska + * \date 2012-04-25 + */ + +/* + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _RAM_SESSION_CLIENT_GUARD_H_ +#define _RAM_SESSION_CLIENT_GUARD_H_ + +#include +#include +#include +#include + +namespace Genode { + + class Ram_session_client_guard : public Ram_session_client + { + private: + + size_t _amount; /* total amount */ + size_t _consumed; /* already consumed bytes */ + Lock _consumed_lock; + + public: + + Ram_session_client_guard(Ram_session_capability session, size_t amount) + : Ram_session_client(session), _amount(amount), _consumed(0) { } + + Ram_dataspace_capability alloc(size_t size) + { + Lock::Guard _consumed_lock_guard(_consumed_lock); + + if ((_amount - _consumed) < size) { + PWRN("Quota exceeded! amount=%zu, size=%zu, consumed=%zu", + _amount, size, _consumed); + return Ram_dataspace_capability(); + } + + Ram_dataspace_capability cap = Ram_session_client::alloc(size); + + _consumed += size; + + return cap; + } + + void free(Ram_dataspace_capability ds) + { + Lock::Guard _consumed_lock_guard(_consumed_lock); + + _consumed -= Dataspace_client(ds).size(); + + Ram_session_client::free(ds); + } + + int transfer_quota(Ram_session_capability ram_session, size_t amount) + { + Lock::Guard _consumed_lock_guard(_consumed_lock); + + if ((_amount - _consumed) < amount) { + PWRN("Quota exceeded! amount=%zu, size=%zu, consumed=%zu", + _amount, amount, _consumed); + return -1; + } + + int result = Ram_session_client::transfer_quota(ram_session, amount); + + if (result == 0) + _consumed += amount; + + return result; + } + + size_t quota() + { + return _amount; + } + + size_t used() + { + Lock::Guard _consumed_lock_guard(_consumed_lock); + return _consumed; + } + }; +} + +#endif /* _RAM_SESSION_CLIENT_GUARD_H_ */