Remove exceptions from Pd_session interface

This patch replaces exceptions of the PD session RPC interface with
result types.
The change of the quota-transfer RPC functions required the adaptation
of base/quota_transfer.h and base/child.h.
The 'alloc_signal_source' method has been renamed to 'signal_source'
to avoid an exceedingly long name of the corresponding result type.
The Pd_session::map function takes a 'Virt_range' instead of basic-type
arguments.
The 'Signal_source_capability' alias for 'Capability<Signal_source>' has
been removed.

Issue #5245
This commit is contained in:
Norman Feske 2024-06-13 16:35:00 +02:00
parent 08066269ba
commit 0d7d60a1f4
24 changed files with 302 additions and 256 deletions

View File

@ -67,5 +67,8 @@ Capability<Pd_session::System_control> System_control_component::control_cap(Aff
bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; }
void Pd_session_component::map(addr_t, addr_t) { }
Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range)
{
return Map_result::OK;
}

View File

@ -86,4 +86,4 @@ Capability<Pd_session::System_control> System_control_component::control_cap(Aff
bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; }
void Pd_session_component::map(addr_t, addr_t) { }
Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range) { return Map_result::OK; }

View File

@ -57,12 +57,19 @@ Signal_receiver::Signal_receiver() : _pd(env().pd())
Ram_quota ram_upgrade { 0 };
Cap_quota cap_upgrade { 0 };
try {
_cap = env().pd().alloc_signal_source();
using Error = Pd_session::Signal_source_error;
env().pd().signal_source().with_result(
[&] (Capability<Signal_source> cap) { _cap = cap; },
[&] (Error e) {
switch (e) {
case Error::OUT_OF_RAM: ram_upgrade = { 2*1024*sizeof(long) }; break;
case Error::OUT_OF_CAPS: cap_upgrade = { 4 }; break;
}
});
if (_cap.valid())
break;
}
catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; }
catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
env().upgrade(Parent::Env::pd(),
String<100>("ram_quota=", ram_upgrade, ", "

View File

@ -41,18 +41,26 @@ Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session& pd, Native_capabili
{
/* first we allocate a cap from core, to allow accounting of caps. */
for (;;) {
Ram_quota ram_upgrade { 0 };
Cap_quota cap_upgrade { 0 };
try { pd.alloc_rpc_cap(_cap); break; }
catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; }
catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
Pd_session::Alloc_rpc_cap_result const result = pd.alloc_rpc_cap(_cap);
if (result.ok())
break;
_parent().upgrade(Parent::Env::pd(),
String<100>("ram_quota=", ram_upgrade, ", "
"cap_quota=", cap_upgrade).string());
using Error = Pd_session::Alloc_rpc_cap_error;
pd.alloc_rpc_cap(_cap).with_error([&] (Error e) {
Ram_quota ram_upgrade { 0 };
Cap_quota cap_upgrade { 0 };
switch (e) {
case Error::OUT_OF_RAM: ram_upgrade = { 2*1024*sizeof(long) }; break;
case Error::OUT_OF_CAPS: cap_upgrade = { 4 }; break;
}
_parent().upgrade(Parent::Env::pd(),
String<100>("ram_quota=", ram_upgrade, ", "
"cap_quota=", cap_upgrade).string());
});
}
return Thread::native_thread().epoll.alloc_rpc_cap();
}

View File

@ -23,7 +23,6 @@
/* core includes */
#include <platform.h>
#include <signal_source_component.h>
#include <signal_source/capability.h>
#include <signal_context_slab.h>
namespace Core { class Signal_broker; }
@ -38,7 +37,7 @@ class Core::Signal_broker
Object_pool<Signal_context_component> _obj_pool { };
Rpc_entrypoint &_context_ep;
Signal_source_component _source;
Signal_source_capability _source_cap;
Capability<Signal_source> _source_cap;
Signal_context_slab _context_slab { _md_alloc };
public:
@ -66,15 +65,15 @@ class Core::Signal_broker
free_context(reinterpret_cap_cast<Signal_context>(r->cap()));
}
Signal_source_capability alloc_signal_source() { return _source_cap; }
Capability<Signal_source> alloc_signal_source() { return _source_cap; }
void free_signal_source(Signal_source_capability) { }
void free_signal_source(Capability<Signal_source>) { }
/*
* \throw Allocator::Out_of_memory
*/
Signal_context_capability
alloc_context(Signal_source_capability, unsigned long imprint)
alloc_context(Capability<Signal_source>, unsigned long imprint)
{
/*
* XXX For now, we ignore the signal-source argument as we

View File

@ -43,7 +43,7 @@ bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf)
}
void Pd_session_component::map(addr_t virt, addr_t size)
Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range const virt_range)
{
Platform_pd &target_pd = *_pd;
Nova::Utcb &utcb = *reinterpret_cast<Nova::Utcb *>(Thread::myself()->utcb());
@ -74,6 +74,8 @@ void Pd_session_component::map(addr_t virt, addr_t size)
}
};
addr_t virt = virt_range.start;
size_t size = virt_range.num_bytes;
try {
while (size) {
@ -98,9 +100,13 @@ void Pd_session_component::map(addr_t virt, addr_t size)
[&] (Region_map_component &, Fault const &) { /* don't reflect */ }
);
}
} catch (...) {
}
catch (Out_of_ram) { return Map_result::OUT_OF_RAM; }
catch (Out_of_caps) { return Map_result::OUT_OF_CAPS; }
catch (...) {
error(__func__, " failed ", Hex(virt), "+", Hex(size));
}
return Map_result::OK;
}

