base: remove int return types from 'Ram_session'

This patch replaces the existing C-style error codes with C++
exceptions.

Fixes #895
This commit is contained in:
Norman Feske 2017-05-08 12:33:56 +02:00 committed by Christian Helmuth
parent 58f44d39c5
commit 843dd179d7
21 changed files with 282 additions and 299 deletions

View File

@ -70,13 +70,13 @@ namespace Genode {
** RAM-session interface ** ** RAM-session interface **
***************************/ ***************************/
Ram_dataspace_capability alloc(size_t size, bool cached) Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::alloc(size, cached); return RAM_SESSION_IMPL::alloc(size, cached);
} }
void free(Ram_dataspace_capability ds) void free(Ram_dataspace_capability ds) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
RAM_SESSION_IMPL::free(ds); RAM_SESSION_IMPL::free(ds);
@ -88,16 +88,16 @@ namespace Genode {
return RAM_SESSION_IMPL::dataspace_size(ds); return RAM_SESSION_IMPL::dataspace_size(ds);
} }
int ref_account(Ram_session_capability session) void ref_account(Ram_session_capability session) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::ref_account(session); RAM_SESSION_IMPL::ref_account(session);
} }
int transfer_quota(Ram_session_capability session, Ram_quota size) void transfer_quota(Ram_session_capability session, Ram_quota amount) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::transfer_quota(session, size); RAM_SESSION_IMPL::transfer_quota(session, amount);
} }
Ram_quota ram_quota() const override Ram_quota ram_quota() const override

View File

@ -80,7 +80,6 @@ class Stack_area_region_map : public Genode::Region_map
struct Stack_area_ram_session : Genode::Ram_session struct Stack_area_ram_session : Genode::Ram_session
{ {
Genode::Ram_dataspace_capability alloc(Genode::size_t size, Genode::Ram_dataspace_capability alloc(Genode::size_t size,
Genode::Cache_attribute) override { Genode::Cache_attribute) override {
return Genode::Ram_dataspace_capability(); } return Genode::Ram_dataspace_capability(); }
@ -89,9 +88,9 @@ struct Stack_area_ram_session : Genode::Ram_session
Genode::size_t dataspace_size(Genode::Ram_dataspace_capability) const override { return 0; } Genode::size_t dataspace_size(Genode::Ram_dataspace_capability) const override { return 0; }
int ref_account(Genode::Ram_session_capability) override { return 0; } void ref_account(Genode::Ram_session_capability) override { }
int transfer_quota(Genode::Ram_session_capability, Genode::Ram_quota) override { return 0; } void transfer_quota(Genode::Ram_session_capability, Genode::Ram_quota) override { }
Genode::Ram_quota ram_quota() const override { return { 0 }; } Genode::Ram_quota ram_quota() const override { return { 0 }; }

View File

@ -130,10 +130,9 @@ struct Stack_area_ram_session : Ram_session
size_t dataspace_size(Ram_dataspace_capability) const override { return 0; } size_t dataspace_size(Ram_dataspace_capability) const override { return 0; }
int ref_account(Ram_session_capability ram_session) override { return 0; } void ref_account(Ram_session_capability) override { }
int transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override { void transfer_quota(Ram_session_capability, Ram_quota) override { }
return 0; }
Ram_quota ram_quota() const override { return { 0 }; } Ram_quota ram_quota() const override { return { 0 }; }

View File

@ -39,11 +39,11 @@ struct Genode::Ram_session_client : Rpc_client<Ram_session>
return ds.valid() ? Dataspace_client(ds).size() : 0; return ds.valid() ? Dataspace_client(ds).size() : 0;
} }
int ref_account(Ram_session_capability ram_session) override { void ref_account(Ram_session_capability ram_session) override {
return call<Rpc_ref_account>(ram_session); } call<Rpc_ref_account>(ram_session); }
int transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override { void transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override {
return call<Rpc_transfer_ram_quota>(ram_session, amount); } call<Rpc_transfer_ram_quota>(ram_session, amount); }
Ram_quota ram_quota() const override { return call<Rpc_ram_quota>(); } Ram_quota ram_quota() const override { return call<Rpc_ram_quota>(); }

