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;
/**
* 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

View File

@ -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),

View File

@ -13,6 +13,7 @@
/* Genode includes */
#include <base/env.h>
#include <base/heap.h>
#include <base/rpc_server.h>
#include <base/signal.h>
#include <base/sleep.h>
@ -24,6 +25,7 @@
/* local includes */
#include <child.h>
#include <nitpicker.h>
#include <ram_session_client_guard.h>
#include <rom.h>
@ -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()

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_ */