View File

@ -538,13 +538,16 @@ class Genode::Child : protected Rpc_object<Parent>,
_child._try_construct_env_dependent_members();
}
using Transfer_ram_quota_result = Pd_session::Transfer_ram_quota_result;
using Transfer_cap_quota_result = Pd_session::Transfer_ram_quota_result;
/**
* Service (Ram_transfer::Account) interface
*/
void transfer(Pd_session_capability to, Ram_quota amount) override
Ram_transfer_result transfer(Pd_session_capability to, Ram_quota amount) override
{
Ram_transfer::Account &from = _service;
from.transfer(to, amount);
return from.transfer(to, amount);
}
/**
@ -559,10 +562,10 @@ class Genode::Child : protected Rpc_object<Parent>,
/**
* Service (Cap_transfer::Account) interface
*/
void transfer(Pd_session_capability to, Cap_quota amount) override
Cap_transfer_result transfer(Pd_session_capability to, Cap_quota amount) override
{
Cap_transfer::Account &from = _service;
from.transfer(to, amount);
return from.transfer(to, amount);
}
/**

View File

@ -19,10 +19,10 @@
namespace Genode {
template <typename SESSION, typename UNIT> class Quota_transfer;
template <typename SESSION, typename UNIT, typename RESULT> class Quota_transfer;
typedef Quota_transfer<Pd_session, Ram_quota> Ram_transfer;
typedef Quota_transfer<Pd_session, Cap_quota> Cap_transfer;
using Ram_transfer = Quota_transfer<Pd_session, Ram_quota, Pd_session::Transfer_ram_quota_result>;
using Cap_transfer = Quota_transfer<Pd_session, Cap_quota, Pd_session::Transfer_cap_quota_result>;
}
@ -38,15 +38,15 @@ namespace Genode {
* exception), the destructor the transfer object reverts the transfer in
* flight.
*/
template <typename SESSION, typename UNIT>
template <typename SESSION, typename UNIT, typename RESULT>
class Genode::Quota_transfer
{
public:
class Quota_exceeded : Exception { };
struct Account : Noncopyable, Interface
{
using Transfer_result = RESULT;
/**
* Return capability used for transfers to the account
*
@ -61,13 +61,11 @@ class Genode::Quota_transfer
/**
* Transfer quota to the specified account
*
* \throw Out_of_ram
* \throw Out_of_caps
* \throw Invalid_session
* \throw Undefined_ref_account
*/
virtual void transfer(Capability<SESSION>, UNIT) { }
virtual Transfer_result transfer(Capability<SESSION>, UNIT)
{
return Transfer_result::OK;
}
/**
* Try to transfer quota, ignoring possible exceptions
@ -76,7 +74,7 @@ class Genode::Quota_transfer
*/
void try_transfer(Capability<SESSION> to, UNIT amount)
{
try { transfer(to, amount); } catch (...) { }
transfer(to, amount);
}
};
@ -93,9 +91,12 @@ class Genode::Quota_transfer
Capability<SESSION> cap(UNIT) const override { return _cap; }
void transfer(Capability<SESSION> to, UNIT amount) override
using Transfer_result = RESULT;
Transfer_result transfer(Capability<SESSION> to, UNIT amount) override
{
if (to.valid()) _session.transfer_quota(to, amount);
return to.valid() ? _session.transfer_quota(to, amount)
: Transfer_result::OK;
}
};
@ -106,14 +107,20 @@ class Genode::Quota_transfer
Account &_from;
Account &_to;
static bool _exceeded(Ram_quota, RESULT r) { return (r == RESULT::OUT_OF_RAM); }
static bool _exceeded(Cap_quota, RESULT r) { return (r == RESULT::OUT_OF_CAPS); }
public:
class Quota_exceeded : Exception { };
/**
* Constructor
*
* \param amount amount of quota to transfer
* \param from donor account
* \param to receiving account
* \throw Quota_exceeded
*/
Quota_transfer(UNIT amount, Account &from, Account &to)
:
@ -122,11 +129,8 @@ class Genode::Quota_transfer
if (!_from.cap(UNIT()).valid() || !_to.cap(UNIT()).valid())
return;
try { _from.transfer(_to.cap(UNIT()), amount); }
catch (typename SESSION::Undefined_ref_account) { }
catch (typename SESSION::Invalid_session) { }
catch (... /* 'Out_of_ram' / 'Out_of_caps' */) {
throw Quota_exceeded(); }
if (_exceeded(UNIT{}, _from.transfer(_to.cap(UNIT()), amount)))
throw Quota_exceeded();
}
/**

View File

@ -41,6 +41,9 @@ class Genode::Service : public Ram_transfer::Account,
typedef Session_state::Name Name;
using Ram_transfer_result = Ram_transfer::Account::Transfer_result;
using Cap_transfer_result = Cap_transfer::Account::Transfer_result;
private:
Name const _name;
@ -473,9 +476,10 @@ class Genode::Child_service : public Async_service
/**
* Ram_transfer::Account interface
*/
void transfer(Pd_session_capability to, Ram_quota amount) override
Ram_transfer_result transfer(Pd_session_capability to, Ram_quota amount) override
{
if (to.valid()) _pd.transfer_quota(to, amount);
return to.valid() ? _pd.transfer_quota(to, amount)
: Ram_transfer_result::OK;
}
/**
@ -486,9 +490,10 @@ class Genode::Child_service : public Async_service
/**
* Cap_transfer::Account interface
*/
void transfer(Pd_session_capability to, Cap_quota amount) override
Cap_transfer_result transfer(Pd_session_capability to, Cap_quota amount) override
{
if (to.valid()) _pd.transfer_quota(to, amount);
return to.valid() ? _pd.transfer_quota(to, amount)
: Cap_transfer_result::OK;
}
/**

View File

@ -31,15 +31,15 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override {
return call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
void map(addr_t virt, addr_t size) override { call<Rpc_map>(virt, size); }
Map_result map(Virt_range range) override { return call<Rpc_map>(range); }
Signal_source_capability alloc_signal_source() override {
return call<Rpc_alloc_signal_source>(); }
Signal_source_result signal_source() override {
return call<Rpc_signal_source>(); }
void free_signal_source(Signal_source_capability cap) override {
void free_signal_source(Capability<Signal_source> cap) override {
call<Rpc_free_signal_source>(cap); }
Alloc_context_result alloc_context(Signal_source_capability source,
Alloc_context_result alloc_context(Capability<Signal_source> source,
Imprint imprint) override {
return call<Rpc_alloc_context>(source, imprint); }
@ -49,7 +49,7 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
void submit(Signal_context_capability receiver, unsigned cnt = 1) override {
call<Rpc_submit>(receiver, cnt); }
Native_capability alloc_rpc_cap(Native_capability ep) override {
Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) override {
return call<Rpc_alloc_rpc_cap>(ep); }
void free_rpc_cap(Native_capability cap) override {
@ -64,11 +64,14 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
Capability<Region_map> linker_area() override {
return call<Rpc_linker_area>(); }
void ref_account(Capability<Pd_session> pd) override {
call<Rpc_ref_account>(pd); }
Ref_account_result ref_account(Capability<Pd_session> pd) override {
return call<Rpc_ref_account>(pd); }
void transfer_quota(Capability<Pd_session> pd, Cap_quota amount) override {
call<Rpc_transfer_cap_quota>(pd, amount); }
Transfer_cap_quota_result transfer_quota(Capability<Pd_session> pd,
Cap_quota amount) override
{
return call<Rpc_transfer_cap_quota>(pd, amount);
}
Cap_quota cap_quota() const override { return call<Rpc_cap_quota>(); }
Cap_quota used_caps() const override { return call<Rpc_used_caps>(); }
@ -85,8 +88,11 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
return ds.valid() ? Dataspace_client(ds).size() : 0;
}
void transfer_quota(Pd_session_capability pd_session, Ram_quota amount) override {
call<Rpc_transfer_ram_quota>(pd_session, amount); }
Transfer_ram_quota_result transfer_quota(Pd_session_capability pd_session,
Ram_quota amount) override
{
return call<Rpc_transfer_ram_quota>(pd_session, amount);
}
Ram_quota ram_quota() const override { return call<Rpc_ram_quota>(); }
Ram_quota used_ram() const override { return call<Rpc_used_ram>(); }

View File

@ -17,7 +17,6 @@
#include <util/attempt.h>
#include <base/affinity.h>
#include <base/exception.h>
#include <cpu/cpu_state.h>
#include <session/session.h>
#include <region_map/region_map.h>
@ -71,48 +70,39 @@ struct Genode::Pd_session : Session, Ram_allocator
*/
virtual bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) = 0;
struct Virt_range { addr_t start; size_t num_bytes; };
enum class Map_result { OK, OUT_OF_RAM, OUT_OF_CAPS };
/**
* Trigger eager insertion of page frames to page table within
* specified virtual range.
* Trigger eager population of page table within specified virtual range
*
* If the used kernel don't support this feature, the operation will
* silently ignore the request.
*
* \param virt virtual address within the address space to start
* \param size the virtual size of the region
*
* \throw Out_of_ram
* \throw Out_of_caps
*/
virtual void map(addr_t virt, addr_t size) = 0;
virtual Map_result map(Virt_range) = 0;
/********************************
** Support for the signal API **
********************************/
typedef Capability<Signal_source> Signal_source_capability;
class Invalid_session : public Exception { };
class Undefined_ref_account : public Exception { };
enum class Signal_source_error { OUT_OF_RAM, OUT_OF_CAPS };
using Signal_source_result = Attempt<Capability<Signal_source>, Signal_source_error>;
/**
* Create a new signal source
*
* \return a cap that acts as reference to the created source
* Return signal source for the PD
*
* The signal source provides an interface to wait for incoming signals.
*
* \throw Out_of_ram
* \throw Out_of_caps
*/
virtual Signal_source_capability alloc_signal_source() = 0;
virtual Signal_source_result signal_source() = 0;
/**
* Free a signal source
*
* \param cap capability of the signal source to destroy
*/
virtual void free_signal_source(Signal_source_capability cap) = 0;
virtual void free_signal_source(Capability<Signal_source> cap) = 0;
enum class Alloc_context_error { OUT_OF_RAM, OUT_OF_CAPS, INVALID_SIGNAL_SOURCE };
using Alloc_context_result = Attempt<Capability<Signal_context>, Alloc_context_error>;
@ -128,7 +118,7 @@ struct Genode::Pd_session : Session, Ram_allocator
* originating from the allocated signal-context capability
* \return new signal-context capability
*/
virtual Alloc_context_result alloc_context(Signal_source_capability source,
virtual Alloc_context_result alloc_context(Capability<Signal_source> source,
Imprint imprint) = 0;
/**
@ -159,17 +149,17 @@ struct Genode::Pd_session : Session, Ram_allocator
** Support for the RPC framework **
***********************************/
enum class Alloc_rpc_cap_error { OUT_OF_RAM, OUT_OF_CAPS };
using Alloc_rpc_cap_result = Attempt<Native_capability, Alloc_rpc_cap_error>;
/**
* Allocate new RPC-object capability
*
* \param ep entry point that will use this capability
*
* \throw Out_of_ram if meta-data backing store is exhausted
* \throw Out_of_caps if 'cap_quota' is exceeded
*
* \return new RPC capability
*/
virtual Native_capability alloc_rpc_cap(Native_capability ep) = 0;
virtual Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) = 0;
/**
* Free RPC-object capability
@ -205,12 +195,14 @@ struct Genode::Pd_session : Session, Ram_allocator
** Accounting for capability allocations **
*******************************************/
enum class Ref_account_result { OK, INVALID_SESSION };
/**
* Define reference account for the PD session
*
* \throw Invalid_session
*/
virtual void ref_account(Capability<Pd_session>) = 0;
virtual Ref_account_result ref_account(Capability<Pd_session>) = 0;
enum class Transfer_cap_quota_result { OK, OUT_OF_CAPS, INVALID_SESSION, NO_REF_ACCOUNT };
/**
* Transfer capability quota to another PD session
@ -218,14 +210,11 @@ struct Genode::Pd_session : Session, Ram_allocator
* \param to receiver of quota donation
* \param amount amount of quota to donate
*
* \throw Out_of_caps
* \throw Invalid_session
* \throw Undefined_ref_account
*
* Quota can only be transfered if the specified PD session is either the
* reference account for this session or vice versa.
*/
virtual void transfer_quota(Capability<Pd_session> to, Cap_quota amount) = 0;
virtual Transfer_cap_quota_result transfer_quota(Capability<Pd_session> to,
Cap_quota amount) = 0;
/**
* Return current capability-quota limit
@ -255,20 +244,19 @@ struct Genode::Pd_session : Session, Ram_allocator
* which comprises the actual allocation and deallocation operations.
*/
enum class Transfer_ram_quota_result { OK, OUT_OF_RAM, INVALID_SESSION, NO_REF_ACCOUNT };
/**
* Transfer quota to another RAM session
*
* \param to receiver of quota donation
* \param amount amount of quota to donate
*
* \throw Out_of_ram
* \throw Invalid_session
* \throw Undefined_ref_account
*
* Quota can only be transfered if the specified PD session is either the
* reference account for this session or vice versa.
*/
virtual void transfer_quota(Capability<Pd_session> to, Ram_quota amount) = 0;
virtual Transfer_ram_quota_result transfer_quota(Capability<Pd_session> to,
Ram_quota amount) = 0;
/**
* Return current quota limit
@ -364,55 +352,38 @@ struct Genode::Pd_session : Session, Ram_allocator
GENODE_RPC(Rpc_assign_parent, void, assign_parent, Capability<Parent>);
GENODE_RPC(Rpc_assign_pci, bool, assign_pci, addr_t, uint16_t);
GENODE_RPC_THROW(Rpc_map, void, map,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
addr_t, addr_t);
GENODE_RPC_THROW(Rpc_alloc_signal_source, Signal_source_capability,
alloc_signal_source,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps));
GENODE_RPC(Rpc_free_signal_source, void, free_signal_source, Signal_source_capability);
GENODE_RPC(Rpc_map, Map_result, map, Virt_range);
GENODE_RPC(Rpc_signal_source, Signal_source_result, signal_source);
GENODE_RPC(Rpc_free_signal_source, void, free_signal_source, Capability<Signal_source>);
GENODE_RPC(Rpc_alloc_context, Alloc_context_result, alloc_context,
Signal_source_capability, Imprint);
GENODE_RPC(Rpc_free_context, void, free_context,
Capability<Signal_context>);
Capability<Signal_source>, Imprint);
GENODE_RPC(Rpc_free_context, void, free_context, Capability<Signal_context>);
GENODE_RPC(Rpc_submit, void, submit, Capability<Signal_context>, unsigned);
GENODE_RPC_THROW(Rpc_alloc_rpc_cap, Native_capability, alloc_rpc_cap,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), Native_capability);
GENODE_RPC(Rpc_alloc_rpc_cap, Alloc_rpc_cap_result, alloc_rpc_cap, Native_capability);
GENODE_RPC(Rpc_free_rpc_cap, void, free_rpc_cap, Native_capability);
GENODE_RPC(Rpc_address_space, Capability<Region_map>, address_space);
GENODE_RPC(Rpc_stack_area, Capability<Region_map>, stack_area);
GENODE_RPC(Rpc_linker_area, Capability<Region_map>, linker_area);
GENODE_RPC_THROW(Rpc_ref_account, void, ref_account,
GENODE_TYPE_LIST(Invalid_session), Capability<Pd_session>);
GENODE_RPC_THROW(Rpc_transfer_cap_quota, void, transfer_quota,
GENODE_TYPE_LIST(Out_of_caps, Invalid_session, Undefined_ref_account),
Capability<Pd_session>, Cap_quota);
GENODE_RPC(Rpc_ref_account, Ref_account_result, ref_account, Capability<Pd_session>);
GENODE_RPC(Rpc_transfer_cap_quota, Transfer_cap_quota_result, transfer_quota,
Capability<Pd_session>, Cap_quota);
GENODE_RPC(Rpc_cap_quota, Cap_quota, cap_quota);
GENODE_RPC(Rpc_used_caps, Cap_quota, used_caps);
GENODE_RPC(Rpc_try_alloc, Alloc_result, try_alloc, size_t, Cache);
GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability);
GENODE_RPC_THROW(Rpc_transfer_ram_quota, void, transfer_quota,
GENODE_TYPE_LIST(Out_of_ram, Invalid_session, Undefined_ref_account),
Capability<Pd_session>, Ram_quota);
GENODE_RPC(Rpc_transfer_ram_quota, Transfer_ram_quota_result, transfer_quota,
Capability<Pd_session>, Ram_quota);
GENODE_RPC(Rpc_ram_quota, Ram_quota, ram_quota);
GENODE_RPC(Rpc_used_ram, Ram_quota, used_ram);
GENODE_RPC(Rpc_native_pd, Capability<Native_pd>, native_pd);
GENODE_RPC(Rpc_system_control_cap, Capability<System_control>,
system_control_cap, Affinity::Location);
GENODE_RPC(Rpc_dma_addr, addr_t, dma_addr, Ram_dataspace_capability);
GENODE_RPC(Rpc_attach_dma, Attach_dma_result, attach_dma,
Dataspace_capability, addr_t);
GENODE_RPC_INTERFACE(Rpc_assign_parent, Rpc_assign_pci, Rpc_map,
Rpc_alloc_signal_source, Rpc_free_signal_source,
Rpc_signal_source, Rpc_free_signal_source,
Rpc_alloc_context, Rpc_free_context, Rpc_submit,
Rpc_alloc_rpc_cap, Rpc_free_rpc_cap, Rpc_address_space,
Rpc_stack_area, Rpc_linker_area, Rpc_ref_account,

View File

@ -198,24 +198,30 @@ class Core::Pd_session_component : public Session_object<Pd_session>
bool assign_pci(addr_t, uint16_t) override;
void map(addr_t, addr_t) override;
Map_result map(Pd_session::Virt_range) override;
/****************
** Signalling **
****************/
Signal_source_capability alloc_signal_source() override
Signal_source_result signal_source() override
{
_consume_cap(SIG_SOURCE_CAP);
try { _consume_cap(SIG_SOURCE_CAP); }
catch (Out_of_caps) {
return Signal_source_error::OUT_OF_CAPS; }
Signal_source_result result = Capability<Signal_source>();
try { return _signal_broker.alloc_signal_source(); }
catch (Allocator::Out_of_memory) {
_released_cap_silent();
throw Out_of_ram();
}
catch (Out_of_ram) { result = Signal_source_error::OUT_OF_RAM; }
catch (Out_of_caps) { result = Signal_source_error::OUT_OF_CAPS; }
_released_cap_silent();
return result;
}
void free_signal_source(Signal_source_capability sig_rec_cap) override
void free_signal_source(Capability<Signal_source> sig_rec_cap) override
{
if (sig_rec_cap.valid()) {
_signal_broker.free_signal_source(sig_rec_cap);
@ -224,7 +230,7 @@ class Core::Pd_session_component : public Session_object<Pd_session>
}
Alloc_context_result
alloc_context(Signal_source_capability sig_rec_cap, Imprint imprint) override
alloc_context(Capability<Signal_source> sig_rec_cap, Imprint imprint) override
{
try {
Cap_quota_guard::Reservation cap_costs(_cap_quota_guard(), Cap_quota{1});
@ -257,14 +263,19 @@ class Core::Pd_session_component : public Session_object<Pd_session>
** RPC capability allocation **
*******************************/
Native_capability alloc_rpc_cap(Native_capability ep) override
Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) override
{
/* may throw 'Out_of_caps' */
_consume_cap(RPC_CAP);
try { _consume_cap(RPC_CAP); }
catch (Out_of_caps) {
return Alloc_rpc_cap_error::OUT_OF_CAPS; }
/* may throw 'Out_of_ram' */
try { return _rpc_cap_factory.alloc(ep); }
catch (...) { _released_cap_silent(); throw; }
try {
return _rpc_cap_factory.alloc(ep); }
catch (...) {
_released_cap_silent();
return Alloc_rpc_cap_error::OUT_OF_RAM; }
}
void free_rpc_cap(Native_capability cap) override
@ -292,10 +303,10 @@ class Core::Pd_session_component : public Session_object<Pd_session>
** Capability and RAM trading and accounting **
***********************************************/
void ref_account(Capability<Pd_session>) override;
Ref_account_result ref_account(Capability<Pd_session>) override;
void transfer_quota(Capability<Pd_session>, Cap_quota) override;
void transfer_quota(Capability<Pd_session>, Ram_quota) override;
Transfer_cap_quota_result transfer_quota(Capability<Pd_session>, Cap_quota) override;
Transfer_ram_quota_result transfer_quota(Capability<Pd_session>, Ram_quota) override;
Cap_quota cap_quota() const override
{

View File

@ -16,7 +16,6 @@
/* core includes */
#include <signal_source_component.h>
#include <signal_source/capability.h>
#include <signal_context_slab.h>
#include <signal_delivery_proxy.h>
@ -27,12 +26,12 @@ class Core::Signal_broker
{
private:
Allocator &_md_alloc;
Rpc_entrypoint &_source_ep;
Rpc_entrypoint &_context_ep;
Signal_source_component _source;
Signal_source_capability _source_cap;
Signal_context_slab _contexts_slab { _md_alloc };
Allocator &_md_alloc;
Rpc_entrypoint &_source_ep;
Rpc_entrypoint &_context_ep;
Signal_source_component _source;
Capability<Signal_source> _source_cap;
Signal_context_slab _contexts_slab { _md_alloc };
Signal_delivery_proxy_component _delivery_proxy { _source_ep };
public:
@ -60,12 +59,12 @@ class Core::Signal_broker
free_context(r->cap());
}
Signal_source_capability alloc_signal_source() { return _source_cap; }
Capability<Signal_source> alloc_signal_source() { return _source_cap; }
void free_signal_source(Signal_source_capability) { }
void free_signal_source(Capability<Signal_source>) { }
Signal_context_capability
alloc_context(Signal_source_capability, unsigned long imprint)
alloc_context(Capability<Signal_source>, unsigned long imprint)
{
/*
* XXX For now, we ignore the signal-source argument as we

View File

@ -99,78 +99,88 @@ size_t Pd_session_component::dataspace_size(Ram_dataspace_capability ds_cap) con
}
void Pd_session_component::ref_account(Capability<Pd_session> pd_cap)
Pd_session::Ref_account_result Pd_session_component::ref_account(Capability<Pd_session> pd_cap)
{
/* the reference account can be defined only once */
if (_cap_account.constructed())
return;
return Ref_account_result::OK;
if (this->cap() == pd_cap)
return;
return Ref_account_result::OK;
Ref_account_result result = Ref_account_result::INVALID_SESSION;
_ep.apply(pd_cap, [&] (Pd_session_component *pd) {
if (!pd || !pd->_ram_account.constructed()) {
error("invalid PD session specified as ref account");
throw Invalid_session();
}
if (!pd || !pd->_ram_account.constructed())
return;
_cap_account.construct(_cap_quota_guard(), _label, *pd->_cap_account);
_ram_account.construct(_ram_quota_guard(), _label, *pd->_ram_account);
result = Ref_account_result::OK;
});
return result;
}
void Pd_session_component::transfer_quota(Capability<Pd_session> pd_cap,
Cap_quota amount)
Pd_session::Transfer_cap_quota_result
Pd_session_component::transfer_quota(Capability<Pd_session> pd_cap, Cap_quota amount)
{
if (!_cap_account.constructed())
throw Undefined_ref_account();
return Transfer_cap_quota_result::NO_REF_ACCOUNT;
if (this->cap() == pd_cap)
return;
return Transfer_cap_quota_result::OK;
Transfer_cap_quota_result result = Transfer_cap_quota_result::INVALID_SESSION;
_ep.apply(pd_cap, [&] (Pd_session_component *pd) {
if (!pd || !pd->_cap_account.constructed())
throw Invalid_session();
return;
try {
_cap_account->transfer_quota(*pd->_cap_account, amount);
diag("transferred ", amount, " caps "
"to '", pd->_cap_account->label(), "' (", _cap_account, ")");
result = Transfer_cap_quota_result::OK;
}
catch (Account<Cap_quota>::Unrelated_account) {
warning("attempt to transfer cap quota to unrelated PD session");
throw Invalid_session(); }
catch (Account<Cap_quota>::Unrelated_account) { }
catch (Account<Cap_quota>::Limit_exceeded) {
throw Out_of_caps(); }
result = Transfer_cap_quota_result::OUT_OF_CAPS;
}
});
return result;
}
void Pd_session_component::transfer_quota(Capability<Pd_session> pd_cap,
Ram_quota amount)
Pd_session::Transfer_ram_quota_result
Pd_session_component::transfer_quota(Capability<Pd_session> pd_cap, Ram_quota amount)
{
if (!_ram_account.constructed())
throw Undefined_ref_account();
return Transfer_ram_quota_result::NO_REF_ACCOUNT;
if (this->cap() == pd_cap)
return;
return Transfer_ram_quota_result::OK;
Transfer_ram_quota_result result = Transfer_ram_quota_result::INVALID_SESSION;
_ep.apply(pd_cap, [&] (Pd_session_component *pd) {
if (!pd || !pd->_ram_account.constructed())
throw Invalid_session();
return;
try {
_ram_account->transfer_quota(*pd->_ram_account, amount); }
catch (Account<Ram_quota>::Unrelated_account) {
warning("attempt to transfer RAM quota to unrelated PD session");
throw Invalid_session(); }
_ram_account->transfer_quota(*pd->_ram_account, amount);
result = Transfer_ram_quota_result::OK;
}
catch (Account<Ram_quota>::Unrelated_account) { }
catch (Account<Ram_quota>::Limit_exceeded) {
throw Out_of_ram(); }
result = Transfer_ram_quota_result::OUT_OF_RAM;
}
});
return result;
}