View File

@ -38,6 +38,14 @@ struct Genode::Ram_session : Session, Ram_allocator
typedef Ram_session_client Client; typedef Ram_session_client Client;
/*********************
** Exception types **
*********************/
class Invalid_session : public Exception { };
class Undefined_ref_account : public Exception { };
/** /**
* Destructor * Destructor
*/ */
@ -48,25 +56,28 @@ struct Genode::Ram_session : Session, Ram_allocator
* *
* \param ram_session reference account * \param ram_session reference account
* *
* \return 0 on success * \throw Invalid_session
* *
* Each RAM session requires another RAM session as reference * Each RAM session requires another RAM session as reference
* account to transfer quota to and from. The reference account can * account to transfer quota to and from. The reference account can
* be defined only once. * be defined only once.
*/ */
virtual int ref_account(Ram_session_capability ram_session) = 0; virtual void ref_account(Ram_session_capability ram_session) = 0;
/** /**
* Transfer quota to 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
* \return 0 on success *
* \throw Out_of_ram
* \throw Invalid_session
* \throw Undefined_ref_account
* *
* Quota can only be transfered if the specified RAM session is * Quota can only be transfered if the specified RAM session is
* either the reference account for this session or vice versa. * either the reference account for this session or vice versa.
*/ */
virtual int transfer_quota(Ram_session_capability ram_session, Ram_quota amount) = 0; virtual void transfer_quota(Ram_session_capability ram_session, Ram_quota amount) = 0;
/** /**
* Return current quota limit * Return current quota limit
@ -89,11 +100,13 @@ struct Genode::Ram_session : Session, Ram_allocator
*********************/ *********************/
GENODE_RPC_THROW(Rpc_alloc, Ram_dataspace_capability, alloc, GENODE_RPC_THROW(Rpc_alloc, Ram_dataspace_capability, alloc,
GENODE_TYPE_LIST(Quota_exceeded, Out_of_metadata), GENODE_TYPE_LIST(Quota_exceeded, Out_of_metadata, Undefined_ref_account),
size_t, Cache_attribute); size_t, Cache_attribute);
GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability); GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability);
GENODE_RPC(Rpc_ref_account, int, ref_account, Ram_session_capability); GENODE_RPC(Rpc_ref_account, void, ref_account, Capability<Ram_session>);
GENODE_RPC(Rpc_transfer_ram_quota, int, transfer_quota, Ram_session_capability, Ram_quota); GENODE_RPC_THROW(Rpc_transfer_ram_quota, void, transfer_quota,
GENODE_TYPE_LIST(Out_of_ram, Invalid_session, Undefined_ref_account),
Capability<Ram_session>, Ram_quota);
GENODE_RPC(Rpc_ram_quota, Ram_quota, ram_quota); GENODE_RPC(Rpc_ram_quota, Ram_quota, ram_quota);
GENODE_RPC(Rpc_used_ram, Ram_quota, used_ram); GENODE_RPC(Rpc_used_ram, Ram_quota, used_ram);

View File

@ -3,9 +3,6 @@
* \author Norman Feske * \author Norman Feske
* \author Christian Helmuth * \author Christian Helmuth
* \date 2006-07-28 * \date 2006-07-28
*
* The Core-specific environment ensures that all sessions of Core's
* environment a local (_component) not remote (_client).
*/ */
/* /*
@ -73,14 +70,15 @@ namespace Genode {
** RAM-session interface ** ** RAM-session interface **
***************************/ ***************************/
Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::alloc(size, cached); return RAM_SESSION_IMPL::alloc(size, cached);
} }
void free(Ram_dataspace_capability ds) void free(Ram_dataspace_capability ds) override
{ {
Lock::Guard lock_guard(_lock);
RAM_SESSION_IMPL::free(ds); RAM_SESSION_IMPL::free(ds);
} }
@ -90,16 +88,16 @@ namespace Genode {
return RAM_SESSION_IMPL::dataspace_size(ds); return RAM_SESSION_IMPL::dataspace_size(ds);
} }
int ref_account(Ram_session_capability session) void ref_account(Ram_session_capability session) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::ref_account(session); RAM_SESSION_IMPL::ref_account(session);
} }
int transfer_quota(Ram_session_capability session, Ram_quota size) void transfer_quota(Ram_session_capability session, Ram_quota amount) override
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::transfer_quota(session, size); RAM_SESSION_IMPL::transfer_quota(session, amount);
} }
Ram_quota ram_quota() const override Ram_quota ram_quota() const override

