Implement RAM accounting

This commit is contained in:
Christian Prochaska 2012-05-02 14:42:47 +02:00 committed by Norman Feske
parent bcf6714eff
commit cf9610a958
4 changed files with 133 additions and 30 deletions

View File

@ -77,7 +77,7 @@ namespace Genode {
virtual int ref_account(Ram_session_capability ram_session) = 0; 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 ram_session receiver of quota donation
* \param amount amount of quota to donate * \param amount amount of quota to donate

View File

@ -44,7 +44,9 @@ namespace Loader {
Cpu_connection cpu; Cpu_connection cpu;
Rm_connection rm; 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) : ram(label), cpu(label)
{ {
/* deduce session costs from usable ram quota */ /* deduce session costs from usable ram quota */
@ -56,8 +58,8 @@ namespace Loader {
ram_quota -= session_donations; ram_quota -= session_donations;
else ram_quota = 0; else ram_quota = 0;
ram.ref_account(env()->ram_session_cap()); ram.ref_account(ram_session_client);
env()->ram_session()->transfer_quota(ram.cap(), ram_quota); ram_session_client.transfer_quota(ram.cap(), ram_quota);
} }
} _resources; } _resources;
@ -87,6 +89,7 @@ namespace Loader {
Child(const char *binary_name, Child(const char *binary_name,
const char *label, const char *label,
Rpc_entrypoint &ep, Rpc_entrypoint &ep,
Ram_session_client &ram_session_client,
size_t ram_quota, size_t ram_quota,
Service_registry &parent_services, Service_registry &parent_services,
Service &local_rom_service, Service &local_rom_service,
@ -95,7 +98,7 @@ namespace Loader {
: :
_label(label), _label(label),
_ep(ep), _ep(ep),
_resources(_label.string, ram_quota), _resources(_label.string, ram_session_client, ram_quota),
_parent_services(parent_services), _parent_services(parent_services),
_local_nitpicker_service(local_nitpicker_service), _local_nitpicker_service(local_nitpicker_service),
_local_rom_service(local_rom_service), _local_rom_service(local_rom_service),

View File

@ -13,6 +13,7 @@
/* Genode includes */ /* Genode includes */
#include <base/env.h> #include <base/env.h>
#include <base/heap.h>
#include <base/rpc_server.h> #include <base/rpc_server.h>
#include <base/signal.h> #include <base/signal.h>
#include <base/sleep.h> #include <base/sleep.h>
@ -24,6 +25,7 @@
/* local includes */ /* local includes */
#include <child.h> #include <child.h>
#include <nitpicker.h> #include <nitpicker.h>
#include <ram_session_client_guard.h>
#include <rom.h> #include <rom.h>
@ -39,6 +41,7 @@ namespace Loader {
struct Local_rom_service : Service struct Local_rom_service : Service
{ {
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Allocator &_md_alloc;
Parent_service _parent_rom_service; Parent_service _parent_rom_service;
Rom_module_registry &_rom_modules; Rom_module_registry &_rom_modules;
Lock _lock; Lock _lock;
@ -47,15 +50,17 @@ namespace Loader {
void _close(Rom_session_component *rom) void _close(Rom_session_component *rom)
{ {
_ep.dissolve(rom); _ep.dissolve(rom);
destroy(env()->heap(), rom); destroy(&_md_alloc, rom);
_rom_sessions.remove(rom); _rom_sessions.remove(rom);
} }
Local_rom_service(Rpc_entrypoint &ep, Local_rom_service(Rpc_entrypoint &ep,
Allocator &md_alloc,
Rom_module_registry &rom_modules) Rom_module_registry &rom_modules)
: :
Service("virtual_rom"), Service("virtual_rom"),
_ep(ep), _ep(ep),
_md_alloc(md_alloc),
_parent_rom_service(Rom_session::service_name()), _parent_rom_service(Rom_session::service_name()),
_rom_modules(rom_modules) _rom_modules(rom_modules)
{ } { }
@ -82,7 +87,7 @@ namespace Loader {
Rom_module &module = _rom_modules.lookup_and_lock(name); 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_session_component(module);
_rom_sessions.insert(rom); _rom_sessions.insert(rom);
@ -118,14 +123,19 @@ namespace Loader {
struct Local_nitpicker_service : Service struct Local_nitpicker_service : Service
{ {
Rpc_entrypoint &ep; Rpc_entrypoint &ep;
Allocator &_md_alloc;
Signal_context_capability view_ready_sigh; Signal_context_capability view_ready_sigh;
Nitpicker::Session_component *open_session; 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() ~Local_nitpicker_service()
@ -134,7 +144,7 @@ namespace Loader {
return; return;
ep.dissolve(open_session); ep.dissolve(open_session);
destroy(env()->heap(), open_session); destroy(&_md_alloc, open_session);
} }
Genode::Session_capability session(const char *args) Genode::Session_capability session(const char *args)
@ -142,11 +152,7 @@ namespace Loader {
if (open_session) if (open_session)
throw Unavailable(); throw Unavailable();
/* open_session = new (&_md_alloc)
* XXX replace allocation from 'env()->heap()' with
* use of session-specific allocator
*/
open_session = new (env()->heap())
Nitpicker::Session_component(ep, view_ready_sigh, args); Nitpicker::Session_component(ep, view_ready_sigh, args);
return ep.manage(open_session); return ep.manage(open_session);
@ -158,6 +164,8 @@ namespace Loader {
enum { STACK_SIZE = 2*4096 }; enum { STACK_SIZE = 2*4096 };
size_t _ram_quota; size_t _ram_quota;
Ram_session_client_guard _ram_session_client;
Heap _md_alloc;
size_t _subsystem_ram_quota_limit; size_t _subsystem_ram_quota_limit;
int _width, _height; int _width, _height;
Rpc_entrypoint _ep; Rpc_entrypoint _ep;
@ -186,19 +194,21 @@ namespace Loader {
Session_component(size_t quota, Ram_session &ram, Cap_session &cap) Session_component(size_t quota, Ram_session &ram, Cap_session &cap)
: :
_ram_quota(quota), _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), _width(-1), _height(-1),
_ep(&cap, STACK_SIZE, "session_ep"), _ep(&cap, STACK_SIZE, "session_ep"),
_rom_modules(ram, *env()->heap()), /* XXX remove env()->heap() */ _rom_modules(_ram_session_client, _md_alloc),
_rom_service(_ep, _rom_modules), _rom_service(_ep, _md_alloc, _rom_modules),
_nitpicker_service(_ep), _nitpicker_service(_ep, _md_alloc),
_child(0) _child(0)
{ } { }
~Session_component() ~Session_component()
{ {
if (_child) if (_child)
destroy(env()->heap(), _child); destroy(&_md_alloc, _child);
} }
@ -241,18 +251,14 @@ namespace Loader {
return; return;
} }
/* size_t const ram_quota = (_subsystem_ram_quota_limit > 0) ?
* XXX account for ROM modules min(_subsystem_ram_quota_limit, _ram_session_client.avail()) :
*/ _ram_session_client.avail();
size_t const ram_quota = _subsystem_ram_quota_limit;
/* _child = new (&_md_alloc)
* XXX don't use 'env()->heap()'
*/
_child = new (env()->heap())
Child(binary_name.string(), label.string(), _ep, Child(binary_name.string(), label.string(), _ep,
ram_quota, _parent_services, _rom_service, _ram_session_client, ram_quota, _parent_services,
_nitpicker_service, _width, _height); _rom_service, _nitpicker_service, _width, _height);
} }
Nitpicker::View_capability view() Nitpicker::View_capability view()

View File

@ -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 <base/lock.h>
#include <base/printf.h>
#include <dataspace/client.h>
#include <ram_session/client.h>
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_ */