View File

@ -18,9 +18,14 @@
using namespace Core;
bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; }
void Pd_session_component::map(addr_t, addr_t) { }
Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range)
{
return Map_result::OK;
}
class System_control_dummy : public System_control

View File

@ -83,26 +83,30 @@ struct Genode::Expanding_pd_session_client : Pd_session_client
}
}
void transfer_quota(Pd_session_capability pd_session, Ram_quota amount) override
Transfer_ram_quota_result transfer_quota(Pd_session_capability pd_session, Ram_quota amount) override
{
/*
* Should the transfer fail because we don't have enough quota, request
* the needed amount from the parent.
*/
enum { NUM_ATTEMPTS = 2 };
retry<Out_of_ram>(
[&] () { Pd_session_client::transfer_quota(pd_session, amount); },
[&] () { _request_ram_from_parent(amount.value); },
NUM_ATTEMPTS);
for (;;) {
auto const result = Pd_session_client::transfer_quota(pd_session, amount);
if (result != Transfer_ram_quota_result::OUT_OF_RAM)
return result;
_request_ram_from_parent(amount.value);
}
}
void transfer_quota(Pd_session_capability pd_session, Cap_quota amount) override
Transfer_cap_quota_result transfer_quota(Pd_session_capability pd_session, Cap_quota amount) override
{
enum { NUM_ATTEMPTS = 2 };
retry<Out_of_caps>(
[&] () { Pd_session_client::transfer_quota(pd_session, amount); },
[&] () { _request_caps_from_parent(amount.value); },
NUM_ATTEMPTS);
for (;;) {
auto const result = Pd_session_client::transfer_quota(pd_session, amount);
if (result != Transfer_cap_quota_result::OUT_OF_CAPS)
return result;
_request_caps_from_parent(amount.value);
}
}
};