View File

@ -30,160 +30,161 @@ namespace Genode {
class Ram_session_component; class Ram_session_component;
typedef List<Ram_session_component> Ram_ref_account_members; typedef List<Ram_session_component> Ram_ref_account_members;
class Ram_session_component : public Rpc_object<Ram_session>,
public Ram_ref_account_members::Element,
public Dataspace_owner
{
private:
class Invalid_dataspace : public Exception { };
/*
* Dimension 'Ds_slab' such that slab blocks (including the
* meta-data overhead of the sliced-heap blocks) are page sized.
*/
static constexpr size_t SBS = get_page_size() - Sliced_heap::meta_data_size();
using Ds_slab = Synced_allocator<Tslab<Dataspace_component, SBS> >;
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;
enum { MAX_LABEL_LEN = 64 };
char _label[MAX_LABEL_LEN];
/**
* List of RAM sessions that use us as their reference account
*/
Ram_ref_account_members _ref_members;
Lock _ref_members_lock; /* protect '_ref_members' */
/**
* Register RAM session to use us as reference account
*/
void _register_ref_account_member(Ram_session_component *new_member);
/**
* 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);
/**
* Return portion of RAM quota that is currently in use
*/
size_t used_quota() { return _payload; }
/**
* Free dataspace
*/
void _free_ds(Dataspace_capability ds_cap);
/**
* Transfer quota to another RAM session
*/
int _transfer_quota(Ram_session_component *dst, size_t amount);
/********************************************
** Platform-implemented support functions **
********************************************/
/**
* Export RAM dataspace as shared memory block
*/
void _export_ram_ds(Dataspace_component *ds);
/**
* Revert export of RAM dataspace
*/
void _revoke_ram_ds(Dataspace_component *ds);
/**
* Zero-out content of dataspace
*/
void _clear_ds(Dataspace_component *ds);
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);
/**
* Destructor
*/
~Ram_session_component();
/**
* Accessors
*/
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); }
/**
* Get physical address of the RAM that backs a dataspace
*
* \param ds targeted dataspace
*
* \throw Invalid_dataspace
*/
addr_t phys_addr(Ram_dataspace_capability ds);
/*****************************
** Ram_allocator interface **
*****************************/
Ram_dataspace_capability alloc(size_t, Cache_attribute) override;
void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability ds) const override;
/***************************
** RAM Session interface **
***************************/
int ref_account(Ram_session_capability);
int transfer_quota(Ram_session_capability, Ram_quota);
Ram_quota ram_quota() const override { return { _quota_limit}; }
Ram_quota used_ram() const override { return { _payload}; }
};
} }
class Genode::Ram_session_component : public Rpc_object<Ram_session>,
public Ram_ref_account_members::Element,
public Dataspace_owner
{
private:
class Invalid_dataspace : public Exception { };
/*
* Dimension 'Ds_slab' such that slab blocks (including the
* meta-data overhead of the sliced-heap blocks) are page sized.
*/
static constexpr size_t SBS = get_page_size() - Sliced_heap::meta_data_size();
using Ds_slab = Synced_allocator<Tslab<Dataspace_component, SBS> >;
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;
enum { MAX_LABEL_LEN = 64 };
char _label[MAX_LABEL_LEN];
/**
* List of RAM sessions that use us as their reference account
*/
Ram_ref_account_members _ref_members;
Lock _ref_members_lock; /* protect '_ref_members' */
/**
* Register RAM session to use us as reference account
*/
void _register_ref_account_member(Ram_session_component *new_member);
/**
* 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);
/**
* Return portion of RAM quota that is currently in use
*/
size_t used_quota() { return _payload; }
/**
* 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 **
********************************************/
/**
* Export RAM dataspace as shared memory block
*/
void _export_ram_ds(Dataspace_component *ds);
/**
* Revert export of RAM dataspace
*/
void _revoke_ram_ds(Dataspace_component *ds);
/**
* Zero-out content of dataspace
*/
void _clear_ds(Dataspace_component *ds);
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);
/**
* Destructor
*/
~Ram_session_component();
/**
* Accessors
*/
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); }
/**
* Get physical address of the RAM that backs a dataspace
*
* \param ds targeted dataspace
*
* \throw Invalid_dataspace
*/
addr_t phys_addr(Ram_dataspace_capability ds);
/*****************************
** Ram_allocator interface **
*****************************/
Ram_dataspace_capability alloc(size_t, Cache_attribute) override;
void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability ds) const override;
/***************************
** 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}; }
};
#endif /* _CORE__INCLUDE__RAM_SESSION_COMPONENT_H_ */ #endif /* _CORE__INCLUDE__RAM_SESSION_COMPONENT_H_ */

