mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-12 05:41:36 +00:00
Implement RAM accounting
This commit is contained in:
parent
bcf6714eff
commit
cf9610a958
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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()
|
||||
|
94
os/src/server/loader/ram_session_client_guard.h
Normal file
94
os/src/server/loader/ram_session_client_guard.h
Normal 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_ */
|
Loading…
x
Reference in New Issue
Block a user