View File

@ -1,22 +0,0 @@
/*
* \brief Signal-source capability type
* \author Norman Feske
* \date 2016-01-04
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_
#define _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_
#include <base/capability.h>
#include <signal_source/signal_source.h>
namespace Genode { typedef Capability<Signal_source> Signal_source_capability; }
#endif /* _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_ */

View File

@ -45,9 +45,21 @@ Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session &pd,
Ram_quota ram_upgrade { 0 };
Cap_quota cap_upgrade { 0 };
try { return pd.alloc_rpc_cap(_cap); }
catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; }
catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
using Error = Pd_session::Alloc_rpc_cap_error;
Native_capability result { };
pd.alloc_rpc_cap(_cap).with_result(
[&] (Native_capability cap) { result = cap; },
[&] (Error e) {
switch (e) {
case Error::OUT_OF_RAM: ram_upgrade = { 2*1024*sizeof(long) }; break;
case Error::OUT_OF_CAPS: cap_upgrade = { 4 }; break;
}
});
if (result.valid())
return result;
_parent().upgrade(Parent::Env::pd(),
String<100>("ram_quota=", ram_upgrade, ", "

View File

@ -46,12 +46,15 @@ class Signal_handler_thread : Thread, Blockade
void entry() override
{
_signal_source.construct(_cpu, _pd.alloc_signal_source());
wakeup();
Signal_receiver::dispatch_signals(*_signal_source);
_pd.signal_source().with_result([&] (Capability<Signal_source> source) {
_signal_source.construct(_cpu, source);
wakeup();
Signal_receiver::dispatch_signals(*_signal_source); },
[&] (Pd_session::Signal_source_error) {
error("failed to initialize signal-source interface"); });
}
enum { STACK_SIZE = 4*1024*sizeof(addr_t) };
static constexpr size_t STACK_SIZE = 4*1024*sizeof(addr_t);
public:

View File

@ -83,7 +83,7 @@ void Device_pd::add_range(Io_mmu::Range const & range,
_pd.attach_dma(cap, range.start).with_result(
[&] (Pd_session::Attach_dma_ok) {
/* trigger eager mapping of memory */
_pd.map(range.start, range.size);
_pd.map(Pd_session::Virt_range { range.start, range.size });
retry = false;
},
[&] (Pd_session::Attach_dma_error e) {
@ -123,7 +123,7 @@ void Device_pd::enable_pci_device(Io_mem_dataspace_capability const io_mem_cap,
throw Region_map::Region_conflict();
/* trigger eager mapping of memory */
_pd.map(addr, 0x1000);
_pd.map(Pd_session::Virt_range { addr, 0x1000 });
/* try to assign pci device to this protection domain */
if (!_pd.assign_pci(addr, Pci::Bdf::rid(bdf)))

View File

@ -118,9 +118,10 @@ class Sandbox::Routed_service : public Async_service, public Abandonable
/**
* Ram_transfer::Account interface
*/
void transfer(Pd_session_capability to, Ram_quota amount) override
Ram_transfer_result transfer(Pd_session_capability to, Ram_quota amount) override
{
if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount);
return to.valid() ? _pd_accessor.pd().transfer_quota(to, amount)
: Ram_transfer_result::OK;
}
/**
@ -134,9 +135,10 @@ class Sandbox::Routed_service : public Async_service, public Abandonable
/**
* Cap_transfer::Account interface
*/
void transfer(Pd_session_capability to, Cap_quota amount) override
Cap_transfer_result transfer(Pd_session_capability to, Cap_quota amount) override
{
if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount);
return to.valid() ? _pd_accessor.pd().transfer_quota(to, amount)
: Cap_transfer_result::OK;
}
/**

View File

@ -198,16 +198,16 @@ struct Monitor::Inferior_pd : Monitored_pd_session
bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override {
return _real.call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
void map(addr_t virt, addr_t size) override {
_real.call<Rpc_map>(virt, size); }
Map_result map(Virt_range range) override {
return _real.call<Rpc_map>(range); }
Signal_source_capability alloc_signal_source() override {
return _real.call<Rpc_alloc_signal_source>(); }
Signal_source_result signal_source() override {
return _real.call<Rpc_signal_source>(); }
void free_signal_source(Signal_source_capability cap) override {
void free_signal_source(Capability<Signal_source> cap) override {
_real.call<Rpc_free_signal_source>(cap); }
Alloc_context_result alloc_context(Signal_source_capability source,
Alloc_context_result alloc_context(Capability<Signal_source> source,
Imprint imprint) override {
return _real.call<Rpc_alloc_context>(source, imprint); }
@ -217,7 +217,7 @@ struct Monitor::Inferior_pd : Monitored_pd_session
void submit(Signal_context_capability receiver, unsigned cnt = 1) override {
_real.call<Rpc_submit>(receiver, cnt); }
Native_capability alloc_rpc_cap(Native_capability ep) override {
Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) override {
return _real.call<Rpc_alloc_rpc_cap>(ep); }
void free_rpc_cap(Native_capability cap) override {

View File

@ -44,29 +44,39 @@ struct Monitor::Monitored_pd_session : Monitored_rpc_object<Pd_session>
** Pd_session interface **
**************************/
void ref_account(Capability<Pd_session> pd_cap) override
{
_with_pd_arg(pd_cap,
[&] (Monitored_pd_session &pd) { _real.call<Rpc_ref_account>(pd._real); },
[&] { _real.call<Rpc_ref_account>(pd_cap); });
}
void transfer_quota(Capability<Pd_session> pd_cap, Cap_quota amount) override
Ref_account_result ref_account(Capability<Pd_session> pd_cap) override
{
Ref_account_result result = Ref_account_result::INVALID_SESSION;
_with_pd_arg(pd_cap,
[&] (Monitored_pd_session &pd) {
_real.call<Rpc_transfer_cap_quota>(pd._real, amount); },
result = _real.call<Rpc_ref_account>(pd._real); },
[&] {
_real.call<Rpc_transfer_cap_quota>(pd_cap, amount); });
result = _real.call<Rpc_ref_account>(pd_cap); });
return result;
}
void transfer_quota(Pd_session_capability pd_cap, Ram_quota amount) override
Transfer_cap_quota_result transfer_quota(Capability<Pd_session> pd_cap,
Cap_quota amount) override
{
Transfer_cap_quota_result result = Transfer_cap_quota_result::INVALID_SESSION;
_with_pd_arg(pd_cap,
[&] (Monitored_pd_session &pd) {
_real.call<Rpc_transfer_ram_quota>(pd._real, amount); },
result = _real.call<Rpc_transfer_cap_quota>(pd._real, amount); },
[&] {
_real.call<Rpc_transfer_ram_quota>(pd_cap, amount); });
result = _real.call<Rpc_transfer_cap_quota>(pd_cap, amount); });
return result;
}
Transfer_ram_quota_result transfer_quota(Pd_session_capability pd_cap,
Ram_quota amount) override
{
Transfer_ram_quota_result result = Transfer_ram_quota_result::INVALID_SESSION;
_with_pd_arg(pd_cap,
[&] (Monitored_pd_session &pd) {
result = _real.call<Rpc_transfer_ram_quota>(pd._real, amount); },
[&] {
result = _real.call<Rpc_transfer_ram_quota>(pd_cap, amount); });
return result;
}
};