View File

@ -67,14 +67,15 @@ void Ram_session_component::_free_ds(Dataspace_capability ds_cap)
} }
int Ram_session_component::_transfer_quota(Ram_session_component *dst, size_t amount) void Ram_session_component::_transfer_quota(Ram_session_component *dst, size_t amount)
{ {
/* check if recipient is a valid Ram_session_component */ /* check if recipient is a valid Ram_session_component */
if (!dst) return -1; if (!dst)
throw Invalid_session();
/* check for reference account relationship */ /* check for reference account relationship */
if ((ref_account() != dst) && (dst->ref_account() != this)) if ((ref_account() != dst) && (dst->ref_account() != this))
return -2; throw Invalid_session();
/* decrease quota limit of this session - check against used quota */ /* decrease quota limit of this session - check against used quota */
if (_quota_limit < amount + _payload) { if (_quota_limit < amount + _payload) {
@ -82,15 +83,13 @@ int Ram_session_component::_transfer_quota(Ram_session_component *dst, size_t am
"'", Cstring(_label), "' to '", Cstring(dst->_label), "' " "'", Cstring(_label), "' to '", Cstring(dst->_label), "' "
"have ", (_quota_limit - _payload)/1024, " KiB, " "have ", (_quota_limit - _payload)/1024, " KiB, "
"need ", amount/1024, " KiB"); "need ", amount/1024, " KiB");
return -3; throw Out_of_ram();
} }
_quota_limit -= amount; _quota_limit -= amount;
/* increase quota_limit of recipient */ /* increase quota_limit of recipient */
dst->_quota_limit += amount; dst->_quota_limit += amount;
return 0;
} }
@ -250,37 +249,37 @@ size_t Ram_session_component::dataspace_size(Ram_dataspace_capability ds_cap) co
} }
int Ram_session_component::ref_account(Ram_session_capability ram_session_cap) void Ram_session_component::ref_account(Ram_session_capability ram_session_cap)
{ {
/* the reference account cannot be defined twice */ /* the reference account cannot be defined twice */
if (_ref_account) return -2; if (_ref_account)
return;
if (this->cap() == ram_session_cap)
return;
auto lambda = [this] (Ram_session_component *ref) { auto lambda = [this] (Ram_session_component *ref) {
/* check if recipient is a valid Ram_session_component */ /* check if recipient is a valid Ram_session_component */
if (!ref) return -1; if (!ref)
throw Invalid_session();
/* deny the usage of the ram session as its own ref account */
/* XXX also check for cycles along the tree of ref accounts */
if (ref == this) return -3;
_ref_account = ref; _ref_account = ref;
_ref_account->_register_ref_account_member(this); _ref_account->_register_ref_account_member(this);
return 0;
}; };
return _ram_session_ep->apply(ram_session_cap, lambda); _ram_session_ep->apply(ram_session_cap, lambda);
} }
int Ram_session_component::transfer_quota(Ram_session_capability ram_session_cap, void Ram_session_component::transfer_quota(Ram_session_capability ram_session_cap,
Ram_quota amount) Ram_quota amount)
{ {
auto lambda = [&] (Ram_session_component *dst) { auto lambda = [&] (Ram_session_component *dst) {
return _transfer_quota(dst, amount.value); }; _transfer_quota(dst, amount.value); };
if (this->cap() == ram_session_cap) if (this->cap() == ram_session_cap)
return 0; return;
return _ram_session_ep->apply(ram_session_cap, lambda); return _ram_session_ep->apply(ram_session_cap, lambda);
} }
@ -322,7 +321,7 @@ Ram_session_component::~Ram_session_component()
if (!_ref_account) return; if (!_ref_account) return;
/* transfer remaining quota to reference account */ /* transfer remaining quota to reference account */
_transfer_quota(_ref_account, _quota_limit); try { _transfer_quota(_ref_account, _quota_limit); } catch (...) { }
/* remember our original reference account */ /* remember our original reference account */
Ram_session_component *orig_ref_account = _ref_account; Ram_session_component *orig_ref_account = _ref_account;

View File

@ -134,8 +134,9 @@ struct Stack_area_ram_session : Ram_session
size_t dataspace_size(Ram_dataspace_capability) const override { return 0; } size_t dataspace_size(Ram_dataspace_capability) const override { return 0; }
int ref_account (Ram_session_capability) override { return 0; } void ref_account (Ram_session_capability) override { }
int transfer_quota (Ram_session_capability, Ram_quota) override { return 0; } void transfer_quota (Ram_session_capability, Ram_quota) override { }
Ram_quota ram_quota () const override { return { 0 }; } Ram_quota ram_quota () const override { return { 0 }; }
Ram_quota used_ram () const override { return { 0 }; } Ram_quota used_ram () const override { return { 0 }; }
}; };

View File

@ -68,22 +68,17 @@ struct Genode::Expanding_ram_session_client : Upgradeable_client<Genode::Ram_ses
NUM_ATTEMPTS); NUM_ATTEMPTS);
} }
int transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override void transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override
{ {
/* /*
* Should the transfer fail because we don't have enough quota, request * Should the transfer fail because we don't have enough quota, request
* the needed amount from the parent. * the needed amount from the parent.
*/ */
enum { NUM_ATTEMPTS = 2 }; enum { NUM_ATTEMPTS = 2 };
int ret = -1; retry<Out_of_ram>(
for (unsigned i = 0; i < NUM_ATTEMPTS; i++) { [&] () { Ram_session_client::transfer_quota(ram_session, amount); },
[&] () { _request_ram_from_parent(amount.value); },
ret = Ram_session_client::transfer_quota(ram_session, amount); NUM_ATTEMPTS);
if (ret != -3) break;
_request_ram_from_parent(amount.value);
}
return ret;
} }
}; };

View File