View File

@ -35,7 +35,7 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics
{
using Monitored_pd_session::Monitored_pd_session;
using Sig_src_cap = Signal_source_capability;
using Sig_src_cap = Capability<Signal_source>;
using Sig_ctx_cap = Signal_context_capability;
using Ram_ds_cap = Ram_dataspace_capability;
using Mng_sys_state = Managing_system_state;
@ -43,13 +43,13 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics
void assign_parent(Capability<Parent>) override { never_called(__func__); };
bool assign_pci(addr_t, uint16_t) override { never_called(__func__); };
void map(addr_t, addr_t) override { never_called(__func__); };
Sig_src_cap alloc_signal_source() override { never_called(__func__); };
Map_result map(Virt_range) override { never_called(__func__); };
Signal_source_result signal_source() override { never_called(__func__); };
void free_signal_source(Sig_src_cap) override { never_called(__func__); };
Alloc_context_result alloc_context(Sig_src_cap, Imprint) override { never_called(__func__); };
void free_context(Sig_ctx_cap) override { never_called(__func__); };
void submit(Sig_ctx_cap, unsigned) override { never_called(__func__); };
Native_capability alloc_rpc_cap(Native_capability) override { never_called(__func__); };
Alloc_rpc_cap_result alloc_rpc_cap(Native_capability) override { never_called(__func__); };
void free_rpc_cap(Native_capability) override { never_called(__func__); };
Capability<Region_map> address_space() override { never_called(__func__); };
Capability<Region_map> stack_area() override { never_called(__func__); };