@ -59,8 +59,11 @@ namespace {
Ram_session_capability to) Ram_session_capability to)
: _ack(false), _quantum(quantum), _from(from), _to(to) : _ack(false), _quantum(quantum), _from(from), _to(to)
{ {
if (_from.valid() && _to.valid() && if (!_from.valid() || !_to.valid())
Ram_session_client(_from).transfer_quota(_to, quantum)) { return;
try { Ram_session_client(_from).transfer_quota(_to, quantum); }
catch (...) {
warning("not enough quota for a donation of ", quantum, " bytes"); warning("not enough quota for a donation of ", quantum, " bytes");
throw Quota_exceeded(); throw Quota_exceeded();
} }

View File

@ -107,15 +107,14 @@ class Cli_monitor::Ram
*/ */
void withdraw_from(Genode::Ram_session_capability from, size_t amount) void withdraw_from(Genode::Ram_session_capability from, size_t amount)
{ {
Genode::Lock::Guard guard(_lock); using namespace Genode;
int const ret = Lock::Guard guard(_lock);
Genode::Ram_session_client(from).transfer_quota(_ram_cap, Genode::Ram_quota{amount});
if (ret != 0) try { Ram_session_client(from).transfer_quota(_ram_cap, Ram_quota{amount}); }
throw Transfer_quota_failed(); catch (...) { throw Transfer_quota_failed(); }
Genode::Signal_transmitter(_resource_avail_sigh).submit(); Signal_transmitter(_resource_avail_sigh).submit();
} }
/** /**
@ -130,10 +129,8 @@ class Cli_monitor::Ram
throw Transfer_quota_failed(); throw Transfer_quota_failed();
} }
int const ret = _ram.transfer_quota(to, Genode::Ram_quota{amount}); try { _ram.transfer_quota(to, Genode::Ram_quota{amount}); }
catch (...) { throw Transfer_quota_failed(); }
if (ret != 0)
throw Transfer_quota_failed();
} }
size_t avail() const { return _ram.avail_ram().value; } size_t avail() const { return _ram.avail_ram().value; }

View File

@ -32,30 +32,12 @@ class Genode::Ram_session_guard : public Genode::Ram_session
size_t _used = 0; size_t _used = 0;
size_t _withdraw = 0; size_t _withdraw = 0;
/* XXX should be either a exception or a enum in rm_session */
enum { RM_SESSION_INSUFFICIENT_QUOTA = -3 };
public: public:
Ram_session_guard(Ram_session &session, Ram_session_capability cap, Ram_session_guard(Ram_session &session, Ram_session_capability cap,
size_t quota) size_t quota)
: _session(session), _session_cap(cap), _quota(quota) { } : _session(session), _session_cap(cap), _quota(quota) { }
/**
* Convenient transfer_quota method throwing a exception iif the
* quota is insufficient.
*/
template <typename T>
int transfer_quota(Ram_session_capability ram_session, size_t amount)
{
int const error = transfer_quota(ram_session, Ram_quota{amount});
if (error == RM_SESSION_INSUFFICIENT_QUOTA)
throw T();
return error;
}
/** /**
* Extend allocation limit * Extend allocation limit
*/ */
@ -98,11 +80,11 @@ class Genode::Ram_session_guard : public Genode::Ram_session
if (amount > _used) if (amount > _used)
return -4; return -4;
int error = ram_session.transfer_quota(_session_cap, Ram_quota{amount}); try {
if (!error) ram_session.transfer_quota(_session_cap, Ram_quota{amount});
_used -= amount; _used -= amount;
return 0;
return error; } catch (...) { return -1; }
} }
/*************************** /***************************
@ -136,21 +118,17 @@ class Genode::Ram_session_guard : public Genode::Ram_session
return _session.dataspace_size(ds); return _session.dataspace_size(ds);
} }
int ref_account(Ram_session_capability ram_session) override { void ref_account(Ram_session_capability ram_session) override {
return _session.ref_account(ram_session); } _session.ref_account(ram_session); }
int transfer_quota(Ram_session_capability ram_session, void transfer_quota(Ram_session_capability ram_session,
Ram_quota amount) override Ram_quota amount) override
{ {
if (_used + amount.value <= _used || _used + amount.value > _quota) if (_used + amount.value <= _used || _used + amount.value > _quota)
return RM_SESSION_INSUFFICIENT_QUOTA; throw Out_of_ram();
int const error = _session.transfer_quota(ram_session, amount); _session.transfer_quota(ram_session, amount);
_used += amount.value;
if (!error)
_used += amount.value;
return error;
} }
Ram_quota ram_quota() const override { return Ram_quota{_quota}; } Ram_quota ram_quota() const override { return Ram_quota{_quota}; }

View File

@ -252,8 +252,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
_ram.ref_account(_env_ram_cap); _ram.ref_account(_env_ram_cap);
enum { OVERHEAD = 4096 }; enum { OVERHEAD = 4096 };
if (_env_ram.transfer_quota(_ram, Genode::Ram_quota{OVERHEAD}) != 0) try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{OVERHEAD}); }
throw Genode::Root::Quota_exceeded(); catch (...) { throw Genode::Root::Quota_exceeded(); }
} }
bool const _ram_initialized = (_init_ram(), true); bool const _ram_initialized = (_init_ram(), true);
@ -942,8 +942,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
_try_init_device_pd(); _try_init_device_pd();
/* transfer ram quota to session specific ram session */ /* transfer ram quota to session specific ram session */
if (_env_ram.transfer_quota<Out_of_metadata>(_ram, size)) try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{size}); }
throw Fatal(); catch (...) { throw Fatal(); }
enum { UPGRADE_QUOTA = 4096 }; enum { UPGRADE_QUOTA = 4096 };
@ -971,7 +971,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
* It is therefore enough to increase the quota in * It is therefore enough to increase the quota in
* UPGRADE_QUOTA steps. * UPGRADE_QUOTA steps.
*/ */
_env_ram.transfer_quota<Out_of_metadata>(_ram, UPGRADE_QUOTA); try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{UPGRADE_QUOTA}); }
catch (...) { throw Out_of_metadata(); }
}); });
if (!ram_cap.valid()) if (!ram_cap.valid())
@ -984,12 +985,14 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
if (!_env_ram.withdraw(UPGRADE_QUOTA)) if (!_env_ram.withdraw(UPGRADE_QUOTA))
_rollback(size, ram_cap); _rollback(size, ram_cap);
if (_env_ram.transfer_quota(_ram, Genode::Ram_quota{UPGRADE_QUOTA})) using namespace Genode;
throw Fatal();
if (_ram.transfer_quota(_device_pd->ram_session_cap(), try { _env_ram.transfer_quota(_ram, Ram_quota{UPGRADE_QUOTA}); }
Genode::Ram_quota{UPGRADE_QUOTA})) catch (...) { throw Fatal(); }
throw Fatal();
try { _ram.transfer_quota(_device_pd->ram_session_cap(),
Ram_quota{UPGRADE_QUOTA}); }
catch (...) { throw Fatal(); }
}); });
} }

View File

@ -238,11 +238,12 @@ void Init::Child::apply_ram_downgrade()
size_t const transfer = min(avail - preserved, decrease); size_t const transfer = min(avail - preserved, decrease);
if (_child.ram().transfer_quota(ref_ram_cap(), Ram_quota{transfer}) == 0) { try {
_child.ram().transfer_quota(ref_ram_cap(), Ram_quota{transfer});
_resources.assigned_ram_quota = _resources.assigned_ram_quota =
Ram_quota { _resources.assigned_ram_quota.value - transfer }; Ram_quota { _resources.assigned_ram_quota.value - transfer };
break; break;
} } catch (...) { }
} }
if (attempts == max_attempts) if (attempts == max_attempts)

View File

@ -196,7 +196,8 @@ void Init::Server::_handle_create_session_request(Xml_node request,
route.label, argbuf, Affinity()); route.label, argbuf, Affinity());
/* transfer session quota */ /* transfer session quota */
if (_env.ram().transfer_quota(route.service.ram(), ram_quota)) { try { _env.ram().transfer_quota(route.service.ram(), forward_ram_quota); }
catch (...) {
/* /*
* This should never happen unless our parent missed to * This should never happen unless our parent missed to
@ -241,7 +242,10 @@ void Init::Server::_handle_upgrade_session_request(Xml_node request,
session.phase = Session_state::UPGRADE_REQUESTED; session.phase = Session_state::UPGRADE_REQUESTED;
if (_env.ram().transfer_quota(session.service().ram(), ram_quota)) { try {
_env.ram().transfer_quota(session.service().ram(), ram_quota);
}
catch (...) {
warning("unable to upgrade session quota (", ram_quota, " bytes) " warning("unable to upgrade session quota (", ram_quota, " bytes) "
"of forwarded ", session.service().name(), " session"); "of forwarded ", session.service().name(), " session");
return; return;

View File

@ -66,7 +66,7 @@ namespace Genode {
return Ram_session_client::dataspace_size(ds); return Ram_session_client::dataspace_size(ds);
} }
int transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override void transfer_quota(Ram_session_capability ram_session, Ram_quota amount) override
{ {
Lock::Guard _consumed_lock_guard(_consumed_lock); Lock::Guard _consumed_lock_guard(_consumed_lock);
@ -74,15 +74,11 @@ namespace Genode {
warning("Quota exceeded! amount=", _amount, ", " warning("Quota exceeded! amount=", _amount, ", "
"size=", amount.value, ", " "size=", amount.value, ", "
"consumed=", _consumed); "consumed=", _consumed);
return -1; throw Out_of_ram();
} }
int result = Ram_session_client::transfer_quota(ram_session, amount); Ram_session_client::transfer_quota(ram_session, amount);
_consumed += amount.value;
if (result == 0)
_consumed += amount.value;
return result;
} }
Ram_quota ram_quota() const override Ram_quota ram_quota() const override

View File

@ -199,11 +199,7 @@ void Component::construct(Genode::Env &env)
* requests, too. * requests, too.
*/ */
log("\n-- out-of-memory during transfer-quota --"); log("\n-- out-of-memory during transfer-quota --");
int ret = env.ram().transfer_quota(ram.cap(), Ram_quota{512*1024}); env.ram().transfer_quota(ram.cap(), Ram_quota{512*1024});
if (ret != 0) {
error("transfer quota failed (ret = ", ret, ")");
throw Error();
}
print_quota_stats(env.ram()); print_quota_stats(env.ram());
size_t const used_quota_after_transfer = env.ram().used_ram().value; size_t const used_quota_after_transfer = env.ram().used_ram().value;

View File

@ -49,16 +49,16 @@ size_t Ram_session_component::dataspace_size(Ram_dataspace_capability ds_cap) co
} }
int Ram_session_component::ref_account(Ram_session_capability ram_session_cap) void Ram_session_component::ref_account(Ram_session_capability ram_session_cap)
{ {
return _parent_ram_session.ref_account(ram_session_cap); _parent_ram_session.ref_account(ram_session_cap);
} }
int Ram_session_component::transfer_quota(Ram_session_capability ram_session_cap, void Ram_session_component::transfer_quota(Ram_session_capability ram_session_cap,
Ram_quota amount) Ram_quota amount)
{ {
return _parent_ram_session.transfer_quota(ram_session_cap, amount); _parent_ram_session.transfer_quota(ram_session_cap, amount);
} }

View File

@ -59,8 +59,8 @@ class Gdb_monitor::Ram_session_component : public Rpc_object<Ram_session>
Ram_dataspace_capability alloc(size_t, Cache_attribute) override; Ram_dataspace_capability alloc(size_t, Cache_attribute) override;
void free(Ram_dataspace_capability) override; void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability) const override; size_t dataspace_size(Ram_dataspace_capability) const override;
int ref_account(Ram_session_capability) override; void ref_account(Ram_session_capability) override;
int transfer_quota(Ram_session_capability, Ram_quota) override; void transfer_quota(Ram_session_capability, Ram_quota) override;
Ram_quota ram_quota() const override; Ram_quota ram_quota() const override;
Ram_quota used_ram() const override; Ram_quota used_ram() const override;
}; };

View File

@ -188,8 +188,8 @@ class Noux::Ram_session_component : public Rpc_object<Ram_session>
return result; return result;
} }
int ref_account(Ram_session_capability) { return 0; } void ref_account(Ram_session_capability) override { }
int transfer_quota(Ram_session_capability, Ram_quota) { return 0; } void transfer_quota(Ram_session_capability, Ram_quota) override { }
Ram_quota ram_quota() const override { return _ram.ram_quota(); } Ram_quota ram_quota() const override { return _ram.ram_quota(); }
Ram_quota used_ram() const override { return Ram_quota{_used_ram_quota}; } Ram_quota used_ram() const override { return Ram_quota{_used_ram_quota}; }
}; };