diff --git a/repos/base-foc/src/core/native_pd_component.cc b/repos/base-foc/src/core/native_pd_component.cc
index 98889d221..6b479a275 100644
--- a/repos/base-foc/src/core/native_pd_component.cc
+++ b/repos/base-foc/src/core/native_pd_component.cc
@@ -28,13 +28,13 @@ Native_pd_component::Native_pd_component(Pd_session_component &pd_session,
:
_pd_session(pd_session)
{
- _pd_session._thread_ep.manage(this);
+ _pd_session._ep.manage(this);
}
Native_pd_component::~Native_pd_component()
{
- _pd_session._thread_ep.dissolve(this);
+ _pd_session._ep.dissolve(this);
}
diff --git a/repos/base-hw/src/core/env.cc b/repos/base-hw/src/core/env.cc
index 410d4f3d3..45b3afdae 100644
--- a/repos/base-hw/src/core/env.cc
+++ b/repos/base-hw/src/core/env.cc
@@ -14,5 +14,6 @@
#include
#include
-void Genode::upgrade_pd_quota_non_blocking(Genode::size_t quota) {
- ASSERT_NEVER_CALLED; }
+using namespace Genode;
+
+void Genode::upgrade_pd_quota_non_blocking(Ram_quota, Cap_quota) { ASSERT_NEVER_CALLED; }
diff --git a/repos/base-hw/src/core/pd_upgrade_ram_quota.cc b/repos/base-hw/src/core/pd_upgrade_ram_quota.cc
index 9b49d3f8c..d44cd5a57 100644
--- a/repos/base-hw/src/core/pd_upgrade_ram_quota.cc
+++ b/repos/base-hw/src/core/pd_upgrade_ram_quota.cc
@@ -17,9 +17,8 @@
using namespace Genode;
-void Pd_session_component::upgrade_ram_quota(size_t ram_quota)
+void Pd_session_component::session_quota_upgraded()
{
- _md_alloc.upgrade(ram_quota);
- _pd.upgrade_slab(_md_alloc);
+ _pd.upgrade_slab(_sliced_heap);
}
diff --git a/repos/base-hw/src/include/base/internal/native_env.h b/repos/base-hw/src/include/base/internal/native_env.h
index ed7397dc0..0ec6579c6 100644
--- a/repos/base-hw/src/include/base/internal/native_env.h
+++ b/repos/base-hw/src/include/base/internal/native_env.h
@@ -16,6 +16,7 @@
/* Genode includes */
#include
+#include
namespace Genode
{
@@ -26,7 +27,7 @@ namespace Genode
* needed when doing upgrades in situations where the environment is
* already locked due to the operation that triggered the upgrade.
*/
- void upgrade_pd_quota_non_blocking(size_t);
+ void upgrade_pd_quota_non_blocking(Ram_quota, Cap_quota);
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_ENV_H_ */
diff --git a/repos/base-hw/src/lib/base/env.cc b/repos/base-hw/src/lib/base/env.cc
index ca352a4bd..e38f367b0 100644
--- a/repos/base-hw/src/lib/base/env.cc
+++ b/repos/base-hw/src/lib/base/env.cc
@@ -18,8 +18,9 @@
#include
#include
-void Genode::upgrade_pd_quota_non_blocking(size_t quota)
+void Genode::upgrade_pd_quota_non_blocking(Ram_quota ram, Cap_quota caps)
{
internal_env().parent().upgrade(Parent::Env::pd(),
- String<64>("ram_quota=", quota).string());
+ String<100>("ram_quota=", ram, ", "
+ "cap_quota=", caps).string());
}
diff --git a/repos/base-hw/src/lib/base/ipc.cc b/repos/base-hw/src/lib/base/ipc.cc
index 3884faaa5..5da1381bf 100644
--- a/repos/base-hw/src/lib/base/ipc.cc
+++ b/repos/base-hw/src/lib/base/ipc.cc
@@ -109,7 +109,8 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
}
},
- [&] () { upgrade_pd_quota_non_blocking(3 * 1024 * sizeof(addr_t)); });
+ [&] () { upgrade_pd_quota_non_blocking(Ram_quota{3 * 1024 * sizeof(addr_t)},
+ Cap_quota{0}); });
return Rpc_exception_code(utcb.exception_code());
}
@@ -154,7 +155,8 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
default: break;
}
},
- [&] () { upgrade_pd_quota_non_blocking(3 * 1024 * sizeof(addr_t)); });
+ [&] () { upgrade_pd_quota_non_blocking(Ram_quota{3 * 1024 * sizeof(addr_t)},
+ Cap_quota{0}); });
copy_utcb_to_msg(utcb, request_msg);
diff --git a/repos/base-hw/src/lib/base/signal.cc b/repos/base-hw/src/lib/base/signal.cc
index a03ac7ecc..41c4987c2 100644
--- a/repos/base-hw/src/lib/base/signal.cc
+++ b/repos/base-hw/src/lib/base/signal.cc
@@ -66,13 +66,22 @@ void Signal_transmitter::submit(unsigned cnt)
Signal_receiver::Signal_receiver()
{
- retry(
- [&] () { _cap = internal_env().pd().alloc_signal_source(); },
- [&] () {
- log("upgrading quota donation for PD session");
- internal_env().upgrade(Parent::Env::pd(), "ram_quota=8K");
+ for (;;) {
+
+ Ram_quota ram_upgrade { 0 };
+ Cap_quota cap_upgrade { 0 };
+
+ try {
+ _cap = internal_env().pd().alloc_signal_source();
+ break;
}
- );
+ catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; }
+ catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
+
+ internal_env().upgrade(Parent::Env::pd(),
+ String<100>("ram_quota=", ram_upgrade, ", "
+ "cap_quota=", cap_upgrade).string());
+ }
}
@@ -98,17 +107,23 @@ Signal_context_capability Signal_receiver::manage(Signal_context * const c)
Lock::Guard context_guard(c->_lock);
if (c->_receiver) { throw Context_already_in_use(); }
- retry(
- [&] () {
+ for (;;) {
+
+ Ram_quota ram_upgrade { 0 };
+ Cap_quota cap_upgrade { 0 };
+
+ try {
/* use signal context as imprint */
c->_cap = env_deprecated()->pd_session()->alloc_context(_cap, (unsigned long)c);
c->_receiver = this;
_contexts.insert(&c->_receiver_le);
return c->_cap;
- },
- [&] () { upgrade_pd_quota_non_blocking(1024 * sizeof(addr_t)); });
+ }
+ catch (Out_of_ram) { ram_upgrade = Ram_quota { 1024*sizeof(long) }; }
+ catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
- return c->_cap;
+ upgrade_pd_quota_non_blocking(ram_upgrade, cap_upgrade);
+ }
}
diff --git a/repos/base-hw/src/test/cpu_quota/sync/main.cc b/repos/base-hw/src/test/cpu_quota/sync/main.cc
index b9c015468..4d306c090 100644
--- a/repos/base-hw/src/test/cpu_quota/sync/main.cc
+++ b/repos/base-hw/src/test/cpu_quota/sync/main.cc
@@ -52,7 +52,7 @@ struct Sync_root : public Root_component
Session_component *_create_session(char const *args) override
{
try { return new (md_alloc()) Session_component(*this); }
- catch (...) { throw Root::Exception(); }
+ catch (...) { throw Root::Invalid_args(); }
}
Sync_root(Entrypoint &ep, Allocator &md_alloc)
diff --git a/repos/base-linux/src/core/include/core_env.h b/repos/base-linux/src/core/include/core_env.h
index 41cfda208..817061925 100644
--- a/repos/base-linux/src/core/include/core_env.h
+++ b/repos/base-linux/src/core/include/core_env.h
@@ -122,8 +122,8 @@ namespace Genode {
* method to issue out-of-order replies to
* 'Signal_source::wait_for_signal' calls.
*/
- Core_pd_session_component _pd_session_component;
- Pd_session_client _pd_session_client;
+ Core_pd_session_component _pd_session_component { _entrypoint };
+ Pd_session_client _pd_session_client { _pd_session_component.cap() };
Registry _services;
@@ -155,9 +155,7 @@ namespace Genode {
Session::Diag{false},
*platform()->ram_alloc(),
*Platform_env_base::rm_session(),
- Ram_session_component::any_phys_range()),
- _pd_session_component(_entrypoint),
- _pd_session_client(_entrypoint.manage(&_pd_session_component))
+ Ram_session_component::any_phys_range())
{
_ram_session.init_ram_account();
}
diff --git a/repos/base-linux/src/core/native_pd_component.cc b/repos/base-linux/src/core/native_pd_component.cc
index 09a119150..4337939bc 100644
--- a/repos/base-linux/src/core/native_pd_component.cc
+++ b/repos/base-linux/src/core/native_pd_component.cc
@@ -143,7 +143,7 @@ void Native_pd_component::_start(Dataspace_component &ds)
/* prefix name of Linux program (helps killing some zombies) */
char const *prefix = "[Genode] ";
char pname_buf[sizeof(_pd_session._label) + sizeof(prefix)];
- snprintf(pname_buf, sizeof(pname_buf), "%s%s", prefix, _pd_session._label.string);
+ snprintf(pname_buf, sizeof(pname_buf), "%s%s", prefix, _pd_session._label.string());
char *argv_buf[2];
argv_buf[0] = pname_buf;
argv_buf[1] = 0;
@@ -184,7 +184,7 @@ Native_pd_component::Native_pd_component(Pd_session_component &pd_session,
:
_pd_session(pd_session)
{
- _pd_session._thread_ep.manage(this);
+ _pd_session._ep.manage(this);
}
@@ -193,14 +193,14 @@ Native_pd_component::~Native_pd_component()
if (_pid)
lx_kill(_pid, 9);
- _pd_session._thread_ep.dissolve(this);
+ _pd_session._ep.dissolve(this);
}
void Native_pd_component::start(Capability binary)
{
/* lookup binary dataspace */
- _pd_session._thread_ep.apply(binary, [&] (Dataspace_component *ds) {
+ _pd_session._ep.apply(binary, [&] (Dataspace_component *ds) {
if (ds)
_start(*ds);
diff --git a/repos/base-nova/include/nova_native_pd/nova_native_pd.h b/repos/base-nova/include/nova_native_pd/nova_native_pd.h
index b5efdc375..a1250227f 100644
--- a/repos/base-nova/include/nova_native_pd/nova_native_pd.h
+++ b/repos/base-nova/include/nova_native_pd/nova_native_pd.h
@@ -28,7 +28,8 @@ struct Genode::Nova_native_pd : Pd_session::Native_pd
* \param entry server-side instruction pointer of the RPC handler
* \param mtd NOVA message transfer descriptor
*
- * \throw Pd_session::Out_of_metadata
+ * \throw Out_of_ram
+ * \throw Out_of_caps
*
* \return new RPC object capability
*/
@@ -41,7 +42,7 @@ struct Genode::Nova_native_pd : Pd_session::Native_pd
virtual void imprint_rpc_cap(Native_capability cap, unsigned long badge) = 0;
GENODE_RPC_THROW(Rpc_alloc_rpc_cap, Native_capability, alloc_rpc_cap,
- GENODE_TYPE_LIST(Pd_session::Out_of_metadata),
+ GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
Native_capability, addr_t, addr_t);
GENODE_RPC(Rpc_imprint_rpc_cap, void, imprint_rpc_cap,
Native_capability, unsigned long);
diff --git a/repos/base-nova/src/core/native_pd_component.cc b/repos/base-nova/src/core/native_pd_component.cc
index 31c23efd8..a0b7e4838 100644
--- a/repos/base-nova/src/core/native_pd_component.cc
+++ b/repos/base-nova/src/core/native_pd_component.cc
@@ -24,6 +24,7 @@ Native_capability Native_pd_component::alloc_rpc_cap(Native_capability ep,
addr_t entry, addr_t mtd)
{
try {
+ _pd_session._consume_cap(Pd_session_component::RPC_CAP);
return _pd_session._rpc_cap_factory.alloc(ep, entry, mtd); }
catch (Allocator::Out_of_memory) { throw Out_of_ram(); }
@@ -42,13 +43,13 @@ Native_pd_component::Native_pd_component(Pd_session_component &pd_session,
:
_pd_session(pd_session)
{
- _pd_session._thread_ep.manage(this);
+ _pd_session._ep.manage(this);
}
Native_pd_component::~Native_pd_component()
{
- _pd_session._thread_ep.dissolve(this);
+ _pd_session._ep.dissolve(this);
}
diff --git a/repos/base-nova/src/lib/base/rpc_cap_alloc.cc b/repos/base-nova/src/lib/base/rpc_cap_alloc.cc
index 59c70a785..ec8a379bf 100644
--- a/repos/base-nova/src/lib/base/rpc_cap_alloc.cc
+++ b/repos/base-nova/src/lib/base/rpc_cap_alloc.cc
@@ -34,18 +34,23 @@ Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session &pd, Native_capabili
Nova_native_pd_client native_pd(_native_pd_cap);
- Untyped_capability new_obj_cap =
- retry(
- [&] () {
- return native_pd.alloc_rpc_cap(ep, entry, 0);
- },
- [&] () {
- internal_env().upgrade(Parent::Env::pd(), "ram_quota=16K");
- });
+ for (;;) {
- native_pd.imprint_rpc_cap(new_obj_cap, new_obj_cap.local_name());
+ Ram_quota ram_upgrade { 0 };
+ Cap_quota cap_upgrade { 0 };
- return new_obj_cap;
+ try {
+ Untyped_capability new_obj_cap = native_pd.alloc_rpc_cap(ep, entry, 0);
+ native_pd.imprint_rpc_cap(new_obj_cap, new_obj_cap.local_name());
+ return new_obj_cap;
+ }
+ catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; }
+ catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
+
+ env_deprecated()->parent()->upgrade(Parent::Env::pd(),
+ String<100>("ram_quota=", ram_upgrade, ", "
+ "cap_quota=", cap_upgrade).string());
+ }
}
diff --git a/repos/base/include/base/allocator.h b/repos/base/include/base/allocator.h
index 2deead4aa..788947cc0 100644
--- a/repos/base/include/base/allocator.h
+++ b/repos/base/include/base/allocator.h
@@ -75,6 +75,7 @@ struct Genode::Allocator : Deallocator
* undefined in the error case
*
* \throw Out_of_ram
+ * \throw Out_of_caps
*
* \return true on success
*/
@@ -89,6 +90,7 @@ struct Genode::Allocator : Deallocator
* pointer will break strict-aliasing rules".
*
* \throw Out_of_ram
+ * \throw Out_of_caps
*/
template bool alloc(size_t size, T **out_addr)
{
@@ -114,6 +116,7 @@ struct Genode::Allocator : Deallocator
* \param size block size to allocate
*
* \throw Out_of_ram
+ * \throw Out_of_caps
*
* \return pointer to the new block
*/
diff --git a/repos/base/include/base/attached_io_mem_dataspace.h b/repos/base/include/base/attached_io_mem_dataspace.h
index 0b6050293..8f16a45fd 100644
--- a/repos/base/include/base/attached_io_mem_dataspace.h
+++ b/repos/base/include/base/attached_io_mem_dataspace.h
@@ -47,8 +47,10 @@ class Genode::Attached_io_mem_dataspace
*
* \throw Parent::Service_denied
* \throw Insufficient_ram_quota
+ * \throw Insufficient_cap_quota
* \throw Parent::Unavailable
* \throw Out_of_ram
+ * \throw Out_of_caps
* \throw Rm_session::Attach_failed
*/
Attached_io_mem_dataspace(Env &env, Genode::addr_t base, Genode::size_t size,
diff --git a/repos/base/include/base/attached_ram_dataspace.h b/repos/base/include/base/attached_ram_dataspace.h
index dc0b0f634..d82645eba 100644
--- a/repos/base/include/base/attached_ram_dataspace.h
+++ b/repos/base/include/base/attached_ram_dataspace.h
@@ -91,6 +91,7 @@ class Genode::Attached_ram_dataspace
* Constructor
*
* \throw Out_of_ram
+ * \throw Out_of_caps
* \throw Rm_session::Attach_failed
*/
Attached_ram_dataspace(Ram_session &ram, Region_map &rm,
diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h
index 78612b2b1..a51f189ba 100644
--- a/repos/base/include/base/child.h
+++ b/repos/base/include/base/child.h
@@ -134,6 +134,15 @@ struct Genode::Child_policy
log("child \"", name(), "\" exited with exit value ", exit_value);
}
+ /**
+ * Reference PD session
+ *
+ * The PD session returned by this method is used for session cap-quota
+ * transfers.
+ */
+ virtual Pd_session &ref_pd() = 0;
+ virtual Pd_session_capability ref_pd_cap() const = 0;
+
/**
* Reference RAM session
*
@@ -393,6 +402,7 @@ class Genode::Child : protected Rpc_object,
* \throw Invalid_executable
* \throw Region_map::Attach_failed
* \throw Out_of_ram
+ * \throw Out_of_caps
*
* The other arguments correspond to those of 'Child::Child'.
*
@@ -487,6 +497,25 @@ class Genode::Child : protected Rpc_object,
Ram_transfer::Account &to = _service;
return to.cap(Ram_quota());
}
+
+ /**
+ * Service (Cap_transfer::Account) interface
+ */
+ void transfer(Pd_session_capability to, Cap_quota amount) override
+ {
+ Cap_transfer::Account &from = _service;
+ from.transfer(to, amount);
+ }
+
+ /**
+ * Service (Cap_transfer::Account) interface
+ */
+ Pd_session_capability cap(Cap_quota) const override
+ {
+ Cap_transfer::Account &to = _service;
+ return to.cap(Cap_quota());
+ }
+
void wakeup() override { _service.wakeup(); }
bool operator == (Service const &other) const override
@@ -662,6 +691,13 @@ class Genode::Child : protected Rpc_object,
2*Rom_connection::RAM_QUOTA };
}
+ static Cap_quota env_cap_quota()
+ {
+ return { Cpu_connection::CAP_QUOTA + Ram_connection::CAP_QUOTA +
+ Pd_connection::CAP_QUOTA + Log_connection::CAP_QUOTA +
+ 2*Rom_connection::CAP_QUOTA + 1 /* parent cap */ };
+ }
+
template
void for_each_session(FN const &fn) const
{
@@ -676,7 +712,16 @@ class Genode::Child : protected Rpc_object,
return _effective_quota(quota, env_ram_quota());
}
+ /**
+ * Deduce env session costs from usable cap quota
+ */
+ static Cap_quota effective_quota(Cap_quota quota)
+ {
+ return _effective_quota(quota, env_cap_quota());
+ }
+
Ram_session_capability ram_session_cap() const { return _ram.cap(); }
+ Pd_session_capability pd_session_cap() const { return _pd.cap(); }
Parent_capability parent_cap() const { return cap(); }
@@ -684,6 +729,7 @@ class Genode::Child : protected Rpc_object,
Ram_session const &ram() const { return _ram.session(); }
Cpu_session &cpu() { return _cpu.session(); }
Pd_session &pd() { return _pd .session(); }
+ Pd_session const &pd() const { return _pd .session(); }
/**
* Request factory for creating session-state objects
diff --git a/repos/base/include/base/connection.h b/repos/base/include/base/connection.h
index 98117ab11..27b13b53f 100644
--- a/repos/base/include/base/connection.h
+++ b/repos/base/include/base/connection.h
@@ -52,10 +52,17 @@ class Genode::Connection_base : public Noncopyable
*/
Connection_base();
+
+ void upgrade(Session::Resources resources)
+ {
+ String<80> const args("ram_quota=", resources.ram_quota, ", "
+ "cap_quota=", resources.cap_quota);
+ _env.upgrade(_id_space_element.id(), args.string());
+ }
+
void upgrade_ram(size_t bytes)
{
- String<64> const args("ram_quota=", Ram_quota{bytes});
- _env.upgrade(_id_space_element.id(), args.string());
+ upgrade(Session::Resources { Ram_quota{bytes}, Cap_quota{0} });
}
};
diff --git a/repos/base/include/base/env.h b/repos/base/include/base/env.h
index 5cb66a546..da9657cd0 100644
--- a/repos/base/include/base/env.h
+++ b/repos/base/include/base/env.h
@@ -93,8 +93,12 @@ struct Genode::Env
* \param affinity preferred CPU affinity for the session
*
* \throw Service_denied
+ * \throw Insufficient_cap_quota
* \throw Insufficient_ram_quota
- * \throw Unavailable
+ * \throw Out_of_caps
+ * \throw Out_of_ram
+ *
+ * See the documentation of 'Parent::session'.
*
* This method blocks until the session is available or an error
* occurred.
@@ -116,6 +120,9 @@ struct Genode::Env
* \param args description of the amount of quota to transfer
*
* \throw Out_of_ram
+ * \throw Out_of_caps
+ *
+ * See the documentation of 'Parent::upgrade'.
*
* The 'args' argument has the same principle format as the 'args'
* argument of the 'session' operation.
diff --git a/repos/base/include/base/local_connection.h b/repos/base/include/base/local_connection.h
index 02337bbae..6e925a404 100644
--- a/repos/base/include/base/local_connection.h
+++ b/repos/base/include/base/local_connection.h
@@ -39,7 +39,7 @@ struct Genode::Local_connection_base : Noncopyable
private:
- static Args _init_args(Args const &args, size_t const &ram_quota,
+ static Args _init_args(Args const &args, Session::Resources resources,
Session::Diag diag)
{
/* copy original arguments into modifiable buffer */
@@ -47,7 +47,9 @@ struct Genode::Local_connection_base : Noncopyable
strncpy(buf, args.string(), sizeof(buf));
Arg_string::set_arg(buf, sizeof(buf), "ram_quota",
- String<64>(ram_quota).string());
+ String<64>(resources.ram_quota.value).string());
+ Arg_string::set_arg(buf, sizeof(buf), "cap_quota",
+ String<64>(resources.cap_quota.value).string());
Arg_string::set_arg(buf, sizeof(buf), "diag", diag.enabled);
/* return result as a copy */
@@ -62,23 +64,35 @@ struct Genode::Local_connection_base : Noncopyable
Args const &args, Affinity const &affinity,
Session::Label const &label,
Session::Diag diag,
- size_t ram_quota)
+ Session::Resources resources)
{
enum { NUM_ATTEMPTS = 10 };
for (unsigned i = 0; i < NUM_ATTEMPTS; i++) {
_session_state.construct(service, id_space, id, label,
- _init_args(args, ram_quota, diag),
+ _init_args(args, resources, diag),
affinity);
_session_state->service().initiate_request(*_session_state);
- if (_session_state->phase == Session_state::INSUFFICIENT_RAM_QUOTA)
- ram_quota += 4096;
- else
+ if (_session_state->alive())
break;
+
+ switch (_session_state->phase) {
+
+ case Session_state::INSUFFICIENT_RAM_QUOTA:
+ resources.ram_quota.value += 4096;
+ break;
+
+ case Session_state::INSUFFICIENT_CAP_QUOTA:
+ resources.cap_quota.value += 1;
+ break;
+
+ default: break;
+ }
}
- if (_session_state->phase == Session_state::INSUFFICIENT_RAM_QUOTA)
+ if (_session_state->phase == Session_state::INSUFFICIENT_RAM_QUOTA
+ || _session_state->phase == Session_state::INSUFFICIENT_CAP_QUOTA)
warning("giving up to increase session quota for ", service.name(), " session "
"after ", (int)NUM_ATTEMPTS, " attempts");
}
@@ -153,7 +167,8 @@ class Genode::Local_connection : Local_connection_base
Local_connection_base(service, id_space, id, args, affinity,
label.valid() ? label : label_from_args(args.string()),
diag,
- CONNECTION::RAM_QUOTA)
+ Session::Resources { Ram_quota { CONNECTION::RAM_QUOTA },
+ Cap_quota { CONNECTION::CAP_QUOTA } })
{
service.wakeup();
}
diff --git a/repos/base/include/base/service.h b/repos/base/include/base/service.h
index 473283280..1e1f958f1 100644
--- a/repos/base/include/base/service.h
+++ b/repos/base/include/base/service.h
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
#include
@@ -33,7 +34,8 @@ namespace Genode {
}
-class Genode::Service : public Ram_transfer::Account
+class Genode::Service : public Ram_transfer::Account,
+ public Cap_transfer::Account
{
public:
@@ -126,6 +128,7 @@ class Genode::Local_service : public Service
*
* \throw Denied
* \throw Insufficient_ram_quota
+ * \throw Insufficient_cap_quota
*/
virtual SESSION &create(Args const &, Affinity) = 0;
@@ -192,6 +195,8 @@ class Genode::Local_service : public Service
}
catch (typename Factory::Denied) {
session.phase = Session_state::INVALID_ARGS; }
+ catch (Insufficient_cap_quota) {
+ session.phase = Session_state::INSUFFICIENT_CAP_QUOTA; }
catch (Insufficient_ram_quota) {
session.phase = Session_state::INSUFFICIENT_RAM_QUOTA; }
@@ -199,7 +204,8 @@ class Genode::Local_service : public Service
case Session_state::UPGRADE_REQUESTED:
{
- String<64> const args("ram_quota=", session.ram_upgrade);
+ String<100> const args("ram_quota=", session.ram_upgrade, ", "
+ "cap_quota=", session.cap_upgrade);
_apply_to_rpc_obj(session, [&] (SESSION &rpc_obj) {
_factory.upgrade(rpc_obj, args.string()); });
@@ -220,6 +226,7 @@ class Genode::Local_service : public Service
case Session_state::INVALID_ARGS:
case Session_state::INSUFFICIENT_RAM_QUOTA:
+ case Session_state::INSUFFICIENT_CAP_QUOTA:
case Session_state::AVAILABLE:
case Session_state::CAP_HANDED_OUT:
case Session_state::CLOSED:
@@ -279,10 +286,19 @@ class Genode::Parent_service : public Service
catch (Out_of_ram) {
session.id_at_parent.destruct();
session.phase = Session_state::INVALID_ARGS; }
+
+ catch (Out_of_caps) {
+ session.id_at_parent.destruct();
+ session.phase = Session_state::INVALID_ARGS; }
+
catch (Insufficient_ram_quota) {
session.id_at_parent.destruct();
session.phase = Session_state::INSUFFICIENT_RAM_QUOTA; }
+ catch (Insufficient_cap_quota) {
+ session.id_at_parent.destruct();
+ session.phase = Session_state::INSUFFICIENT_CAP_QUOTA; }
+
catch (Parent::Service_denied) {
session.id_at_parent.destruct();
session.phase = Session_state::INVALID_ARGS; }
@@ -291,7 +307,8 @@ class Genode::Parent_service : public Service
case Session_state::UPGRADE_REQUESTED:
{
- String<64> const args("ram_quota=", session.ram_upgrade);
+ String<100> const args("ram_quota=", session.ram_upgrade, ", "
+ "cap_quota=", session.cap_upgrade);
if (!session.id_at_parent.constructed())
error("invalid parent-session state: ", session);
@@ -300,6 +317,8 @@ class Genode::Parent_service : public Service
_env.upgrade(session.id_at_parent->id(), args.string()); }
catch (Out_of_ram) {
warning("RAM quota exceeded while upgrading parent session"); }
+ catch (Out_of_caps) {
+ warning("cap quota exceeded while upgrading parent session"); }
session.confirm_ram_upgrade();
session.phase = Session_state::CAP_HANDED_OUT;
@@ -317,6 +336,7 @@ class Genode::Parent_service : public Service
case Session_state::INVALID_ARGS:
case Session_state::INSUFFICIENT_RAM_QUOTA:
+ case Session_state::INSUFFICIENT_CAP_QUOTA:
case Session_state::AVAILABLE:
case Session_state::CAP_HANDED_OUT:
case Session_state::CLOSED:
@@ -398,6 +418,7 @@ class Genode::Child_service : public Async_service
private:
Ram_session_client _ram;
+ Pd_session_client _pd;
public:
@@ -408,10 +429,11 @@ class Genode::Child_service : public Async_service
Id_space &server_id_space,
Session_state::Factory &factory,
Wakeup &wakeup,
- Ram_session_capability ram)
+ Ram_session_capability ram,
+ Pd_session_capability pd)
:
Async_service(name, server_id_space, factory, wakeup),
- _ram(ram)
+ _ram(ram), _pd(pd)
{ }
/**
@@ -426,6 +448,19 @@ class Genode::Child_service : public Async_service
* Ram_transfer::Account interface
*/
Ram_session_capability cap(Ram_quota) const override { return _ram; }
+
+ /**
+ * Cap_transfer::Account interface
+ */
+ void transfer(Pd_session_capability to, Cap_quota amount) override
+ {
+ if (to.valid()) _pd.transfer_quota(to, amount);
+ }
+
+ /**
+ * Cap_transfer::Account interface
+ */
+ Pd_session_capability cap(Cap_quota) const override { return _pd; }
};
#endif /* _INCLUDE__BASE__SERVICE_H_ */
diff --git a/repos/base/include/base/session_object.h b/repos/base/include/base/session_object.h
index e06c19c87..78943e211 100644
--- a/repos/base/include/base/session_object.h
+++ b/repos/base/include/base/session_object.h
@@ -65,12 +65,14 @@ class Genode::Session_object : public Ram_quota_guard,
Cap_quota_guard(resources.cap_quota),
_ep(ep), _diag(diag), _label(label)
{
+ Cap_quota_guard::withdraw(Cap_quota{1});
_ep.manage(this);
}
~Session_object()
{
_ep.dissolve(this);
+ Cap_quota_guard::replenish(Cap_quota{1});
}
/**
diff --git a/repos/base/include/base/session_state.h b/repos/base/include/base/session_state.h
index a009ec472..d2f96b5ff 100644
--- a/repos/base/include/base/session_state.h
+++ b/repos/base/include/base/session_state.h
@@ -59,6 +59,7 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
* Total of quota associated with this session
*/
Ram_quota _donated_ram_quota { 0 };
+ Cap_quota _donated_cap_quota { 0 };
Factory *_factory = nullptr;
@@ -80,6 +81,7 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
enum Phase { CREATE_REQUESTED,
INVALID_ARGS,
INSUFFICIENT_RAM_QUOTA,
+ INSUFFICIENT_CAP_QUOTA,
AVAILABLE,
CAP_HANDED_OUT,
UPGRADE_REQUESTED,
@@ -107,6 +109,7 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
Session_capability cap;
Ram_quota ram_upgrade { 0 };
+ Cap_quota cap_upgrade { 0 };
void print(Output &out) const;
@@ -150,10 +153,13 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
ram_upgrade = Ram_quota { 0 };
}
- void increase_donated_quota(Ram_quota added_ram_quota)
+ void increase_donated_quota(Ram_quota added_ram_quota,
+ Cap_quota added_cap_quota)
{
_donated_ram_quota.value += added_ram_quota.value;
+ _donated_cap_quota.value += added_cap_quota.value;
ram_upgrade = added_ram_quota;
+ cap_upgrade = added_cap_quota;
}
Parent::Client::Id id_at_client() const
@@ -178,6 +184,7 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
void generate_server_side_info(Xml_generator &, Detail detail) const;
Ram_quota donated_ram_quota() const { return _donated_ram_quota; }
+ Cap_quota donated_cap_quota() const { return _donated_cap_quota; }
bool alive() const
{
@@ -186,6 +193,7 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
case CREATE_REQUESTED:
case INVALID_ARGS:
case INSUFFICIENT_RAM_QUOTA:
+ case INSUFFICIENT_CAP_QUOTA:
case CLOSED:
return false;
diff --git a/repos/base/include/parent/parent.h b/repos/base/include/parent/parent.h
index 7c9a11dcd..f57f0d901 100644
--- a/repos/base/include/parent/parent.h
+++ b/repos/base/include/parent/parent.h
@@ -57,9 +57,8 @@ class Genode::Parent
** Exception types **
*********************/
- class Exception : public ::Genode::Exception { };
- class Service_denied : public Exception { };
- class Unavailable : public Exception { };
+ struct Service_denied : Exception { };
+ struct Unavailable : Exception { };
typedef Rpc_in_buffer<64> Service_name;
typedef Rpc_in_buffer<160> Session_args;
@@ -160,7 +159,9 @@ class Genode::Parent
* \param affinity preferred CPU affinity for the session
*
* \throw Service_denied parent denies session request
+ * \throw Insufficient_cap_quota donated cap quota does not suffice
* \throw Insufficient_ram_quota donated RAM quota does not suffice
+ * \throw Out_of_caps session CAP quota exceeds our resources
* \throw Out_of_ram session RAM quota exceeds our resources
*
* \return session capability of the new session is immediately
@@ -182,8 +183,11 @@ class Genode::Parent
* Request session capability
*
* \throw Service_denied
+ * \throw Insufficient_cap_quota
* \throw Insufficient_ram_quota
*
+ * See 'session' for more documentation.
+ *
* In the exception case, the parent implicitly closes the session.
*/
virtual Session_capability session_cap(Client::Id id) = 0;
@@ -196,6 +200,7 @@ class Genode::Parent
* \param id ID of recipient session
* \param args description of the amount of quota to transfer
*
+ * \throw Out_of_caps
* \throw Out_of_ram
*
* The 'args' argument has the same principle format as the 'args'
@@ -216,7 +221,7 @@ class Genode::Parent
*/
enum Session_response { SESSION_OK, SESSION_CLOSED, INVALID_ARGS,
- INSUFFICIENT_RAM_QUOTA };
+ INSUFFICIENT_RAM_QUOTA, INSUFFICIENT_CAP_QUOTA };
/**
* Set state of a session provided by the child service
@@ -294,16 +299,17 @@ class Genode::Parent
Service_name const &);
GENODE_RPC(Rpc_session_sigh, void, session_sigh, Signal_context_capability);
GENODE_RPC_THROW(Rpc_session, Session_capability, session,
- GENODE_TYPE_LIST(Service_denied, Out_of_ram,
+ GENODE_TYPE_LIST(Service_denied, Out_of_caps,
+ Out_of_ram, Insufficient_cap_quota,
Insufficient_ram_quota, Unavailable),
Client::Id, Service_name const &, Session_args const &,
Affinity const &);
GENODE_RPC_THROW(Rpc_session_cap, Session_capability, session_cap,
- GENODE_TYPE_LIST(Service_denied,
+ GENODE_TYPE_LIST(Service_denied, Insufficient_cap_quota,
Insufficient_ram_quota, Unavailable),
Client::Id);
GENODE_RPC_THROW(Rpc_upgrade, Upgrade_result, upgrade,
- GENODE_TYPE_LIST(Out_of_ram),
+ GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
Client::Id, Upgrade_args const &);
GENODE_RPC(Rpc_close, Close_result, close, Client::Id);
GENODE_RPC(Rpc_session_response, void, session_response,
diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h
index 9a0d7050b..1beffd435 100644
--- a/repos/base/include/pd_session/client.h
+++ b/repos/base/include/pd_session/client.h
@@ -62,6 +62,15 @@ struct Genode::Pd_session_client : Rpc_client
Capability linker_area() override {
return call(); }
+ void ref_account(Capability pd) override {
+ call(pd); }
+
+ void transfer_quota(Capability pd, Cap_quota amount) override {
+ call(pd, amount); }
+
+ Cap_quota cap_quota() const { return call(); }
+ Cap_quota used_caps() const { return call(); }
+
Capability native_pd() override { return call(); }
};
diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h
index ebbfca0ac..782ad939f 100644
--- a/repos/base/include/pd_session/pd_session.h
+++ b/repos/base/include/pd_session/pd_session.h
@@ -71,7 +71,8 @@ struct Genode::Pd_session : Session
typedef Capability Signal_source_capability;
- class Out_of_metadata : public Exception { };
+ class Invalid_session : public Exception { };
+ class Undefined_ref_account : public Exception { };
class Invalid_signal_source : public Exception { };
/**
@@ -81,7 +82,8 @@ struct Genode::Pd_session : Session
*
* The signal source provides an interface to wait for incoming signals.
*
- * \throw Out_of_metadata
+ * \throw Out_of_ram
+ * \throw Out_of_caps
*/
virtual Signal_source_capability alloc_signal_source() = 0;
@@ -102,7 +104,8 @@ struct Genode::Pd_session : Session
* originating from the allocated signal-context capability
* \return new signal-context capability
*
- * \throw Out_of_metadata
+ * \throw Out_of_ram
+ * \throw Out_of_caps
* \throw Invalid_signal_source
*/
virtual Capability
@@ -141,7 +144,8 @@ struct Genode::Pd_session : Session
*
* \param ep entry point that will use this capability
*
- * \throw Out_of_metadata if meta-data backing store is exhausted
+ * \throw Out_of_ram if meta-data backing store is exhausted
+ * \throw Out_of_caps if 'cap_quota' is exceeded
*
* \return new RPC capability
*/
@@ -177,6 +181,49 @@ struct Genode::Pd_session : Session
virtual Capability linker_area() = 0;
+ /*******************************************
+ ** Accounting for capability allocations **
+ *******************************************/
+
+ /**
+ * Define reference account for the PD session
+ *
+ * \throw Invalid_session
+ */
+ virtual void ref_account(Capability) = 0;
+
+ /**
+ * Transfer capability quota to another PD session
+ *
+ * \param pd_session 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,
+ Cap_quota amount) = 0;
+
+ /**
+ * Return current capability-quota limit
+ */
+ virtual Cap_quota cap_quota() const = 0;
+
+ /**
+ * Return number of capabilities allocated from the session
+ */
+ virtual Cap_quota used_caps() const = 0;
+
+ Cap_quota avail_caps() const
+ {
+ return Cap_quota { cap_quota().value - used_caps().value };
+ }
+
+
/*****************************************
** Access to kernel-specific interface **
*****************************************/
@@ -200,30 +247,41 @@ struct Genode::Pd_session : Session
GENODE_RPC(Rpc_assign_pci, bool, assign_pci, addr_t, uint16_t);
GENODE_RPC_THROW(Rpc_alloc_signal_source, Signal_source_capability,
- alloc_signal_source, GENODE_TYPE_LIST(Out_of_metadata));
+ 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_THROW(Rpc_alloc_context, Capability, alloc_context,
- GENODE_TYPE_LIST(Out_of_metadata, Invalid_signal_source),
+ GENODE_TYPE_LIST(Out_of_ram, Out_of_caps, Invalid_signal_source),
Signal_source_capability, unsigned long);
GENODE_RPC(Rpc_free_context, void, free_context,
Capability);
GENODE_RPC(Rpc_submit, void, submit, Capability, unsigned);
GENODE_RPC_THROW(Rpc_alloc_rpc_cap, Native_capability, alloc_rpc_cap,
- GENODE_TYPE_LIST(Out_of_metadata), Native_capability);
+ GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), Native_capability);
GENODE_RPC(Rpc_free_rpc_cap, void, free_rpc_cap, Native_capability);
GENODE_RPC(Rpc_address_space, Capability, address_space);
GENODE_RPC(Rpc_stack_area, Capability, stack_area);
GENODE_RPC(Rpc_linker_area, Capability, linker_area);
+ GENODE_RPC_THROW(Rpc_ref_account, void, ref_account,
+ GENODE_TYPE_LIST(Invalid_session), Capability);
+ GENODE_RPC_THROW(Rpc_transfer_cap_quota, void, transfer_quota,
+ GENODE_TYPE_LIST(Out_of_caps, Invalid_session, Undefined_ref_account),
+ Capability, Cap_quota);
+ GENODE_RPC(Rpc_cap_quota, Cap_quota, cap_quota);
+ GENODE_RPC(Rpc_used_caps, Cap_quota, used_caps);
+
GENODE_RPC(Rpc_native_pd, Capability, native_pd);
GENODE_RPC_INTERFACE(Rpc_assign_parent, Rpc_assign_pci,
Rpc_alloc_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_native_pd);
+ Rpc_stack_area, Rpc_linker_area, Rpc_ref_account,
+ Rpc_transfer_cap_quota, Rpc_cap_quota, Rpc_used_caps,
+ Rpc_native_pd);
};
#endif /* _INCLUDE__PD_SESSION__PD_SESSION_H_ */
diff --git a/repos/base/include/rom_session/connection.h b/repos/base/include/rom_session/connection.h
index c68ec3ade..5834d1736 100644
--- a/repos/base/include/rom_session/connection.h
+++ b/repos/base/include/rom_session/connection.h
@@ -26,7 +26,7 @@ class Genode::Rom_connection : public Connection,
{
public:
- class Rom_connection_failed : public Parent::Exception { };
+ class Rom_connection_failed : public Parent::Service_denied { };
enum { RAM_QUOTA = 6*1024UL };
diff --git a/repos/base/include/root/component.h b/repos/base/include/root/component.h
index c9bc07967..060476635 100644
--- a/repos/base/include/root/component.h
+++ b/repos/base/include/root/component.h
@@ -151,6 +151,24 @@ class Genode::Root_component : public Rpc_object >,
Ram_quota const remaining_ram_quota { ram_quota.value - needed };
+ /*
+ * Validate that the client provided the amount of caps as mandated
+ * for the session interface.
+ */
+ Cap_quota const cap_quota = cap_quota_from_args(args.string());
+
+ if (cap_quota.value < SESSION_TYPE::CAP_QUOTA)
+ throw Insufficient_cap_quota();
+
+ /*
+ * Account for the dataspace capability needed for allocating the
+ * session object from the sliced heap.
+ */
+ if (cap_quota.value < 1)
+ throw Insufficient_cap_quota();
+
+ Cap_quota const remaining_cap_quota { cap_quota.value - 1 };
+
/*
* Deduce ram quota needed for allocating the session object from the
* donated ram quota.
@@ -162,9 +180,13 @@ class Genode::Root_component : public Rpc_object >,
Arg_string::set_arg(adjusted_args, sizeof(adjusted_args),
"ram_quota", String<64>(remaining_ram_quota).string());
+ Arg_string::set_arg(adjusted_args, sizeof(adjusted_args),
+ "cap_quota", String<64>(remaining_cap_quota).string());
+
SESSION_TYPE *s = 0;
try { s = _create_session(adjusted_args, affinity); }
catch (Out_of_ram) { throw Insufficient_ram_quota(); }
+ catch (Out_of_caps) { throw Insufficient_cap_quota(); }
/*
* Consider that the session-object constructor may already have
@@ -281,7 +303,9 @@ class Genode::Root_component : public Rpc_object >,
{
try {
return _create(args, affinity); }
+
catch (Insufficient_ram_quota) { throw; }
+ catch (Insufficient_cap_quota) { throw; }
catch (...) {
throw typename Local_service::Factory::Denied(); }
}
diff --git a/repos/base/include/root/root.h b/repos/base/include/root/root.h
index 585d297ef..fd58d42c5 100644
--- a/repos/base/include/root/root.h
+++ b/repos/base/include/root/root.h
@@ -33,10 +33,8 @@ struct Genode::Root
** Exception types **
*********************/
- class Exception : public ::Genode::Exception { };
- class Unavailable : public Exception { };
- class Quota_exceeded : public Exception { };
- class Invalid_args : public Exception { };
+ class Unavailable : public Exception { };
+ class Invalid_args : public Exception { };
typedef Rpc_in_buffer<160> Session_args;
typedef Rpc_in_buffer<160> Upgrade_args;
@@ -48,6 +46,7 @@ struct Genode::Root
*
* \throw Unavailable
* \throw Insufficient_ram_quota
+ * \throw Insufficient_cap_quota
* \throw Invalid_args
*
* \return capability to new session
@@ -72,7 +71,7 @@ struct Genode::Root
GENODE_RPC_THROW(Rpc_session, Session_capability, session,
GENODE_TYPE_LIST(Unavailable, Insufficient_ram_quota,
- Invalid_args),
+ Insufficient_cap_quota, Invalid_args),
Session_args const &, Affinity const &);
GENODE_RPC_THROW(Rpc_upgrade, void, upgrade,
GENODE_TYPE_LIST(Invalid_args),
diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld
index 3cb2bf6b9..6994b5eab 100644
--- a/repos/base/lib/symbols/ld
+++ b/repos/base/lib/symbols/ld
@@ -188,7 +188,7 @@ _ZN6Genode18server_socket_pairEv T
_ZN6Genode20env_session_id_spaceEv T
_ZN6Genode25env_stack_area_region_mapE B 4
_ZN6Genode26env_stack_area_ram_sessionE B 4
-_ZN6Genode29upgrade_pd_quota_non_blockingEm T
+_ZN6Genode29upgrade_pd_quota_non_blockingENS_9Ram_quotaENS_9Cap_quotaE T
_ZN6Genode3Log3logEv T
_ZN6Genode3Log8_acquireENS0_4TypeE T
_ZN6Genode3Log8_releaseEv T
diff --git a/repos/base/src/core/include/core_env.h b/repos/base/src/core/include/core_env.h
index 397396cd2..ad62f5927 100644
--- a/repos/base/src/core/include/core_env.h
+++ b/repos/base/src/core/include/core_env.h
@@ -112,11 +112,10 @@ namespace Genode {
bool _init_stack_area() { init_stack_area(); return true; }
bool _stack_area_initialized = _init_stack_area();
- Rpc_entrypoint _entrypoint;
- Core_region_map _region_map;
- Ram_session_component _ram_session;
- Ram_session_capability _ram_session_cap;
- Synced_ram_session _synced_ram_session { _ram_session };
+ Rpc_entrypoint _entrypoint;
+ Core_region_map _region_map;
+ Ram_session_component _ram_session;
+ Synced_ram_session _synced_ram_session { _ram_session };
/*
* The core-local PD session is provided by a real RPC object
@@ -159,7 +158,8 @@ namespace Genode {
_region_map,
Ram_session_component::any_phys_range()),
_pd_session_component(_entrypoint),
- _pd_session_client(_entrypoint.manage(&_pd_session_component))
+ _pd_session_client(_pd_session_component.cap()),
+ _heap(_ram_session, _region_map)
{
_ram_session.init_ram_account();
}
@@ -192,7 +192,7 @@ namespace Genode {
Cpu_session_capability cpu_session_cap() override
{
- warning(__func__, " not implemented");
+ warning(__FILE__, ":", __LINE__, " not implemented");
return Cpu_session_capability();
}
diff --git a/repos/base/src/core/include/core_pd_session.h b/repos/base/src/core/include/core_pd_session.h
index a07b99296..f95bbd109 100644
--- a/repos/base/src/core/include/core_pd_session.h
+++ b/repos/base/src/core/include/core_pd_session.h
@@ -30,20 +30,17 @@ class Genode::Core_pd_session_component : public Rpc_object
{
private:
- Rpc_entrypoint &_signal_source_ep;
+ Rpc_entrypoint &_ep;
public:
/**
* Constructor
- *
- * \param context_ep entrypoint that serves the signal-source
- * components
*/
- Core_pd_session_component(Rpc_entrypoint &signal_source_ep)
- :
- _signal_source_ep(signal_source_ep)
- { }
+ Core_pd_session_component(Rpc_entrypoint &ep) : _ep(ep)
+ {
+ ep.manage(this);
+ }
void assign_parent(Capability parent) override
{
@@ -83,7 +80,7 @@ class Genode::Core_pd_session_component : public Rpc_object
void submit(Capability cap, unsigned cnt = 1) override
{
- _signal_source_ep.apply(cap, [&] (Signal_context_component *context) {
+ _ep.apply(cap, [&] (Signal_context_component *context) {
if (!context) {
warning("invalid signal-context capability");
return;
@@ -103,11 +100,17 @@ class Genode::Core_pd_session_component : public Rpc_object
ASSERT_NEVER_CALLED;
}
- Capability address_space() { ASSERT_NEVER_CALLED; }
+ Capability address_space() override { ASSERT_NEVER_CALLED; }
+ Capability stack_area() override { ASSERT_NEVER_CALLED; }
+ Capability linker_area() override { ASSERT_NEVER_CALLED; }
- Capability stack_area() { ASSERT_NEVER_CALLED; }
+ void ref_account(Capability) override { ASSERT_NEVER_CALLED; }
- Capability linker_area() { ASSERT_NEVER_CALLED; }
+ void transfer_quota(Capability, Cap_quota) override {
+ ASSERT_NEVER_CALLED; }
+
+ Cap_quota cap_quota() const { ASSERT_NEVER_CALLED; }
+ Cap_quota used_caps() const { ASSERT_NEVER_CALLED; }
Capability native_pd() override { ASSERT_NEVER_CALLED; }
};
diff --git a/repos/base/src/core/include/pd_root.h b/repos/base/src/core/include/pd_root.h
index 018d52ece..fa46d834b 100644
--- a/repos/base/src/core/include/pd_root.h
+++ b/repos/base/src/core/include/pd_root.h
@@ -29,27 +29,29 @@ class Genode::Pd_root : public Genode::Root_componentupgrade_ram_quota(ram_quota);
+ pd->Ram_quota_guard::upgrade(ram_quota_from_args(args));
+ pd->Cap_quota_guard::upgrade(cap_quota_from_args(args));
+ pd->session_quota_upgraded();
}
public:
@@ -57,16 +59,20 @@ class Genode::Pd_root : public Genode::Root_component(session_ep, md_alloc),
- _thread_ep(*thread_ep), _pager_ep(pager_ep), _md_alloc(*md_alloc) { }
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Allocator &md_alloc)
+ :
+ Root_component(&ep, &md_alloc),
+ _ep(ep), _pager_ep(pager_ep), _ram_alloc(ram_alloc), _local_rm(local_rm)
+ { }
};
#endif /* _CORE__INCLUDE__PD_ROOT_H_ */
diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h
index 1e6cc3ac4..2a46db2be 100644
--- a/repos/base/src/core/include/pd_session_component.h
+++ b/repos/base/src/core/include/pd_session_component.h
@@ -17,9 +17,11 @@
#define _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
/* Genode includes */
+#include
#include
-#include
-#include
+#include
+#include
+#include
#include
#include
@@ -33,88 +35,111 @@
#include
#include
#include
+#include
namespace Genode { class Pd_session_component; }
-class Genode::Pd_session_component : public Rpc_object
+class Genode::Pd_session_component : public Session_object
{
private:
- /**
- * Read and store the PD label
- */
- struct Label {
-
- enum { MAX_LEN = 64 };
- char string[MAX_LEN];
-
- Label(char const *args)
- {
- Arg_string::find_arg(args, "label").string(string,
- sizeof(string), "");
- }
- } const _label;
-
- Allocator_guard _md_alloc; /* guarded meta-data allocator */
- Platform_pd _pd;
- Capability _parent;
- Rpc_entrypoint &_thread_ep;
- Pager_entrypoint &_pager_ep;
- Signal_broker _signal_broker;
- Rpc_cap_factory _rpc_cap_factory;
- Native_pd_component _native_pd;
+ Constrained_ram_allocator _constrained_md_ram_alloc;
+ Sliced_heap _sliced_heap;
+ Platform_pd _pd { &_sliced_heap, _label.string() };
+ Capability _parent;
+ Rpc_entrypoint &_ep;
+ Pager_entrypoint &_pager_ep;
+ Signal_broker _signal_broker { _sliced_heap, _ep, _ep };
+ Rpc_cap_factory _rpc_cap_factory { _sliced_heap };
+ Native_pd_component _native_pd;
Region_map_component _address_space;
Region_map_component _stack_area;
Region_map_component _linker_area;
- size_t _ram_quota(char const * args) {
- return Arg_string::find_arg(args, "ram_quota").long_value(0); }
+ Constructible > _cap_account;
friend class Native_pd_component;
+ enum Cap_type { RPC_CAP, SIG_SOURCE_CAP, SIG_CONTEXT_CAP, IGN_CAP };
+
+ char const *_name(Cap_type type)
+ {
+ switch (type) {
+ case RPC_CAP: return "RPC";
+ case SIG_SOURCE_CAP: return "signal-source";
+ case SIG_CONTEXT_CAP: return "signal-context";
+ default: return "";
+ }
+ }
+
+ /*
+ * \throw Out_of_caps
+ */
+ void _consume_cap(Cap_type type)
+ {
+ try { Cap_quota_guard::withdraw(Cap_quota{1}); }
+ catch (Out_of_caps) {
+ diag("out of caps while consuming ", _name(type), " cap "
+ "(", _cap_account, ")");
+ throw;
+ }
+ diag("consumed ", _name(type), " cap (", _cap_account, ")");
+ }
+
+ void _released_cap_silent() { Cap_quota_guard::replenish(Cap_quota{1}); }
+
+ void _released_cap(Cap_type type)
+ {
+ _released_cap_silent();
+ diag("released ", _name(type), " cap (", _cap_account, ")");
+ }
+
public:
/**
* Constructor
*
- * \param receiver_ep entrypoint holding signal-receiver component
- * objects
- * \param context_ep global pool of all signal contexts
- * \param md_alloc backing-store allocator for
- * signal-context component objects
- *
- * To maintain proper synchronization, 'receiver_ep' must be
- * the same entrypoint as used for the signal-session component.
- * The 'signal_context_ep' is only used for associative array
- * to map signal-context capabilities to 'Signal_context_component'
- * objects and as capability allocator for such objects.
+ * \param ep entrypoint holding signal-receiver component
+ * objects, signal contexts, thread objects
+ * \param ram_alloc backing store for dynamically allocated
+ * session meta data
*/
- Pd_session_component(Rpc_entrypoint &thread_ep,
- Rpc_entrypoint &receiver_ep,
- Rpc_entrypoint &context_ep,
- Allocator &md_alloc,
+ Pd_session_component(Rpc_entrypoint &ep,
+ Resources resources,
+ Label const &label,
+ Diag diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
Pager_entrypoint &pager_ep,
char const *args)
:
- _label(args),
- _md_alloc(&md_alloc, _ram_quota(args)),
- _pd(&_md_alloc, _label.string),
- _thread_ep(thread_ep), _pager_ep(pager_ep),
- _signal_broker(_md_alloc, receiver_ep, context_ep),
- _rpc_cap_factory(_md_alloc),
+ Session_object(ep, resources, label, diag),
+ _constrained_md_ram_alloc(ram_alloc, *this, *this),
+ _sliced_heap(_constrained_md_ram_alloc, local_rm),
+ _ep(ep), _pager_ep(pager_ep),
+ _rpc_cap_factory(_sliced_heap),
_native_pd(*this, args),
- _address_space(thread_ep, _md_alloc, pager_ep,
+ _address_space(ep, _sliced_heap, pager_ep,
platform()->vm_start(), platform()->vm_size()),
- _stack_area(thread_ep, _md_alloc, pager_ep, 0, stack_area_virtual_size()),
- _linker_area(thread_ep, _md_alloc, pager_ep, 0, LINKER_AREA_SIZE)
+ _stack_area (_ep, _sliced_heap, pager_ep, 0, stack_area_virtual_size()),
+ _linker_area(_ep, _sliced_heap, pager_ep, 0, LINKER_AREA_SIZE)
{ }
/**
- * Register quota donation at allocator guard
+ * Initialize cap account without providing a reference account
+ *
+ * This method is solely used to set up the initial PD session within
+ * core. The cap accounts of regular PD session are initialized via
+ * 'ref_account'.
*/
- void upgrade_ram_quota(size_t ram_quota);
+ void init_cap_account() { _cap_account.construct(*this, _label); }
+
+ /**
+ * Session_object interface
+ */
+ void session_quota_upgraded() override;
/**
* Associate thread with PD
@@ -135,8 +160,6 @@ class Genode::Pd_session_component : public Rpc_object
return _address_space;
}
- Session_label label() { return Session_label(_label.string); }
-
/**************************
** PD session interface **
@@ -147,42 +170,62 @@ class Genode::Pd_session_component : public Rpc_object
Signal_source_capability alloc_signal_source() override
{
- try {
- return _signal_broker.alloc_signal_source(); }
+ _consume_cap(SIG_SOURCE_CAP);
+ try { return _signal_broker.alloc_signal_source(); }
catch (Genode::Allocator::Out_of_memory) {
- throw Pd_session::Out_of_metadata(); }
+ _released_cap_silent();
+ throw Out_of_ram();
+ }
}
- void free_signal_source(Signal_source_capability sig_rec_cap) override {
- _signal_broker.free_signal_source(sig_rec_cap); }
+ void free_signal_source(Signal_source_capability sig_rec_cap) override
+ {
+ _signal_broker.free_signal_source(sig_rec_cap);
+ _released_cap(SIG_SOURCE_CAP);
+ }
Signal_context_capability
alloc_context(Signal_source_capability sig_rec_cap, unsigned long imprint) override
{
+ Cap_quota_guard::Reservation cap_costs(*this, Cap_quota{1});
try {
- return _signal_broker.alloc_context(sig_rec_cap, imprint); }
+ Signal_context_capability cap =
+ _signal_broker.alloc_context(sig_rec_cap, imprint);
+
+ cap_costs.acknowledge();
+ diag("consumed signal-context cap (", _cap_account, ")");
+ return cap;
+ }
catch (Genode::Allocator::Out_of_memory) {
- throw Pd_session::Out_of_metadata(); }
+ throw Out_of_ram(); }
catch (Signal_broker::Invalid_signal_source) {
throw Pd_session::Invalid_signal_source(); }
}
- void free_context(Signal_context_capability cap) override {
- _signal_broker.free_context(cap); }
+ void free_context(Signal_context_capability cap) override
+ {
+ _signal_broker.free_context(cap);
+ _released_cap(SIG_CONTEXT_CAP);
+ }
void submit(Signal_context_capability cap, unsigned n) override {
_signal_broker.submit(cap, n); }
+ /*
+ * \throw Out_of_caps by '_consume_cap'
+ * \throw Out_of_ram by '_rpc_cap_factory.alloc'
+ */
Native_capability alloc_rpc_cap(Native_capability ep) override
{
- try {
- return _rpc_cap_factory.alloc(ep); }
- catch (Genode::Allocator::Out_of_memory) {
- throw Pd_session::Out_of_metadata(); }
+ _consume_cap(RPC_CAP);
+ return _rpc_cap_factory.alloc(ep);
}
- void free_rpc_cap(Native_capability cap) override {
- _rpc_cap_factory.free(cap); }
+ void free_rpc_cap(Native_capability cap) override
+ {
+ _rpc_cap_factory.free(cap);
+ _released_cap(RPC_CAP);
+ }
Capability address_space() {
return _address_space.cap(); }
@@ -193,6 +236,65 @@ class Genode::Pd_session_component : public Rpc_object
Capability linker_area() {
return _linker_area.cap(); }
+ void ref_account(Capability pd_cap) override
+ {
+ /* the reference account can be defined only once */
+ if (_cap_account.constructed())
+ return;
+
+ if (this->cap() == pd_cap)
+ return;
+
+ _ep.apply(pd_cap, [&] (Pd_session_component *pd) {
+
+ if (!pd || !pd->_cap_account.constructed()) {
+ error("invalid PD session specified as ref account");
+ throw Invalid_session();
+ }
+
+ _cap_account.construct(*this, _label, *pd->_cap_account);
+ });
+ }
+
+ void transfer_quota(Capability pd_cap, Cap_quota amount) override
+ {
+ /* the reference account can be defined only once */
+ if (!_cap_account.constructed())
+ throw Undefined_ref_account();
+
+ if (this->cap() == pd_cap)
+ return;
+
+ _ep.apply(pd_cap, [&] (Pd_session_component *pd) {
+
+ if (!pd || !pd->_cap_account.constructed())
+ throw Invalid_session();
+
+ try {
+ _cap_account->transfer_quota(*pd->_cap_account, amount);
+ diag("transferred ", amount, " caps "
+ "to '", pd->_cap_account->label(), "' (", _cap_account, ")");
+ }
+ catch (Account::Unrelated_account) {
+ warning("attempt to transfer cap quota to unrelated PD session");
+ throw Invalid_session(); }
+ catch (Account::Limit_exceeded) {
+ warning("cap limit (", *_cap_account, ") exceeded "
+ "during transfer_quota(", amount, ")");
+ throw Out_of_caps(); }
+ });
+ }
+
+ Cap_quota cap_quota() const
+ {
+ return _cap_account.constructed() ? _cap_account->limit() : Cap_quota { 0 };
+ }
+
+ Cap_quota used_caps() const
+ {
+ return _cap_account.constructed() ? _cap_account->used() : Cap_quota { 0 };
+ }
+
Capability native_pd() { return _native_pd.cap(); }
};
diff --git a/repos/base/src/core/include/trace/subject_registry.h b/repos/base/src/core/include/trace/subject_registry.h
index 4ea2f0f80..2b636e9b8 100644
--- a/repos/base/src/core/include/trace/subject_registry.h
+++ b/repos/base/src/core/include/trace/subject_registry.h
@@ -387,7 +387,7 @@ class Genode::Trace::Subject_registry
}
/**
- * \throw Ram_session::Quota_exceeded
+ * \throw Out_of_ram
*/
void import_new_sources(Source_registry &sources)
{
diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc
index 7d01cba58..bf43cb637 100644
--- a/repos/base/src/core/main.cc
+++ b/repos/base/src/core/main.cc
@@ -125,12 +125,16 @@ class Core_child : public Child_policy
Registry &_services;
+ Capability _core_pd_cap;
+ Pd_session &_core_pd;
+
Capability _core_ram_cap;
Ram_session &_core_ram;
Capability _core_cpu_cap;
Cpu_session &_core_cpu;
+ Cap_quota const _cap_quota;
Ram_quota const _ram_quota;
Child _child;
@@ -141,14 +145,17 @@ class Core_child : public Child_policy
* Constructor
*/
Core_child(Registry &services,
+ Pd_session &core_pd, Capability core_pd_cap,
Ram_session &core_ram, Capability core_ram_cap,
Cpu_session &core_cpu, Capability core_cpu_cap,
- Ram_quota ram_quota)
+ Cap_quota cap_quota, Ram_quota ram_quota)
:
_entrypoint(nullptr, STACK_SIZE, "init_child", false),
_services(services),
+ _core_pd_cap (core_pd_cap), _core_pd (core_pd),
_core_ram_cap(core_ram_cap), _core_ram(core_ram),
_core_cpu_cap(core_cpu_cap), _core_cpu(core_cpu),
+ _cap_quota(Child::effective_quota(cap_quota)),
_ram_quota(Child::effective_quota(ram_quota)),
_child(*env_deprecated()->rm_session(), _entrypoint, *this)
{
@@ -176,6 +183,12 @@ class Core_child : public Child_policy
return *service;
}
+ void init(Pd_session &session, Capability cap) override
+ {
+ session.ref_account(_core_pd_cap);
+ _core_pd.transfer_quota(cap, _cap_quota);
+ }
+
void init(Ram_session &session, Capability cap) override
{
session.ref_account(_core_ram_cap);
@@ -188,6 +201,9 @@ class Core_child : public Child_policy
_core_cpu.transfer_quota(cap, Cpu_session::quota_lim_upscale(100, 100));
}
+ Pd_session &ref_pd() { return _core_pd; }
+ Pd_session_capability ref_pd_cap() const { return _core_pd_cap; }
+
Ram_session &ref_ram() { return _core_ram; }
Ram_session_capability ref_ram_cap() const { return _core_ram_cap; }
@@ -271,7 +287,7 @@ int main()
static Rm_root rm_root (e, &sliced_heap, pager_ep);
static Cpu_root cpu_root (e, e, &pager_ep, &sliced_heap,
Trace::sources());
- static Pd_root pd_root (e, e, pager_ep, &sliced_heap);
+ static Pd_root pd_root (*e, pager_ep, core_ram_alloc, local_rm, sliced_heap);
static Log_root log_root (e, &sliced_heap);
static Io_mem_root io_mem_root (e, e, platform()->io_mem_alloc(),
platform()->ram_alloc(), &sliced_heap);
@@ -292,7 +308,27 @@ int main()
/* make platform-specific services known to service pool */
platform_add_local_services(e, &sliced_heap, &services);
- /* create CPU session representing core */
+ /* calculate number of capabilities to be assigned to init */
+ size_t const preservered_cap_quota = 1000;
+
+ if (platform()->max_caps() < preservered_cap_quota) {
+ error("platform cap limit lower than preservation for core");
+ return -1;
+ }
+
+ size_t const avail_cap_quota = platform()->max_caps() - preservered_cap_quota;
+
+ /* PD session representing core */
+ static Pd_session_component
+ core_pd(*e,
+ Session::Resources { Ram_quota { 16*1024 },
+ Cap_quota { avail_cap_quota } },
+ Session::Label("core"), Session::Diag{false},
+ core_ram_alloc, local_rm, pager_ep, "");
+
+ core_pd.init_cap_account();
+
+ /* CPU session representing core */
static Cpu_session_component
core_cpu(e, e, &pager_ep, &sliced_heap, Trace::sources(),
"label=\"core\"", Affinity(), Cpu_session::QUOTA_LIMIT);
@@ -309,14 +345,15 @@ int main()
size_t const avail_ram_quota = platform_ram_limit - preserved_ram_quota;
- log("", avail_ram_quota / (1024*1024), " MiB RAM "
+ log("", avail_ram_quota / (1024*1024), " MiB RAM and ", avail_cap_quota, " caps "
"assigned to init");
static Reconstructible
init(services,
+ core_pd, core_pd.cap(),
*env_deprecated()->ram_session(), env_deprecated()->ram_session_cap(),
core_cpu, core_cpu_cap,
- Ram_quota{avail_ram_quota});
+ core_pd.cap_quota(), Ram_quota{avail_ram_quota});
platform()->wait_for_exit();
diff --git a/repos/base/src/core/pd_upgrade_ram_quota.cc b/repos/base/src/core/pd_upgrade_ram_quota.cc
index 681dfe6c0..456303f93 100644
--- a/repos/base/src/core/pd_upgrade_ram_quota.cc
+++ b/repos/base/src/core/pd_upgrade_ram_quota.cc
@@ -17,8 +17,5 @@
using namespace Genode;
-void Pd_session_component::upgrade_ram_quota(size_t ram_quota)
-{
- _md_alloc.upgrade(ram_quota);
-}
+void Pd_session_component::session_quota_upgraded() { }
diff --git a/repos/base/src/core/ram_session_component.cc b/repos/base/src/core/ram_session_component.cc
index ae8024773..7ab1191c8 100644
--- a/repos/base/src/core/ram_session_component.cc
+++ b/repos/base/src/core/ram_session_component.cc
@@ -60,8 +60,10 @@ void Ram_session_component::_free_ds(Dataspace_capability ds_cap)
});
/* call dataspace destructors and free memory */
- if (ds)
+ if (ds) {
destroy(*_ds_slab, ds);
+ Cap_quota_guard::replenish(Cap_quota{1});
+ }
}
@@ -92,6 +94,11 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr
Ram_quota_guard::Reservation sbs_ram_costs(*this, Ram_quota{SBS});
}
+ /*
+ * Each dataspace is an RPC object and thereby consumes a capability.
+ */
+ Cap_quota_guard::Reservation dataspace_cap_costs(*this, Cap_quota{1});
+
/*
* Allocate physical backing store
*
@@ -191,6 +198,7 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attr
Dataspace_capability result = _ep.manage(ds);
dataspace_ram_costs.acknowledge();
+ dataspace_cap_costs.acknowledge();
phys_alloc_guard.ack = true;
return static_cap_cast(result);
diff --git a/repos/base/src/core/spec/x86/io_port_session_component.cc b/repos/base/src/core/spec/x86/io_port_session_component.cc
index 22ad51131..c807d8993 100644
--- a/repos/base/src/core/spec/x86/io_port_session_component.cc
+++ b/repos/base/src/core/spec/x86/io_port_session_component.cc
@@ -43,11 +43,6 @@ Io_port_session_component::Io_port_session_component(Range_allocator *io_port_al
case Range_allocator::Alloc_return::OUT_OF_METADATA:
error("I/O port allocator ran out of meta data");
-
- /*
- * Do not throw 'Quota_exceeded' because the client cannot do
- * anything about the meta data allocator of I/O ports.
- */
throw Root::Invalid_args();
case Range_allocator::Alloc_return::OK: break;
diff --git a/repos/base/src/include/base/internal/expanding_ram_session_client.h b/repos/base/src/include/base/internal/expanding_ram_session_client.h
index 979d8216e..dbd39aa6e 100644
--- a/repos/base/src/include/base/internal/expanding_ram_session_client.h
+++ b/repos/base/src/include/base/internal/expanding_ram_session_client.h
@@ -31,8 +31,17 @@ struct Genode::Expanding_ram_session_client : Upgradeable_clientparent();
parent.resource_request(String<128>("ram_quota=", amount).string());
}
+
+ void _request_caps_from_parent(size_t amount)
+ {
+ Parent &parent = *env_deprecated()->parent();
+ parent.resource_request(String<128>("cap_quota=", amount).string());
+ }
+
Expanding_ram_session_client(Ram_session_capability cap, Parent::Client::Id id)
- : Upgradeable_client(cap, id) { }
+ :
+ Upgradeable_client(cap, id)
+ { }
Ram_dataspace_capability alloc(size_t size, Cache_attribute cached = UNCACHED) override
{
@@ -41,8 +50,20 @@ struct Genode::Expanding_ram_session_client : Upgradeable_client(
- [&] () { return Ram_session_client::alloc(size, cached); },
+ [&] () {
+ return retry(
+ [&] () { return Ram_session_client::alloc(size, cached); },
+ [&] () {
+ try { upgrade_caps(UPGRADE_CAPS); }
+ catch (Out_of_caps) {
+ warning("cap quota exhausted, issuing resource request to parent");
+ _request_caps_from_parent(UPGRADE_CAPS);
+ }
+ },
+ NUM_ATTEMPTS);
+ },
[&] () {
/*
* The RAM service withdraws the meta data for the allocator
diff --git a/repos/base/src/include/base/internal/platform_env.h b/repos/base/src/include/base/internal/platform_env.h
index f16023746..f8c30b2e2 100644
--- a/repos/base/src/include/base/internal/platform_env.h
+++ b/repos/base/src/include/base/internal/platform_env.h
@@ -115,8 +115,8 @@ class Genode::Platform_env : public Env_deprecated,
** Emergency_ram_reserve interface **
*************************************/
- void release() {
-
+ void release()
+ {
log("used before freeing emergency=", _resources.ram.used_ram());
_resources.ram.free(_emergency_ram_ds);
log("used after freeing emergency=", _resources.ram.used_ram());
diff --git a/repos/base/src/include/base/internal/upgradeable_client.h b/repos/base/src/include/base/internal/upgradeable_client.h
index 70d7f4ef9..3666d7ea9 100644
--- a/repos/base/src/include/base/internal/upgradeable_client.h
+++ b/repos/base/src/include/base/internal/upgradeable_client.h
@@ -35,10 +35,12 @@ struct Genode::Upgradeable_client : CLIENT
void upgrade_ram(size_t quota)
{
- char buf[128];
- snprintf(buf, sizeof(buf), "ram_quota=%lu", quota);
+ env_deprecated()->parent()->upgrade(_id, String<64>("ram_quota=", quota).string());
+ }
- env_deprecated()->parent()->upgrade(_id, buf);
+ void upgrade_caps(size_t quota)
+ {
+ env_deprecated()->parent()->upgrade(_id, String<64>("cap_quota=", quota).string());
}
};
diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc
index 2b2e69490..5db391e00 100644
--- a/repos/base/src/lib/base/child.cc
+++ b/repos/base/src/lib/base/child.cc
@@ -75,6 +75,7 @@ void Child::session_sigh(Signal_context_capability sigh)
if (session.phase == Session_state::AVAILABLE ||
session.phase == Session_state::INSUFFICIENT_RAM_QUOTA ||
+ session.phase == Session_state::INSUFFICIENT_CAP_QUOTA ||
session.phase == Session_state::INVALID_ARGS) {
if (sigh.valid() && session.async_client_notify)
@@ -88,6 +89,7 @@ void Child::session_sigh(Signal_context_capability sigh)
* Create session-state object for a dynamically created session
*
* \throw Out_of_ram
+ * \throw Insufficient_cap_quota
* \throw Insufficient_ram_quota
* \throw Parent::Service_denied
*/
@@ -104,6 +106,11 @@ create_session(Child_policy::Name const &child_name, Service &service,
catch (Insufficient_ram_quota) {
error(child_name, " requested session with insufficient RAM quota");
throw; }
+
+ catch (Insufficient_cap_quota) {
+ error(child_name, " requested session with insufficient cap quota");
+ throw; }
+
catch (Allocator::Out_of_memory) {
error(child_name, " session meta data could not be allocated");
throw Out_of_ram(); }
@@ -170,6 +177,7 @@ Session_capability Child::session(Parent::Client::Id id,
/* filter session affinity */
Affinity const filtered_affinity = _policy.filter_session_affinity(affinity);
+ Cap_quota const cap_quota = cap_quota_from_args(argbuf);
Ram_quota const ram_quota = ram_quota_from_args(argbuf);
/* portion of quota to keep for ourself to maintain the session meta data */
@@ -202,13 +210,18 @@ Session_capability Child::session(Parent::Client::Id id,
try {
Ram_transfer::Remote_account ref_ram_account { _policy.ref_ram(), _policy.ref_ram_cap() };
+ Cap_transfer::Remote_account ref_cap_account { _policy.ref_pd(), _policy.ref_pd_cap() };
+
Ram_transfer::Remote_account ram_account { ram(), ram_session_cap() };
+ Cap_transfer::Remote_account cap_account { pd(), pd_session_cap() };
/* transfer the quota donation from the child's account to ourself */
Ram_transfer ram_donation_from_child(ram_quota, ram_account, ref_ram_account);
+ Cap_transfer cap_donation_from_child(cap_quota, cap_account, ref_cap_account);
/* transfer session quota from ourself to the service provider */
Ram_transfer ram_donation_to_service(forward_ram_quota, ref_ram_account, service);
+ Cap_transfer cap_donation_to_service(cap_quota, ref_cap_account, service);
/* try to dispatch session request synchronously */
service.initiate_request(session);
@@ -223,9 +236,16 @@ Session_capability Child::session(Parent::Client::Id id,
throw Insufficient_ram_quota();
}
+ if (session.phase == Session_state::INSUFFICIENT_CAP_QUOTA) {
+ _revert_quota_and_destroy(session);
+ throw Insufficient_cap_quota();
+ }
+
/* finish transaction */
ram_donation_from_child.acknowledge();
+ cap_donation_from_child.acknowledge();
ram_donation_to_service.acknowledge();
+ cap_donation_to_service.acknowledge();
}
/*
* Release session meta data if one of the quota transfers went wrong.
@@ -234,6 +254,10 @@ Session_capability Child::session(Parent::Client::Id id,
session.destroy();
throw Out_of_ram();
}
+ catch (Cap_transfer::Quota_exceeded) {
+ session.destroy();
+ throw Out_of_caps();
+ }
/*
* Copy out the session cap before we are potentially kicking off the
@@ -261,7 +285,8 @@ Session_capability Child::session_cap(Client::Id id)
auto lamda = [&] (Session_state &session) {
if (session.phase == Session_state::INVALID_ARGS
- || session.phase == Session_state::INSUFFICIENT_RAM_QUOTA) {
+ || session.phase == Session_state::INSUFFICIENT_RAM_QUOTA
+ || session.phase == Session_state::INSUFFICIENT_CAP_QUOTA) {
Session_state::Phase const phase = session.phase;
@@ -275,6 +300,7 @@ Session_capability Child::session_cap(Client::Id id)
switch (phase) {
case Session_state::INVALID_ARGS: throw Parent::Service_denied();
case Session_state::INSUFFICIENT_RAM_QUOTA: throw Insufficient_ram_quota();
+ case Session_state::INSUFFICIENT_CAP_QUOTA: throw Insufficient_cap_quota();
default: break;
}
}
@@ -318,29 +344,43 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const
Ram_quota const ram_quota {
Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0) };
+ Cap_quota const cap_quota {
+ Arg_string::find_arg(args.string(), "cap_quota").ulong_value(0) };
+
try {
Ram_transfer::Remote_account ref_ram_account { _policy.ref_ram(), _policy.ref_ram_cap() };
+ Cap_transfer::Remote_account ref_cap_account { _policy.ref_pd(), _policy.ref_pd_cap() };
+
Ram_transfer::Remote_account ram_account { ram(), ram_session_cap() };
+ Cap_transfer::Remote_account cap_account { pd(), pd_session_cap() };
/* transfer quota from client to ourself */
Ram_transfer ram_donation_from_child(ram_quota, ram_account, ref_ram_account);
+ Cap_transfer cap_donation_from_child(cap_quota, cap_account, ref_cap_account);
/* transfer session quota from ourself to the service provider */
Ram_transfer ram_donation_to_service(ram_quota, ref_ram_account, session.service());
+ Cap_transfer cap_donation_to_service(cap_quota, ref_cap_account, session.service());
- session.increase_donated_quota(ram_quota);
+ session.increase_donated_quota(ram_quota, cap_quota);
session.phase = Session_state::UPGRADE_REQUESTED;
session.service().initiate_request(session);
/* finish transaction */
ram_donation_from_child.acknowledge();
+ cap_donation_from_child.acknowledge();
ram_donation_to_service.acknowledge();
+ cap_donation_to_service.acknowledge();
}
catch (Ram_transfer::Quota_exceeded) {
warning(_policy.name(), ": RAM upgrade of ", session.service().name(), " failed");
throw Out_of_ram();
}
+ catch (Cap_transfer::Quota_exceeded) {
+ warning(_policy.name(), ": cap upgrade of ", session.service().name(), " failed");
+ throw Out_of_caps();
+ }
if (session.phase == Session_state::CAP_HANDED_OUT) {
result = UPGRADE_DONE;
@@ -361,11 +401,18 @@ void Child::_revert_quota_and_destroy(Session_state &session)
Ram_transfer::Account &service_ram_account = session.service();
Ram_transfer::Remote_account child_ram_account(ram(), ram_session_cap());
+ Cap_transfer::Remote_account ref_cap_account(_policy.ref_pd(), _policy.ref_pd_cap());
+ Cap_transfer::Account &service_cap_account = session.service();
+ Cap_transfer::Remote_account child_cap_account(pd(), pd_session_cap());
+
try {
/* transfer session quota from the service to ourself */
Ram_transfer ram_donation_from_service(session.donated_ram_quota(),
service_ram_account, ref_ram_account);
+ Cap_transfer cap_donation_from_service(session.donated_cap_quota(),
+ service_cap_account, ref_cap_account);
+
/*
* Transfer session quota from ourself to the client (our child). In
* addition to the quota returned from the server, we also return the
@@ -377,9 +424,14 @@ void Child::_revert_quota_and_destroy(Session_state &session)
Ram_transfer ram_donation_to_client(returned_ram,
ref_ram_account, child_ram_account);
+ Cap_transfer cap_donation_to_client(session.donated_cap_quota(),
+ ref_cap_account, child_cap_account);
+
/* finish transaction */
ram_donation_from_service.acknowledge();
+ cap_donation_from_service.acknowledge();
ram_donation_to_client.acknowledge();
+ cap_donation_to_client.acknowledge();
}
catch (Ram_transfer::Quota_exceeded) {
warning(_policy.name(), ": could not revert session RAM quota (", session, ")"); }
@@ -398,7 +450,8 @@ Child::Close_result Child::_close(Session_state &session)
* without involving the server
*/
if (session.phase == Session_state::INVALID_ARGS
- || session.phase == Session_state::INSUFFICIENT_RAM_QUOTA) {
+ || session.phase == Session_state::INSUFFICIENT_RAM_QUOTA
+ || session.phase == Session_state::INSUFFICIENT_CAP_QUOTA) {
_revert_quota_and_destroy(session);
return CLOSE_DONE;
}
@@ -503,6 +556,12 @@ void Child::session_response(Server::Id id, Session_response response)
session.ready_callback->session_ready(session);
break;
+ case Parent::INSUFFICIENT_CAP_QUOTA:
+ session.phase = Session_state::INSUFFICIENT_CAP_QUOTA;
+ if (session.ready_callback)
+ session.ready_callback->session_ready(session);
+ break;
+
case Parent::SESSION_OK:
if (session.phase == Session_state::UPGRADE_REQUESTED) {
session.phase = Session_state::CAP_HANDED_OUT;
@@ -649,6 +708,7 @@ void Child::_try_construct_env_dependent_members()
_parent_cap);
}
catch (Out_of_ram) { _error("out of RAM during ELF loading"); }
+ catch (Out_of_caps) { _error("out of caps during ELF loading"); }
catch (Cpu_session::Thread_creation_failed) { _error("unable to create initial thread"); }
catch (Cpu_session::Out_of_metadata) { _error("CPU session quota exhausted"); }
catch (Process::Missing_dynamic_linker) { _error("dynamic linker unavailable"); }
diff --git a/repos/base/src/lib/base/component.cc b/repos/base/src/lib/base/component.cc
index ad27ca5c7..3c01aae62 100644
--- a/repos/base/src/lib/base/component.cc
+++ b/repos/base/src/lib/base/component.cc
@@ -123,24 +123,27 @@ namespace {
* the route between client and server, the session quota provided
* by the client may become successively diminished by intermediate
* components, prompting the server to deny the session request.
- *
- * If the session creation failed due to insufficient session
- * quota, we try to repeatedly increase the quota up to
- * 'NUM_ATTEMPTS'.
*/
- enum { NUM_ATTEMPTS = 10 };
/* extract session quota as specified by the 'Connection' */
char argbuf[Parent::Session_args::MAX_SIZE];
strncpy(argbuf, args.string(), sizeof(argbuf));
- Ram_quota ram_quota = ram_quota_from_args(argbuf);
- return retry(
- [&] () {
+ Ram_quota ram_quota = ram_quota_from_args(argbuf);
+ Cap_quota cap_quota = cap_quota_from_args(argbuf);
+
+ unsigned warn_after_attempts = 2;
+
+ for (unsigned cnt = 0;; cnt++) {
+
+ try {
Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota",
String<32>(ram_quota).string());
+ Arg_string::set_arg(argbuf, sizeof(argbuf), "cap_quota",
+ String<32>(cap_quota).string());
+
Session_capability cap =
_parent.session(id, name, Parent::Session_args(argbuf), affinity);
@@ -149,30 +152,34 @@ namespace {
_block_for_session();
return _parent.session_cap(id);
- },
- [&] () {
- /*
- * If our RAM session has less quota available than the
- * session quota, the session-quota transfer failed. In
- * this case, we try to recover by issuing a resource
- * request to the parent.
- *
- * Otherwise, the session-quota transfer succeeded but
- * the request was denied by the server.
- */
+ }
+
+ catch (Insufficient_ram_quota) {
+ ram_quota = Ram_quota { ram_quota.value + 4096 }; }
+
+ catch (Insufficient_cap_quota) {
+ cap_quota = Cap_quota { cap_quota.value + 4 }; }
+
+ catch (Out_of_ram) {
if (ram_quota.value > ram().avail_ram().value) {
Parent::Resource_args args(String<64>("ram_quota=", ram_quota));
_parent.resource_request(args);
- } else {
- ram_quota = Ram_quota { ram_quota.value + 4096 };
}
- },
- NUM_ATTEMPTS);
+ }
- warning("giving up to increase session quota for ", name.string(), " session "
- "after ", (int)NUM_ATTEMPTS, " attempts");
+ catch (Out_of_caps) {
+ if (cap_quota.value > pd().avail_caps().value) {
+ Parent::Resource_args args(String<64>("cap_quota=", cap_quota));
+ _parent.resource_request(args);
+ }
+ }
- throw Insufficient_ram_quota();
+ if (cnt == warn_after_attempts) {
+ warning("re-attempted ", name.string(), " session request ",
+ cnt, " times (args: ", Cstring(argbuf), ")");
+ warn_after_attempts *= 2;
+ }
+ }
}
void upgrade(Parent::Client::Id id, Parent::Upgrade_args const &args) override
diff --git a/repos/base/src/lib/base/root_proxy.cc b/repos/base/src/lib/base/root_proxy.cc
index da052e968..cba0c442a 100644
--- a/repos/base/src/lib/base/root_proxy.cc
+++ b/repos/base/src/lib/base/root_proxy.cc
@@ -187,6 +187,8 @@ void Root_proxy::_handle_session_request(Xml_node request)
_env.parent().session_response(id, Parent::INVALID_ARGS); }
catch (Insufficient_ram_quota) {
_env.parent().session_response(id, Parent::INSUFFICIENT_RAM_QUOTA); }
+ catch (Insufficient_cap_quota) {
+ _env.parent().session_response(id, Parent::INSUFFICIENT_CAP_QUOTA); }
catch (Root::Unavailable) {
_env.parent().session_response(id, Parent::INVALID_ARGS); }
}
@@ -196,8 +198,9 @@ void Root_proxy::_handle_session_request(Xml_node request)
_id_space.apply(id, [&] (Session &session) {
Ram_quota const ram_quota { request.attribute_value("ram_quota", 0UL) };
+ Cap_quota const cap_quota { request.attribute_value("cap_quota", 0UL) };
- String<80> const args("ram_quota=", ram_quota);
+ String<80> const args("ram_quota=", ram_quota, ", cap_quota=", cap_quota);
Root_client(session.service.root).upgrade(session.cap, args.string());
diff --git a/repos/base/src/lib/base/rpc_cap_alloc.cc b/repos/base/src/lib/base/rpc_cap_alloc.cc
index c63a6447e..e1cc305c5 100644
--- a/repos/base/src/lib/base/rpc_cap_alloc.cc
+++ b/repos/base/src/lib/base/rpc_cap_alloc.cc
@@ -23,13 +23,19 @@ using namespace Genode;
Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session &pd,
Native_capability ep, addr_t)
{
- Untyped_capability new_obj_cap =
- retry(
- [&] () { return pd.alloc_rpc_cap(_cap); },
- [&] () { env_deprecated()->parent()->upgrade(Parent::Env::pd(),
- "ram_quota=16K"); });
+ for (;;) {
- return new_obj_cap;
+ 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 }; }
+
+ env_deprecated()->parent()->upgrade(Parent::Env::pd(),
+ String<100>("ram_quota=", ram_upgrade, ", "
+ "cap_quota=", cap_upgrade).string());
+ }
}
diff --git a/repos/base/src/lib/base/session_state.cc b/repos/base/src/lib/base/session_state.cc
index f5da491fb..8f3c3e70c 100644
--- a/repos/base/src/lib/base/session_state.cc
+++ b/repos/base/src/lib/base/session_state.cc
@@ -33,6 +33,7 @@ struct Formatted_phase
case State::CREATE_REQUESTED: print(output, "CREATE_REQUESTED"); break;
case State::INVALID_ARGS: print(output, "INVALID_ARGS"); break;
case State::INSUFFICIENT_RAM_QUOTA: print(output, "INSUFFICIENT_RAM_QUOTA"); break;
+ case State::INSUFFICIENT_CAP_QUOTA: print(output, "INSUFFICIENT_CAP_QUOTA"); break;
case State::AVAILABLE: print(output, "AVAILABLE"); break;
case State::CAP_HANDED_OUT: print(output, "CAP_HANDED_OUT"); break;
case State::UPGRADE_REQUESTED: print(output, "UPGRADE_REQUESTED"); break;
@@ -49,7 +50,7 @@ void Session_state::print(Output &out) const
print(out, "service=", _service.name(), " cid=", _id_at_client, " "
"args='", _args, "' state=", Formatted_phase(phase), " "
- "ram_quota=", _donated_ram_quota);
+ "ram_quota=", _donated_ram_quota, ", cap_quota=", _donated_cap_quota);
}
@@ -77,6 +78,7 @@ void Session_state::generate_session_request(Xml_generator &xml) const
xml.node("upgrade", [&] () {
xml.attribute("id", id_at_server->id().value);
xml.attribute("ram_quota", ram_upgrade.value);
+ xml.attribute("cap_quota", cap_upgrade.value);
});
break;
@@ -88,6 +90,7 @@ void Session_state::generate_session_request(Xml_generator &xml) const
case INVALID_ARGS:
case INSUFFICIENT_RAM_QUOTA:
+ case INSUFFICIENT_CAP_QUOTA:
case AVAILABLE:
case CAP_HANDED_OUT:
case CLOSED:
@@ -102,6 +105,7 @@ void Session_state::generate_client_side_info(Xml_generator &xml, Detail detail)
xml.attribute("label", _label);
xml.attribute("state", String<32>(Formatted_phase(phase)));
xml.attribute("ram", String<32>(_donated_ram_quota));
+ xml.attribute("caps", String<32>(_donated_cap_quota));
if (detail.args == Detail::ARGS)
xml.node("args", [&] () { xml.append_sanitized(_args.string()); });
@@ -161,6 +165,7 @@ Session_state::Session_state(Service &service,
:
_service(service),
_donated_ram_quota(ram_quota_from_args(args.string())),
+ _donated_cap_quota(cap_quota_from_args(args.string())),
_id_at_client(*this, client_id_space, client_id),
_label(label), _args(args), _affinity(affinity)
{ }
diff --git a/repos/base/src/lib/base/signal.cc b/repos/base/src/lib/base/signal.cc
index ab7303b85..a6b554fc7 100644
--- a/repos/base/src/lib/base/signal.cc
+++ b/repos/base/src/lib/base/signal.cc
@@ -229,21 +229,26 @@ Signal_context_capability Signal_receiver::manage(Signal_context *context)
/* register context at process-wide registry */
signal_context_registry()->insert(&context->_registry_le);
- retry(
- [&] () {
+ for (;;) {
+
+ Ram_quota ram_upgrade { 0 };
+ Cap_quota cap_upgrade { 0 };
+
+ try {
/* use signal context as imprint */
context->_cap = env_deprecated()->pd_session()->alloc_context(_cap, (long)context);
- },
- [&] () {
- size_t const quota = 1024*sizeof(long);
- char buf[64];
- snprintf(buf, sizeof(buf), "ram_quota=%ld", quota);
-
- log("upgrading quota donation for PD session (", quota, " bytes)");
-
- env_deprecated()->parent()->upgrade(Parent::Env::pd(), buf);
+ break;
}
- );
+ catch (Out_of_ram) { ram_upgrade = Ram_quota { 1024*sizeof(long) }; }
+ catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
+
+ log("upgrading quota donation for PD session "
+ "(", ram_upgrade, " bytes, ", cap_upgrade, " caps)");
+
+ env_deprecated()->parent()->upgrade(Parent::Env::pd(),
+ String<100>("ram_quota=", ram_upgrade, ", "
+ "cap_quota=", cap_upgrade).string());
+ }
return context->_cap;
}
diff --git a/repos/base/src/lib/base/slab.cc b/repos/base/src/lib/base/slab.cc
index 39fa829a8..cbfea202a 100644
--- a/repos/base/src/lib/base/slab.cc
+++ b/repos/base/src/lib/base/slab.cc
@@ -319,7 +319,6 @@ void Slab::insert_sb(void *ptr)
bool Slab::alloc(size_t size, void **out_addr)
{
-
/* too large for us ? */
if (size > _slab_size) {
error("requested size ", size, " is larger then slab size ",
diff --git a/repos/base/src/test/rm_fault/main.cc b/repos/base/src/test/rm_fault/main.cc
index 6b5a693d2..0d3df446e 100644
--- a/repos/base/src/test/rm_fault/main.cc
+++ b/repos/base/src/test/rm_fault/main.cc
@@ -98,8 +98,10 @@ class Test_child_policy : public Child_policy
Binary_name binary_name() const override { return "test-rm_fault"; }
- Ram_session &ref_ram() override { return _env.ram(); }
+ Pd_session &ref_pd() override { return _env.pd(); }
+ Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
+ Ram_session &ref_ram() override { return _env.ram(); }
Ram_session_capability ref_ram_cap() const override { return _env.ram_session_cap(); }
void init(Ram_session &session, Ram_session_capability cap) override
@@ -111,6 +113,9 @@ class Test_child_policy : public Child_policy
void init(Pd_session &session, Pd_session_capability cap) override
{
+ session.ref_account(_env.pd_session_cap());
+ _env.pd().transfer_quota(cap, Cap_quota{20});
+
Region_map_client address_space(session.address_space());
address_space.fault_handler(_fault_handler_sigh);
}
diff --git a/repos/demo/include/launchpad/launchpad.h b/repos/demo/include/launchpad/launchpad.h
index 311ffbdb2..e540b3fdc 100644
--- a/repos/demo/include/launchpad/launchpad.h
+++ b/repos/demo/include/launchpad/launchpad.h
@@ -59,6 +59,7 @@ class Launchpad_child : public Genode::Child_policy,
Genode::Ram_session_capability _ref_ram_cap;
Genode::Ram_session_client _ref_ram { _ref_ram_cap };
+ Genode::Cap_quota const _cap_quota;
Genode::Ram_quota const _ram_quota;
Parent_services &_parent_services;
@@ -97,6 +98,7 @@ class Launchpad_child : public Genode::Child_policy,
Genode::Allocator &alloc,
Genode::Session_label const &label,
Binary_name const &elf_name,
+ Genode::Cap_quota cap_quota,
Genode::Ram_quota ram_quota,
Parent_services &parent_services,
Child_services &child_services,
@@ -105,6 +107,7 @@ class Launchpad_child : public Genode::Child_policy,
_name(label), _elf_name(elf_name),
_env(env), _alloc(alloc),
_ref_ram_cap(env.ram_session_cap()),
+ _cap_quota(Genode::Child::effective_quota(cap_quota)),
_ram_quota(Genode::Child::effective_quota(ram_quota)),
_parent_services(parent_services),
_child_services(child_services),
@@ -133,9 +136,19 @@ class Launchpad_child : public Genode::Child_policy,
Binary_name binary_name() const override { return _elf_name; }
+ Genode::Pd_session &ref_pd() override { return _env.pd(); }
+ Genode::Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
+
Genode::Ram_session &ref_ram() override { return _ref_ram; }
Genode::Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
+ void init(Genode::Pd_session &session,
+ Genode::Pd_session_capability cap) override
+ {
+ session.ref_account(_env.pd_session_cap());
+ _env.pd().transfer_quota(cap, _cap_quota);
+ }
+
void init(Genode::Ram_session &session,
Genode::Ram_session_capability cap) override
{
@@ -200,7 +213,8 @@ class Launchpad_child : public Genode::Child_policy,
Child_service(_child_services, service_name,
_session_requester.id_space(),
_child.session_factory(), *this,
- _child.ram_session_cap());
+ _child.ram_session_cap(),
+ _child.pd_session_cap());
}
};
@@ -233,6 +247,7 @@ class Launchpad
public:
+ typedef Genode::Cap_quota Cap_quota;
typedef Genode::Ram_quota Ram_quota;
Launchpad(Genode::Env &env, unsigned long initial_quota);
@@ -254,7 +269,7 @@ class Launchpad
virtual void quota(unsigned long quota) { }
virtual void add_launcher(Launchpad_child::Name const &binary_name,
- unsigned long default_quota,
+ Cap_quota caps, unsigned long default_quota,
Genode::Dataspace_capability config_ds) { }
virtual void add_child(Launchpad_child::Name const &,
@@ -266,7 +281,7 @@ class Launchpad
Genode::Allocator &) { }
Launchpad_child *start_child(Launchpad_child::Name const &binary_name,
- Ram_quota quota,
+ Cap_quota cap_quota, Ram_quota ram_quota,
Genode::Dataspace_capability config_ds);
/**
diff --git a/repos/demo/src/app/launchpad/launch_entry.h b/repos/demo/src/app/launchpad/launch_entry.h
index 81c50ec29..c71e42b9f 100644
--- a/repos/demo/src/app/launchpad/launch_entry.h
+++ b/repos/demo/src/app/launchpad/launch_entry.h
@@ -38,14 +38,15 @@ class Launch_entry : public Scout::Parent_element, public Loadbar_listener
/**
* Constructor
*/
- Launch_entry(Scout::Launcher::Name const &prg_name, unsigned long initial_quota,
+ Launch_entry(Scout::Launcher::Name const &prg_name,
+ unsigned long caps, unsigned long initial_quota,
unsigned long max_quota, Launchpad *launchpad,
Genode::Dataspace_capability config_ds)
:
_prg_name(prg_name),
_block(Scout::Block::RIGHT), _loadbar(this, &Scout::label_font),
_config(config_ds),
- _launcher(prg_name, launchpad, initial_quota * 1024UL, &_config)
+ _launcher(prg_name, launchpad, caps, initial_quota * 1024UL, &_config)
{
_block.append_launchertext(_prg_name.string(), &Scout::link_style, &_launcher);
diff --git a/repos/demo/src/app/launchpad/launcher.cc b/repos/demo/src/app/launchpad/launcher.cc
index 63fb5a312..786f247bd 100644
--- a/repos/demo/src/app/launchpad/launcher.cc
+++ b/repos/demo/src/app/launchpad/launcher.cc
@@ -21,6 +21,7 @@ using namespace Scout;
void Launcher::launch()
{
_launchpad->start_child(prg_name(),
+ Launchpad::Cap_quota{caps()},
Launchpad::Ram_quota{quota()},
_config ? _config->config_ds()
: Genode::Dataspace_capability());
diff --git a/repos/demo/src/app/launchpad/launchpad_window.h b/repos/demo/src/app/launchpad/launchpad_window.h
index 41cad81dd..ca5e02924 100644
--- a/repos/demo/src/app/launchpad/launchpad_window.h
+++ b/repos/demo/src/app/launchpad/launchpad_window.h
@@ -127,12 +127,12 @@ class Launchpad_window : public Scout::Scrollbar_listener,
_status_entry.refresh();
}
- void add_launcher(Launchpad_child::Name const &name,
+ void add_launcher(Launchpad_child::Name const &name, Cap_quota caps,
unsigned long default_quota,
Genode::Dataspace_capability config_ds = Genode::Dataspace_capability()) override
{
Launch_entry *le;
- le = new Launch_entry(name, default_quota / 1024,
+ le = new Launch_entry(name, caps.value, default_quota / 1024,
initial_quota() / 1024,
this, config_ds);
_launch_section.append(le);
diff --git a/repos/demo/src/app/scout/doc.cc b/repos/demo/src/app/scout/doc.cc
index 27843242e..7d5c481eb 100644
--- a/repos/demo/src/app/scout/doc.cc
+++ b/repos/demo/src/app/scout/doc.cc
@@ -149,7 +149,7 @@ Document *create_document()
b0->append_plaintext("that can be started by clicking on the application's name. Before starting an", &plain_style);
b0->append_plaintext("application, the user can define the amount of memory quota to donate to the", &plain_style);
b0->append_plaintext("new application by adjusting the red bar using the mouse.", &plain_style);
- Launcher *l0 = new Launcher("launchpad", 1, 22*1024*1024);
+ Launcher *l0 = new Launcher("launchpad", 1, 100000, 22*1024*1024);
b0->append_launchertext("Start the launchpad by clicking on this link...", &link_style, l0);
chapter->append(b0);
diff --git a/repos/demo/src/app/scout/elements.h b/repos/demo/src/app/scout/elements.h
index 438cdb6a2..b31698d75 100644
--- a/repos/demo/src/app/scout/elements.h
+++ b/repos/demo/src/app/scout/elements.h
@@ -227,12 +227,13 @@ class Scout::Launcher : public Anchor
private:
- Name _prg_name;
- int _active;
- int _exec_once;
- Launchpad *_launchpad;
- unsigned long _quota;
- Launcher_config *_config;
+ Name _prg_name;
+ int _active;
+ int _exec_once;
+ Launchpad *_launchpad;
+ unsigned long const _caps;
+ unsigned long _quota;
+ Launcher_config *_config;
public:
@@ -242,22 +243,30 @@ class Scout::Launcher : public Anchor
* Constructors
*/
Launcher(Name const &prg_name, int exec_once = 0,
- unsigned long quota = 0, Launcher_config *config = 0) :
+ unsigned long caps = 0, unsigned long quota = 0,
+ Launcher_config *config = 0)
+ :
_prg_name(prg_name), _active(1),
- _exec_once(exec_once), _quota(quota), _config(config) { }
+ _exec_once(exec_once), _caps(caps), _quota(quota), _config(config)
+ { }
Launcher(Name const &prg_name, Launchpad *launchpad,
- unsigned long quota, Launcher_config *config = 0) :
- _prg_name(prg_name), _launchpad(launchpad), _quota(quota),
- _config(config) { }
+ unsigned long caps, unsigned long quota,
+ Launcher_config *config = 0)
+ :
+ _prg_name(prg_name), _launchpad(launchpad),
+ _caps(caps), _quota(quota), _config(config)
+ { }
- int active() { return _active; }
+ int active() const { return _active; }
- Name prg_name() { return _prg_name; }
+ Name prg_name() const { return _prg_name; }
void quota(unsigned long quota) { _quota = quota; }
- unsigned long quota() { return _quota; }
+ unsigned long quota() const { return _quota; }
+
+ unsigned long caps() const { return _caps; }
Launcher_config *config() { return _config; }
diff --git a/repos/demo/src/app/scout/launcher.cc b/repos/demo/src/app/scout/launcher.cc
index efc29bcea..9179c27b8 100644
--- a/repos/demo/src/app/scout/launcher.cc
+++ b/repos/demo/src/app/scout/launcher.cc
@@ -115,6 +115,7 @@ void Launcher::launch()
}
_launchpad_ptr->start_child(prg_name(),
+ Launchpad::Cap_quota{caps()},
Launchpad::Ram_quota{quota()},
config_registry.config(prg_name().string()));
}
diff --git a/repos/demo/src/lib/launchpad/launchpad.cc b/repos/demo/src/lib/launchpad/launchpad.cc
index da126050a..491ee2a80 100644
--- a/repos/demo/src/lib/launchpad/launchpad.cc
+++ b/repos/demo/src/lib/launchpad/launchpad.cc
@@ -106,6 +106,8 @@ void Launchpad::process_config(Genode::Xml_node config_node)
Number_of_bytes default_ram_quota =
node.attribute_value("ram_quota", Number_of_bytes(0));
+ Launchpad::Cap_quota const cap_quota { node.attribute_value("caps", 0UL) };
+
/*
* Obtain configuration for the child
*/
@@ -137,13 +139,13 @@ void Launchpad::process_config(Genode::Xml_node config_node)
}
/* add launchpad entry */
- add_launcher(*name, default_ram_quota, config_ds);
+ add_launcher(*name, cap_quota, default_ram_quota, config_ds);
});
}
Launchpad_child *Launchpad::start_child(Launchpad_child::Name const &binary_name,
- Ram_quota ram_quota,
+ Cap_quota cap_quota, Ram_quota ram_quota,
Dataspace_capability config_ds)
{
log("starting ", binary_name, " with quota ", ram_quota);
@@ -165,6 +167,17 @@ Launchpad_child *Launchpad::start_child(Launchpad_child::Name const &binary_name
ram_quota = Ram_quota { avail - preserved };
}
+ size_t const avail_caps = _env.pd().avail_caps().value;
+
+ if (cap_quota.value > avail_caps) {
+ warning("child's cap quota (", cap_quota.value, ") exceeds the "
+ "number of available capabilities (", avail_caps, ")");
+
+ size_t const preserved_caps = min(avail_caps, 25UL);
+
+ cap_quota = Cap_quota { avail_caps - preserved_caps };
+ }
+
size_t metadata_size = 4096*16 + sizeof(Launchpad_child);
if (metadata_size > ram_quota.value) {
@@ -176,7 +189,8 @@ Launchpad_child *Launchpad::start_child(Launchpad_child::Name const &binary_name
try {
Launchpad_child *c = new (&_sliced_heap)
- Launchpad_child(_env, _heap, unique_name, binary_name, ram_quota,
+ Launchpad_child(_env, _heap, unique_name, binary_name,
+ cap_quota, ram_quota,
_parent_services, _child_services, config_ds);
Lock::Guard lock_guard(_children_lock);
diff --git a/repos/gems/include/gems/report_rom_slave.h b/repos/gems/include/gems/report_rom_slave.h
index fb308e4b5..2b1331b32 100644
--- a/repos/gems/include/gems/report_rom_slave.h
+++ b/repos/gems/include/gems/report_rom_slave.h
@@ -45,16 +45,20 @@ class Report_rom_slave : public Genode::Noncopyable
static Name _name() { return "report_rom"; }
static Genode::Ram_quota _quota() { return { 1024*1024 }; }
+ static Genode::Cap_quota _caps() { return { 25 }; }
public:
Policy(Genode::Rpc_entrypoint &ep,
Genode::Region_map &rm,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Ram_session &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
const char *config)
:
Genode::Slave::Policy(_name(), _name(), *this, ep, rm,
+ ref_pd, ref_pd_cap, _caps(),
ref_ram, ref_ram_cap, _quota())
{
if (config)
@@ -76,14 +80,15 @@ class Report_rom_slave : public Genode::Noncopyable
* \param ram RAM session used to allocate the configuration
* dataspace
*/
- Report_rom_slave(Genode::Pd_session &pd,
- Genode::Region_map &rm,
+ Report_rom_slave(Genode::Region_map &rm,
+ Genode::Pd_session &pd,
+ Genode::Pd_session_capability pd_cap,
Genode::Ram_session &ram,
Genode::Ram_session_capability ram_cap,
char const *config)
:
_ep(&pd, _ep_stack_size, "report_rom"),
- _policy(_ep, rm, ram, ram_cap, config),
+ _policy(_ep, rm, pd, pd_cap, ram, ram_cap, config),
_child(rm, _ep, _policy)
{ }
diff --git a/repos/gems/src/app/launcher/fading_dialog.h b/repos/gems/src/app/launcher/fading_dialog.h
index da0c424c7..cf4d6ec3c 100644
--- a/repos/gems/src/app/launcher/fading_dialog.h
+++ b/repos/gems/src/app/launcher/fading_dialog.h
@@ -196,11 +196,10 @@ class Launcher::Fading_dialog : private Input_event_handler
_fader_slave_ep(&env.pd(), _fader_slave_ep_stack_size, "nit_fader"),
_nitpicker_connection(env, "menu"),
_nitpicker_session(env, _nitpicker_connection, env.ep(), _fader_slave_ep, *this),
- _nit_fader_slave(_fader_slave_ep, env.rm(),
- env.ram(), env.ram_session_cap(),
- _nitpicker_service),
+ _nit_fader_slave(_fader_slave_ep, env.rm(), env.pd(), env.pd_session_cap(),
+ env.ram(), env.ram_session_cap(), _nitpicker_service),
_nit_fader_connection(env.rm(), _nit_fader_slave.policy(), Slave::Args("label=menu")),
- _menu_view_slave(env.pd(), env.rm(),
+ _menu_view_slave(env.rm(), env.pd(), env.pd_session_cap(),
env.ram(), env.ram_session_cap(),
_nit_fader_connection,
_dialog_rom, _hover_report, initial_position)
diff --git a/repos/gems/src/app/launcher/main.cc b/repos/gems/src/app/launcher/main.cc
index dd69c638a..a83978013 100644
--- a/repos/gems/src/app/launcher/main.cc
+++ b/repos/gems/src/app/launcher/main.cc
@@ -43,7 +43,7 @@ struct Launcher::Main
"";
Report_rom_slave _report_rom_slave {
- _env.pd(), _env.rm(), _env.ram(), _env.ram_session_cap(),
+ _env.rm(), _env.pd(), _env.pd_session_cap(), _env.ram(), _env.ram_session_cap(),
_report_rom_config };
/**
diff --git a/repos/gems/src/app/launcher/menu_view_slave.h b/repos/gems/src/app/launcher/menu_view_slave.h
index 09c249194..df826e1ef 100644
--- a/repos/gems/src/app/launcher/menu_view_slave.h
+++ b/repos/gems/src/app/launcher/menu_view_slave.h
@@ -75,11 +75,14 @@ class Launcher::Menu_view_slave
static Name _name() { return "menu_view"; }
static Genode::Ram_quota _quota() { return { 6*1024*1024 }; }
+ static Genode::Cap_quota _caps() { return { 25 }; }
public:
Policy(Genode::Rpc_entrypoint &ep,
Genode::Region_map &rm,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Ram_session &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
Capability nitpicker_session,
@@ -88,6 +91,7 @@ class Launcher::Menu_view_slave
Position position)
:
Genode::Slave::Policy(_name(), _name(), *this, ep, rm,
+ ref_pd, ref_pd_cap, _caps(),
ref_ram, ref_ram_cap, _quota()),
_nitpicker(rm, nitpicker_session),
_dialog_rom(dialog_rom_session),
@@ -127,8 +131,9 @@ class Launcher::Menu_view_slave
/**
* Constructor
*/
- Menu_view_slave(Genode::Pd_session &pd,
- Genode::Region_map &rm,
+ Menu_view_slave(Genode::Region_map &rm,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Ram_session &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
Capability nitpicker_session,
@@ -136,8 +141,8 @@ class Launcher::Menu_view_slave
Capability hover_report_session,
Position initial_position)
:
- _ep(&pd, _ep_stack_size, "nit_fader"),
- _policy(_ep, rm, ref_ram, ref_ram_cap,
+ _ep(&ref_pd, _ep_stack_size, "nit_fader"),
+ _policy(_ep, rm, ref_pd, ref_pd_cap, ref_ram, ref_ram_cap,
nitpicker_session, dialog_rom_session,
hover_report_session, initial_position),
_child(rm, _ep, _policy)
diff --git a/repos/gems/src/app/launcher/nit_fader_slave.h b/repos/gems/src/app/launcher/nit_fader_slave.h
index 1d0b51530..d467617be 100644
--- a/repos/gems/src/app/launcher/nit_fader_slave.h
+++ b/repos/gems/src/app/launcher/nit_fader_slave.h
@@ -47,16 +47,20 @@ class Launcher::Nit_fader_slave
static Name _name() { return "nit_fader"; }
static Genode::Ram_quota _quota() { return { 2*1024*1024 }; }
+ static Genode::Cap_quota _caps() { return { 25 }; }
public:
Policy(Rpc_entrypoint &ep,
Region_map &rm,
+ Pd_session &ref_pd,
+ Pd_session_capability ref_pd_cap,
Ram_session &ref_ram,
Ram_session_capability ref_ram_cap,
Genode::Service &nitpicker_service)
:
Genode::Slave::Policy(_name(), _name(), *this, ep, rm,
+ ref_pd, ref_pd_cap, _caps(),
ref_ram, ref_ram_cap, _quota()),
_nitpicker_service(nitpicker_service)
{
@@ -95,11 +99,13 @@ class Launcher::Nit_fader_slave
*/
Nit_fader_slave(Rpc_entrypoint &ep,
Genode::Region_map &rm,
+ Pd_session &ref_pd,
+ Pd_session_capability ref_pd_cap,
Ram_session &ref_ram,
Ram_session_capability ref_ram_cap,
Genode::Service &nitpicker_service)
:
- _policy(ep, rm, ref_ram, ref_ram_cap, nitpicker_service),
+ _policy(ep, rm, ref_pd, ref_pd_cap, ref_ram, ref_ram_cap, nitpicker_service),
_child(rm, ep, _policy)
{
visible(false);
diff --git a/repos/gems/src/app/launcher/subsystem_manager.h b/repos/gems/src/app/launcher/subsystem_manager.h
index 818d78d9e..c82f91220 100644
--- a/repos/gems/src/app/launcher/subsystem_manager.h
+++ b/repos/gems/src/app/launcher/subsystem_manager.h
@@ -147,6 +147,18 @@ class Launcher::Subsystem_manager
return Ram_config { quantum, limit };
}
+ static Cap_quota _caps_config(Xml_node subsystem)
+ {
+ Cap_quota const caps { subsystem.attribute_value("caps", 0UL) };
+
+ if (caps.value)
+ return caps;
+
+ Genode::error("missing 'caps' attribute for ",
+ subsystem.attribute_value("name", Label()));
+ throw Invalid_config();
+ }
+
public:
Subsystem_manager(Genode::Env & env,
@@ -166,8 +178,7 @@ class Launcher::Subsystem_manager
{
Child::Binary_name const binary_name = _binary_name(subsystem);
- Label const label = string_attribute(subsystem, "name",
- Label(""));
+ Label const label = string_attribute(subsystem, "name", Label(""));
Ram_config const ram_config = _ram_config(subsystem);
@@ -177,9 +188,11 @@ class Launcher::Subsystem_manager
Child *child = new (_heap)
Child(_ram, _heap, label, binary_name.string(),
_env.pd(),
+ _env.pd_session_cap(),
_env.ram(),
_env.ram_session_cap(),
_env.rm(),
+ _caps_config(subsystem),
ram_config.quantum, ram_config.limit,
_yield_broadcast_handler,
_exited_child_sig_cap);
diff --git a/repos/hello_tutorial/doc/hello_tutorial.txt b/repos/hello_tutorial/doc/hello_tutorial.txt
index 8a76bc4fb..926421a30 100644
--- a/repos/hello_tutorial/doc/hello_tutorial.txt
+++ b/repos/hello_tutorial/doc/hello_tutorial.txt
@@ -76,6 +76,8 @@ C++ class in 'include/hello_session/hello_session.h'
!{
! static const char *service_name() { return "Hello"; }
!
+! enum { CAP_QUOTA = 2 };
+!
! virtual void say_hello() = 0;
! virtual int add(int a, int b) = 0;
!
@@ -91,7 +93,12 @@ across component boundaries.
Furthermore, we use the interface to specify the name of the service by
providing the 'service_name' method. This method will later be used by both
the server for announcing the service at its parent and the client for
-requesting the creation of a "Hello" session.
+requesting the creation of a "Hello" session. The 'CAP_QUOTA' definition
+specifies the amount of capabilities required to establish the session.
+The specified amount is transferred from the client to the server at session
+creation time. For the "Hello" session, two capabilities are required, namely
+a dataspace capability for the server-side memory occupied by the session
+object and the actual session capability that refers to the RPC interface.
The 'GENODE_RPC' macro is used to declare an RPC function. Its first argument
is a type name that is used to refer to the RPC function. The type name can
@@ -251,6 +258,7 @@ entry to init's 'config' file, which is located at 'build/bin/config'.
!
!
!
+!
!
!
!
@@ -345,7 +353,7 @@ of the session interface. For our case, the file
! :
! /* create session */
! Genode::Connection(env, session(env.parent(),
-! "ram_quota=4K")),
+! "ram_quota=4K, cap_quota=4")),
! /* initialize RPC interface */
! Session_client(cap()) { }
!};
@@ -413,6 +421,7 @@ at the _run/hello.run_ and look as follows:
!
!
!
+!
!
!
!
diff --git a/repos/libports/run/ldso.run b/repos/libports/run/ldso.run
index 84867bbac..c1a526f0c 100644
--- a/repos/libports/run/ldso.run
+++ b/repos/libports/run/ldso.run
@@ -43,6 +43,7 @@ run_genode_until {child ".*" exited with exit value 123.*\n} 10
grep_output {^\[init }
unify_output {\[init \-\> test\-ldso\] upgrading quota donation for .* \([0-9]+ bytes\)} ""
unify_output {ram_quota=[0-9]+} "ram_quota=UNIFIED"
+unify_output {cap_quota=[0-9]+} "cap_quota=UNIFIED"
trim_lines
compare_output_to {
@@ -83,7 +84,7 @@ compare_output_to {
[init -> test-ldso] Catch exceptions in program
[init -> test-ldso] ---------------------------
[init -> test-ldso] exception in remote procedure call:
-[init -> test-ldso] Error: ROM-session creation failed (ram_quota=UNIFIED, label="unknown_file")
+[init -> test-ldso] Error: ROM-session creation failed (ram_quota=UNIFIED, cap_quota=UNIFIED, label="unknown_file")
[init -> test-ldso] Error: Could not open ROM session for "unknown_file"
[init -> test-ldso] caught
[init -> test-ldso] exception in program: caught
diff --git a/repos/os/include/cli_monitor/child.h b/repos/os/include/cli_monitor/child.h
index 030776843..0b4c458ce 100644
--- a/repos/os/include/cli_monitor/child.h
+++ b/repos/os/include/cli_monitor/child.h
@@ -43,6 +43,7 @@ class Cli_monitor::Child_base : public Genode::Child_policy
class Quota_exceeded : public Genode::Exception { };
typedef Genode::size_t size_t;
+ typedef Genode::Cap_quota Cap_quota;
typedef Genode::Registered Parent_service;
@@ -55,9 +56,14 @@ class Cli_monitor::Child_base : public Genode::Child_policy
Genode::Session_label const _label;
Binary_name const _binary_name;
+ Genode::Pd_session_capability _ref_pd_cap;
+ Genode::Pd_session &_ref_pd;
+
Genode::Ram_session_capability _ref_ram_cap;
Genode::Ram_session &_ref_ram;
+ Cap_quota _cap_quota;
+
size_t _ram_quota;
size_t _ram_limit;
@@ -110,10 +116,12 @@ class Cli_monitor::Child_base : public Genode::Child_policy
Genode::Allocator &alloc,
Name const &label,
Binary_name const &binary_name,
- Genode::Pd_session &pd_session,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Ram_session &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
Genode::Region_map &local_rm,
+ Cap_quota cap_quota,
Genode::size_t ram_quota,
Genode::size_t ram_limit,
Genode::Signal_context_capability yield_response_sig_cap,
@@ -121,9 +129,10 @@ class Cli_monitor::Child_base : public Genode::Child_policy
:
_ram(ram), _alloc(alloc),
_label(label), _binary_name(binary_name),
+ _ref_pd_cap (ref_pd_cap), _ref_pd (ref_pd),
_ref_ram_cap(ref_ram_cap), _ref_ram(ref_ram),
- _ram_quota(ram_quota), _ram_limit(ram_limit),
- _entrypoint(&pd_session, ENTRYPOINT_STACK_SIZE, _label.string(), false),
+ _cap_quota(cap_quota), _ram_quota(ram_quota), _ram_limit(ram_limit),
+ _entrypoint(&ref_pd, ENTRYPOINT_STACK_SIZE, _label.string(), false),
_config_policy(local_rm, "config", _entrypoint, &ref_ram),
_yield_response_sigh_cap(yield_response_sig_cap),
_exit_sig_cap(exit_sig_cap),
@@ -275,9 +284,18 @@ class Cli_monitor::Child_base : public Genode::Child_policy
Name name() const override { return _label; }
Binary_name binary_name() const override { return _binary_name; }
+ Genode::Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; }
+ Genode::Pd_session &ref_pd() override { return _ref_pd; }
+
Genode::Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
Genode::Ram_session &ref_ram() override { return _ref_ram; }
+ void init(Genode::Pd_session &session, Genode::Pd_session_capability cap) override
+ {
+ session.ref_account(_ref_pd_cap);
+ _ref_pd.transfer_quota(cap, _cap_quota);
+ }
+
void init(Genode::Ram_session &session, Genode::Ram_session_capability cap) override
{
session.ref_account(_ref_ram_cap);
diff --git a/repos/os/include/loader_session/client.h b/repos/os/include/loader_session/client.h
index 11f0497c9..0b79691bd 100644
--- a/repos/os/include/loader_session/client.h
+++ b/repos/os/include/loader_session/client.h
@@ -34,6 +34,9 @@ struct Loader::Session_client : Genode::Rpc_client
void commit_rom_module(Name const &name) override {
call(name); }
+ void cap_quota(Cap_quota limit) override {
+ call(limit); }
+
void ram_quota(Ram_quota quantum) override {
call(quantum); }
diff --git a/repos/os/include/loader_session/connection.h b/repos/os/include/loader_session/connection.h
index 85ae33b8b..f2da35ca2 100644
--- a/repos/os/include/loader_session/connection.h
+++ b/repos/os/include/loader_session/connection.h
@@ -26,11 +26,12 @@ struct Loader::Connection : Genode::Connection, Session_client
/**
* Constructor
*/
- Connection(Genode::Env &env, Ram_quota ram_quota)
+ Connection(Genode::Env &env, Ram_quota ram_quota, Cap_quota cap_quota)
:
Genode::Connection(env, session(env.parent(),
- "ram_quota=%ld",
- ram_quota.value)),
+ "ram_quota=%ld, cap_quota=%ld",
+ ram_quota.value,
+ CAP_QUOTA + cap_quota.value)),
Session_client(cap())
{ }
diff --git a/repos/os/include/loader_session/loader_session.h b/repos/os/include/loader_session/loader_session.h
index 5ce86b728..5881d0eac 100644
--- a/repos/os/include/loader_session/loader_session.h
+++ b/repos/os/include/loader_session/loader_session.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -32,6 +33,7 @@ namespace Loader {
using Genode::Dataspace_capability;
using Genode::Signal_context_capability;
using Genode::Ram_quota;
+ using Genode::Cap_quota;
struct Session;
}
@@ -90,6 +92,11 @@ struct Loader::Session : Genode::Session
*/
virtual void commit_rom_module(Name const &name) = 0;
+ /**
+ * Define capability quota assigned to the subsystem
+ */
+ virtual void cap_quota(Cap_quota) = 0;
+
/**
* Define RAM quota assigned to the subsystem
*
@@ -167,6 +174,7 @@ struct Loader::Session : Genode::Session
GENODE_RPC_THROW(Rpc_commit_rom_module, void, commit_rom_module,
GENODE_TYPE_LIST(Rom_module_does_not_exist),
Name const &);
+ GENODE_RPC(Rpc_cap_quota, void, cap_quota, Cap_quota);
GENODE_RPC(Rpc_ram_quota, void, ram_quota, Ram_quota);
GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, Area);
GENODE_RPC(Rpc_parent_view, void, parent_view, Nitpicker::View_capability);
@@ -182,7 +190,7 @@ struct Loader::Session : Genode::Session
GENODE_TYPE_LIST(View_does_not_exist));
GENODE_RPC_INTERFACE(Rpc_alloc_rom_module, Rpc_commit_rom_module,
- Rpc_ram_quota, Rpc_constrain_geometry,
+ Rpc_cap_quota, Rpc_ram_quota, Rpc_constrain_geometry,
Rpc_parent_view, Rpc_view_ready_sigh, Rpc_fault_sigh,
Rpc_start, Rpc_view_geometry, Rpc_view_size);
};
diff --git a/repos/os/include/os/attached_mmio.h b/repos/os/include/os/attached_mmio.h
index 438d9dd81..ccf6fbbe9 100644
--- a/repos/os/include/os/attached_mmio.h
+++ b/repos/os/include/os/attached_mmio.h
@@ -44,7 +44,9 @@ class Genode::Attached_mmio : public Attached_io_mem_dataspace,
*
* \throw Parent::Service_denied
* \throw Insufficient_ram_quota
- * \throw Parent::Unavailable
+ * \throw Insufficient_cap_quota
+ * \throw Out_of_ram
+ * \throw Out_of_caps
* \throw Rm_session::Attach_failed
*/
Attached_mmio(Env &env, addr_t base, size_t size,
diff --git a/repos/os/include/os/child_policy_dynamic_rom.h b/repos/os/include/os/child_policy_dynamic_rom.h
index c69cc7439..a53ae5138 100644
--- a/repos/os/include/os/child_policy_dynamic_rom.h
+++ b/repos/os/include/os/child_policy_dynamic_rom.h
@@ -71,6 +71,9 @@ class Genode::Child_policy_dynamic_rom_file : public Rpc_object,
* \param ram RAM session used to allocate the backing store
* for buffering ROM module data
*
+ * \throw Out_of_ram
+ * \throw Out_of_caps
+ *
* If 'ram' is 0, the child policy is ineffective.
*/
Child_policy_dynamic_rom_file(Region_map &rm,
@@ -195,6 +198,7 @@ class Genode::Child_policy_dynamic_rom_file : public Rpc_object,
case Session_state::INVALID_ARGS:
case Session_state::INSUFFICIENT_RAM_QUOTA:
+ case Session_state::INSUFFICIENT_CAP_QUOTA:
case Session_state::AVAILABLE:
case Session_state::CAP_HANDED_OUT:
case Session_state::CLOSED:
diff --git a/repos/os/include/os/dynamic_rom_session.h b/repos/os/include/os/dynamic_rom_session.h
index 510e84060..f77ad1d77 100644
--- a/repos/os/include/os/dynamic_rom_session.h
+++ b/repos/os/include/os/dynamic_rom_session.h
@@ -98,6 +98,21 @@ class Genode::Dynamic_rom_session : public Rpc_object
*/
return true;
}
+ catch (Out_of_caps) {
+
+ error("ouf of child cap quota while delivering dynamic ROM");
+
+ /*
+ * XXX We may try to generate a resource request on
+ * behalf of the child.
+ */
+
+ /*
+ * Don't let the child try again to obtain a dataspace
+ * by pretending that the ROM module is up-to-date.
+ */
+ return true;
+ }
try {
_content_producer.produce_content(_ds->local_addr(),
@@ -166,6 +181,9 @@ class Genode::Dynamic_rom_session : public Rpc_object
if (!_ds.constructed())
_unsynchronized_update();
+ if (!_ds.constructed())
+ return Rom_dataspace_capability();
+
Dataspace_capability ds_cap = _ds->cap();
return static_cap_cast(ds_cap);
diff --git a/repos/os/include/os/slave.h b/repos/os/include/os/slave.h
index afc3bd09c..90d49e442 100644
--- a/repos/os/include/os/slave.h
+++ b/repos/os/include/os/slave.h
@@ -52,16 +52,19 @@ class Genode::Slave::Policy : public Child_policy
private:
- Label const _label;
- Binary_name const _binary_name;
+ Label const _label;
+ Binary_name const _binary_name;
+ Pd_session &_ref_pd;
+ Pd_session_capability _ref_pd_cap;
Ram_session &_ref_ram;
Ram_session_capability _ref_ram_cap;
- Genode::Parent_service _binary_service;
- Ram_quota const _ram_quota;
- Parent_services &_parent_services;
- Rpc_entrypoint &_ep;
- Child_policy_dynamic_rom_file _config_policy;
- Session_requester _session_requester;
+ Genode::Parent_service _binary_service;
+ Cap_quota const _cap_quota;
+ Ram_quota const _ram_quota;
+ Parent_services &_parent_services;
+ Rpc_entrypoint &_ep;
+ Child_policy_dynamic_rom_file _config_policy;
+ Session_requester _session_requester;
public:
@@ -83,14 +86,18 @@ class Genode::Slave::Policy : public Child_policy
Parent_services &parent_services,
Rpc_entrypoint &ep,
Region_map &rm,
+ Pd_session &ref_pd,
+ Pd_session_capability ref_pd_cap,
+ Cap_quota cap_quota,
Ram_session &ref_ram,
Ram_session_capability ref_ram_cap,
Ram_quota ram_quota)
:
_label(label), _binary_name(binary_name),
+ _ref_pd(ref_pd), _ref_pd_cap(ref_pd_cap),
_ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap),
_binary_service(Rom_session::service_name()),
- _ram_quota(ram_quota),
+ _cap_quota(cap_quota), _ram_quota(ram_quota),
_parent_services(parent_services), _ep(ep),
_config_policy(rm, "config", _ep, &_ref_ram),
_session_requester(ep, _ref_ram, rm)
@@ -127,9 +134,18 @@ class Genode::Slave::Policy : public Child_policy
Binary_name binary_name() const override { return _binary_name; }
+ Pd_session &ref_pd() override { return _ref_pd; }
+ Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; }
+
Ram_session &ref_ram() override { return _ref_ram; }
Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
+ void init(Pd_session &session, Pd_session_capability cap) override
+ {
+ session.ref_account(_ref_pd_cap);
+ _ref_pd.transfer_quota(cap, _cap_quota);
+ }
+
void init(Ram_session &session, Ram_session_capability cap) override
{
session.ref_account(_ref_ram_cap);
@@ -217,6 +233,7 @@ class Genode::Slave::Connection_base
case Session_state::INVALID_ARGS:
case Session_state::INSUFFICIENT_RAM_QUOTA:
+ case Session_state::INSUFFICIENT_CAP_QUOTA:
case Session_state::AVAILABLE:
case Session_state::CAP_HANDED_OUT:
case Session_state::CLOSED:
@@ -256,6 +273,22 @@ class Genode::Slave::Connection_base
return _policy.ref_ram_cap();
}
+ /**
+ * Service ('Cap_transfer::Account') interface
+ */
+ void transfer(Pd_session_capability to, Cap_quota amount) override
+ {
+ if (to.valid()) _policy.ref_pd().transfer_quota(to, amount);
+ }
+
+ /**
+ * Service ('Cap_transfer::Account') interface
+ */
+ Pd_session_capability cap(Cap_quota) const override
+ {
+ return _policy.ref_pd_cap();
+ }
+
} _service;
Local_connection _connection;
diff --git a/repos/os/run/report_rom.run b/repos/os/run/report_rom.run
index 6e3b0e5f6..5c057b13d 100644
--- a/repos/os/run/report_rom.run
+++ b/repos/os/run/report_rom.run
@@ -71,7 +71,7 @@ compare_output_to {
[init -> test-report_rom] Reporter: start reporting (while the ROM client still listens)
[init -> test-report_rom] ROM client: wait for update notification
[init -> test-report_rom] ROM client: try to open the same report again
- [init -> test-report_rom] Error: Report-session creation failed (label="brightness", ram_quota=14336, buffer_size=4096)
+ [init -> test-report_rom] Error: Report-session creation failed (label="brightness", ram_quota=14336, cap_quota=3, buffer_size=4096)
[init -> test-report_rom] ROM client: catched Parent::Service_denied - OK
[init -> test-report_rom] --- test-report_rom finished ---
}
diff --git a/repos/os/src/app/cli_monitor/child.h b/repos/os/src/app/cli_monitor/child.h
index 2e768c617..f881d8693 100644
--- a/repos/os/src/app/cli_monitor/child.h
+++ b/repos/os/src/app/cli_monitor/child.h
@@ -31,10 +31,12 @@ struct Cli_monitor::Child : Child_base, List::Element
Genode::Allocator &alloc,
Name const &label,
Binary_name const &binary,
- Genode::Pd_session &pd_session,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Ram_session &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
Genode::Region_map &local_rm,
+ Cap_quota cap_quota,
Genode::size_t ram_quota,
Genode::size_t ram_limit,
Genode::Signal_context_capability yield_response_sig_cap,
@@ -44,10 +46,12 @@ struct Cli_monitor::Child : Child_base, List::Element
alloc,
label,
binary,
- pd_session,
+ ref_pd,
+ ref_pd_cap,
ref_ram,
ref_ram_cap,
local_rm,
+ cap_quota,
ram_quota,
ram_limit,
yield_response_sig_cap,
diff --git a/repos/os/src/app/cli_monitor/main.cc b/repos/os/src/app/cli_monitor/main.cc
index 184ba3acb..0346928f1 100644
--- a/repos/os/src/app/cli_monitor/main.cc
+++ b/repos/os/src/app/cli_monitor/main.cc
@@ -172,7 +172,8 @@ struct Cli_monitor::Main
/* initialize generic commands */
Registered _help_command { _commands };
Registered _kill_command { _commands, _children, _heap };
- Registered _start_command { _commands, _ram, _heap, _env.pd(),
+ Registered _start_command { _commands, _ram, _heap,
+ _env.pd(), _env.pd_session_cap(),
_env.ram(), _env.ram_session_cap(),
_env.rm(), _children,
_subsystem_config_registry,
diff --git a/repos/os/src/app/cli_monitor/start_command.h b/repos/os/src/app/cli_monitor/start_command.h
index 97a9501c6..aaf750e37 100644
--- a/repos/os/src/app/cli_monitor/start_command.h
+++ b/repos/os/src/app/cli_monitor/start_command.h
@@ -34,7 +34,8 @@ class Cli_monitor::Start_command : public Command
Ram &_ram;
Genode::Allocator &_alloc;
Child_registry &_children;
- Genode::Pd_session &_pd;
+ Genode::Pd_session &_ref_pd;
+ Genode::Pd_session_capability _ref_pd_cap;
Genode::Ram_session &_ref_ram;
Genode::Ram_session_capability _ref_ram_cap;
Genode::Region_map &_local_rm;
@@ -50,6 +51,7 @@ class Cli_monitor::Start_command : public Command
size_t count = 1;
Genode::Number_of_bytes ram = 0;
Genode::Number_of_bytes ram_limit = 0;
+ size_t caps = subsystem_node.attribute_value("caps", 0UL);
/* read default RAM quota from config */
try {
@@ -113,8 +115,10 @@ class Cli_monitor::Start_command : public Command
Child *child = 0;
try {
child = new (_alloc)
- Child(_ram, _alloc, label, binary_name, _pd, _ref_ram,
- _ref_ram_cap, _local_rm, ram, ram_limit,
+ Child(_ram, _alloc, label, binary_name,
+ _ref_pd, _ref_pd_cap, _ref_ram,
+ _ref_ram_cap, _local_rm,
+ Genode::Cap_quota{caps}, ram, ram_limit,
_yield_response_sigh_cap, _exit_sig_cap);
}
catch (Genode::Parent::Service_denied) {
@@ -160,7 +164,8 @@ class Cli_monitor::Start_command : public Command
Start_command(Ram &ram,
Genode::Allocator &alloc,
- Genode::Pd_session &pd,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Ram_session &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
Genode::Region_map &local_rm,
@@ -170,8 +175,10 @@ class Cli_monitor::Start_command : public Command
Signal_context_capability exit_sig_cap)
:
Command("start", "create new subsystem"),
- _ram(ram), _alloc(alloc), _children(children), _pd(pd),
- _ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap), _local_rm(local_rm),
+ _ram(ram), _alloc(alloc), _children(children),
+ _ref_pd(ref_pd), _ref_pd_cap(ref_pd_cap),
+ _ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap),
+ _local_rm(local_rm),
_subsystem_configs(subsustem_configs),
_yield_response_sigh_cap(yield_response_sigh_cap),
_exit_sig_cap(exit_sig_cap)
diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd.h b/repos/os/src/drivers/platform/spec/x86/device_pd.h
index 406a93433..a28af2672 100644
--- a/repos/os/src/drivers/platform/spec/x86/device_pd.h
+++ b/repos/os/src/drivers/platform/spec/x86/device_pd.h
@@ -33,12 +33,16 @@ class Platform::Device_pd_policy
Device_pd_policy(Genode::Rpc_entrypoint &slave_ep,
Genode::Region_map &local_rm,
+ Genode::Pd_session &pd_ref,
+ Genode::Pd_session_capability pd_ref_cap,
+ Genode::Cap_quota cap_quota,
Genode::Ram_session &ram_ref,
Genode::Ram_session_capability ram_ref_cap,
Genode::Ram_quota ram_quota,
Genode::Session_label const &label)
:
Genode::Slave::Policy(label, "device_pd", *this, slave_ep, local_rm,
+ pd_ref, pd_ref_cap, cap_quota,
ram_ref, ram_ref_cap, ram_quota)
{ }
};
diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h
index 1b508d1f8..c5a725bd3 100644
--- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h
+++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h
@@ -202,6 +202,8 @@ class Platform::Session_component : public Genode::Rpc_object
Genode::Attached_rom_dataspace &_config;
Genode::Ram_session_guard _env_ram;
Genode::Ram_session_capability _env_ram_cap;
+ Genode::Pd_session &_env_pd;
+ Genode::Pd_session_capability _env_pd_cap;
Genode::Region_map &_local_rm;
Genode::Heap _md_alloc;
Genode::Session_label const _label;
@@ -254,6 +256,13 @@ class Platform::Session_component : public Genode::Rpc_object
enum { OVERHEAD = 4096 };
try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{OVERHEAD}); }
catch (...) { throw Genode::Insufficient_ram_quota(); }
+
+ /*
+ * XXX instead of eagerly upgrading the RAM session, upgrade it
+ * on demand, paid by the client's cap session quota.
+ */
+ using namespace Genode;
+ _ram.upgrade(Session::Resources { Ram_quota{0}, Cap_quota{10} });
}
bool const _ram_initialized = (_init_ram(), true);
@@ -291,7 +300,7 @@ class Platform::Session_component : public Genode::Rpc_object
private:
- enum { RAM_QUOTA = 190 * 4096 };
+ enum { CAP_QUOTA = 60, RAM_QUOTA = 190 * 4096 };
Quota_reservation const _reservation;
Device_pd_policy _policy;
@@ -319,11 +328,15 @@ class Platform::Session_component : public Genode::Rpc_object
Genode::Rpc_entrypoint &ep,
Genode::Ram_session_guard &ref_ram,
Genode::Ram_session_capability ref_ram_cap,
+ Genode::Pd_session &ref_pd,
+ Genode::Pd_session_capability ref_pd_cap,
Genode::Session_label const &label)
try :
_reservation(ref_ram, RAM_QUOTA),
_policy(ep, local_rm,
- ref_ram, ref_ram_cap, Genode::Ram_quota{RAM_QUOTA}, label),
+ ref_pd, ref_pd_cap, Genode::Cap_quota{CAP_QUOTA},
+ ref_ram, ref_ram_cap, Genode::Ram_quota{RAM_QUOTA},
+ label),
_child(local_rm, ep, _policy),
_connection(_policy, Genode::Slave::Args())
{ }
@@ -331,8 +344,18 @@ class Platform::Session_component : public Genode::Rpc_object
catch (Out_of_metadata) { throw; }
/* thrown by 'Device_pd_policy' or 'Child' */
catch (Genode::Out_of_ram) { throw Out_of_metadata(); }
- /* throw by 'Slave::Connection' */
+ catch (Genode::Out_of_caps) {
+ /* XXX reflect 'Out_of_caps' exception to client */
+ Genode::error("Out_of_caps during device-pd creation");
+ throw Out_of_metadata();
+ }
+ /* thrown by 'Slave::Connection' */
catch (Genode::Insufficient_ram_quota) { throw Out_of_metadata(); }
+ /* thrown by 'Slave::Connection' */
+ catch (Genode::Insufficient_cap_quota) {
+ Genode::error("Insufficient_cap_quota during device-pd creation");
+ throw Out_of_metadata();
+ }
Device_pd_client &session() { return _connection; }
@@ -368,13 +391,19 @@ class Platform::Session_component : public Genode::Rpc_object
try {
_device_pd = new (_md_alloc)
- Device_pd(_local_rm, _device_pd_ep, _env_ram,
- _env_ram_cap, _label);
+ Device_pd(_local_rm, _device_pd_ep, _env_ram, _env_ram_cap,
+ _env_pd, _env_pd_cap, _label);
}
/* thrown by '_md_alloc' */
catch (Genode::Out_of_ram) { throw Out_of_metadata(); }
+ catch (Genode::Out_of_caps) {
+ /* XXX reflect exception to client */
+ Genode::error("Out_of_caps during Device_pd construction");
+ throw Out_of_metadata();
+ }
+
/* thrown by 'Device_pd' */
catch (Out_of_metadata) { throw; }
@@ -609,6 +638,8 @@ class Platform::Session_component : public Genode::Rpc_object
_env_ram(env.ram(), env.ram_session_cap(),
Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
_env_ram_cap(env.ram_session_cap()),
+ _env_pd(env.pd()),
+ _env_pd_cap(env.pd_session_cap()),
_local_rm(env.rm()),
_md_alloc(_env_ram, env.rm()),
_label(Genode::label_from_args(args)),
@@ -846,6 +877,10 @@ class Platform::Session_component : public Genode::Rpc_object
return _env.ep().rpc_ep().manage(dev);
} catch (Genode::Allocator::Out_of_memory) {
throw Out_of_metadata();
+ } catch (Genode::Out_of_caps) {
+ /* XXX reflect exception to client */
+ Genode::error("Out_of_caps during Device_component construction");
+ throw Out_of_metadata();
}
};
return _env.ep().rpc_ep().apply(prev_device, lambda);
@@ -945,24 +980,35 @@ class Platform::Session_component : public Genode::Rpc_object
/* transfer ram quota to session specific ram session */
try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{size}); }
catch (Genode::Out_of_ram) { throw Out_of_metadata(); }
- catch (...) { throw Fatal(); }
+ catch (Genode::Out_of_caps) {
+ Genode::error("Out_of_caps during alloc_dma_buffer (transfer_quota)");
+ throw Fatal();
+ }
+ catch (...) { }
enum { UPGRADE_QUOTA = 4096 };
/* allocate dataspace from session specific ram session */
Ram_capability ram_cap = Genode::retry(
[&] () {
- try {
- return _ram.alloc(size, Genode::UNCACHED);
- }
- catch (Genode::Out_of_ram) {
+ Ram_capability ram = Genode::retry(
+ [&] () {
+ try { return _ram.alloc(size, Genode::UNCACHED); }
+ catch (Genode::Out_of_caps) {
+ Genode::error("Out_of_caps during alloc_dma_buffer (alloc)");
+ throw Fatal();
+ }
+ },
+ [&] () {
+ if (!_env_ram.withdraw(UPGRADE_QUOTA)) {
+ _rollback(size);
+ }
- if (!_env_ram.withdraw(UPGRADE_QUOTA))
- _rollback(size);
-
- throw;
- }
+ /* upgrade meta-data quota */
+ _ram.upgrade_ram(UPGRADE_QUOTA);
+ });
+ return ram;
},
[&] () {
/*
@@ -973,7 +1019,7 @@ class Platform::Session_component : public Genode::Rpc_object
* UPGRADE_QUOTA steps.
*/
try { _env_ram.transfer_quota(_ram, Genode::Ram_quota{UPGRADE_QUOTA}); }
- catch (...) { throw Genode::Out_of_ram(); }
+ catch (Genode::Out_of_ram) { throw Out_of_metadata(); }
});
if (!ram_cap.valid())
diff --git a/repos/os/src/init/child.cc b/repos/os/src/init/child.cc
index b0abce20d..bb00983be 100644
--- a/repos/os/src/init/child.cc
+++ b/repos/os/src/init/child.cc
@@ -289,9 +289,20 @@ void Init::Child::report_state(Xml_generator &xml, Report_detail const &detail)
generate_ram_info(xml, _child.ram());
- if (_requested_resources.constructed())
- xml.attribute("requested", String<32> {
- Number_of_bytes(_requested_resources->ram.value) });
+ if (_requested_resources.constructed() && _requested_resources->ram.value)
+ xml.attribute("requested", String<32>(_requested_resources->ram));
+ });
+ }
+
+ if (detail.child_caps() && _child.pd_session_cap().valid()) {
+ xml.node("caps", [&] () {
+
+ xml.attribute("assigned", String<32>(_resources.assigned_cap_quota));
+
+ generate_caps_info(xml, _child.pd());
+
+ if (_requested_resources.constructed() && _requested_resources->caps.value)
+ xml.attribute("requested", String<32>(_requested_resources->caps));
});
}
@@ -320,6 +331,18 @@ void Init::Child::report_state(Xml_generator &xml, Report_detail const &detail)
}
+void Init::Child::init(Pd_session &session, Pd_session_capability cap)
+{
+ session.ref_account(_env.pd_session_cap());
+
+ Cap_quota const quota { _resources.effective_cap_quota().value };
+
+ try { _env.pd().transfer_quota(cap, quota); }
+ catch (Out_of_caps) {
+ error(name(), ": unable to initialize cap quota of PD"); }
+}
+
+
void Init::Child::init(Ram_session &session, Ram_session_capability cap)
{
session.ref_account(_env.ram_session_cap());
@@ -613,8 +636,10 @@ Init::Child::Child(Env &env,
Report_update_trigger &report_update_trigger,
Xml_node start_node,
Default_route_accessor &default_route_accessor,
+ Default_caps_accessor &default_caps_accessor,
Name_registry &name_registry,
Ram_quota ram_limit,
+ Cap_quota cap_limit,
Ram_limit_accessor &ram_limit_accessor,
Prio_levels prio_levels,
Affinity::Space const &affinity_space,
@@ -628,8 +653,10 @@ Init::Child::Child(Env &env,
_default_route_accessor(default_route_accessor),
_ram_limit_accessor(ram_limit_accessor),
_name_registry(name_registry),
- _resources(_resources_from_start_node(start_node, prio_levels, affinity_space)),
- _resources_checked((_check_ram_constraints(ram_limit), true)),
+ _resources(_resources_from_start_node(start_node, prio_levels, affinity_space,
+ default_caps_accessor.default_caps(), cap_limit)),
+ _resources_checked((_check_ram_constraints(ram_limit),
+ _check_cap_constraints(cap_limit), true)),
_parent_services(parent_services),
_child_services(child_services),
_session_requester(_env.ep().rpc_ep(), _env.ram(), _env.rm())
@@ -637,6 +664,7 @@ Init::Child::Child(Env &env,
if (_verbose.enabled()) {
log("child \"", _unique_name, "\"");
log(" RAM quota: ", _resources.effective_ram_quota());
+ log(" cap quota: ", _resources.effective_cap_quota());
log(" ELF binary: ", _binary_name);
log(" priority: ", _resources.priority);
}
diff --git a/repos/os/src/init/child.h b/repos/os/src/init/child.h
index 8ee582c9f..ae2096597 100644
--- a/repos/os/src/init/child.h
+++ b/repos/os/src/init/child.h
@@ -48,6 +48,8 @@ class Init::Child : Child_policy, Routed_service::Wakeup
struct Default_route_accessor { virtual Xml_node default_route() = 0; };
+ struct Default_caps_accessor { virtual Cap_quota default_caps() = 0; };
+
struct Ram_limit_accessor { virtual Ram_quota ram_limit() = 0; };
private:
@@ -124,6 +126,7 @@ class Init::Child : Child_policy, Routed_service::Wakeup
long priority;
Affinity affinity;
Ram_quota assigned_ram_quota;
+ Cap_quota assigned_cap_quota;
size_t cpu_quota_pc;
bool constrain_phys;
@@ -131,15 +134,39 @@ class Init::Child : Child_policy, Routed_service::Wakeup
{
return Genode::Child::effective_quota(assigned_ram_quota);
}
+
+ Cap_quota effective_cap_quota() const
+ {
+ /* capabilities consumed by 'Genode::Child' */
+ Cap_quota const effective =
+ Genode::Child::effective_quota(assigned_cap_quota);
+
+ /* capabilities additionally consumed by init */
+ enum {
+ STATIC_COSTS = 1 /* possible heap backing-store
+ allocation for session object */
+ + 1 /* buffered XML start node */
+ + 2 /* dynamic ROM for config */
+ + 2 /* dynamic ROM for session requester */
+ };
+
+ if (effective.value < STATIC_COSTS)
+ return Cap_quota{0};
+
+ return Cap_quota{effective.value - STATIC_COSTS};
+ }
};
Resources _resources_from_start_node(Xml_node start_node, Prio_levels prio_levels,
- Affinity::Space const &affinity_space)
+ Affinity::Space const &affinity_space,
+ Cap_quota default_cap_quota, Cap_quota cap_limit)
{
size_t cpu_quota_pc = 0;
bool constrain_phys = false;
Number_of_bytes ram_bytes = 0;
+ size_t caps = start_node.attribute_value("caps", default_cap_quota.value);
+
start_node.for_each_sub_node("resource", [&] (Xml_node rsc) {
typedef String<8> Name;
@@ -153,6 +180,10 @@ class Init::Child : Child_policy, Routed_service::Wakeup
if (name == "CPU") {
cpu_quota_pc = rsc.attribute_value("quantum", 0UL);
}
+
+ if (name == "CAP") {
+ caps = rsc.attribute_value("quantum", 0UL);
+ }
});
return Resources { log2(prio_levels.value),
@@ -160,6 +191,7 @@ class Init::Child : Child_policy, Routed_service::Wakeup
Affinity(affinity_space,
affinity_location_from_xml(affinity_space, start_node)),
Ram_quota { ram_bytes },
+ Cap_quota { caps },
cpu_quota_pc,
constrain_phys };
}
@@ -171,6 +203,9 @@ class Init::Child : Child_policy, Routed_service::Wakeup
if (_resources.effective_ram_quota().value == 0)
warning(name(), ": no valid RAM quota defined");
+ if (_resources.effective_cap_quota().value == 0)
+ warning(name(), ": no valid cap quota defined");
+
/*
* If the configured RAM quota exceeds our own quota, we donate
* all remaining quota to the child.
@@ -183,6 +218,20 @@ class Init::Child : Child_policy, Routed_service::Wakeup
}
}
+ void _check_cap_constraints(Cap_quota cap_limit)
+ {
+ if (_resources.assigned_cap_quota.value == 0)
+ warning(name(), ": no valid cap quota defined");
+
+ if (_resources.assigned_cap_quota.value > cap_limit.value) {
+
+ warning(name(), ": assigned caps (", _resources.assigned_cap_quota.value, ") "
+ "exceed available caps (", cap_limit.value, ")");
+
+ _resources.assigned_cap_quota.value = cap_limit.value;
+ }
+ }
+
bool const _resources_checked;
Registry &_parent_services;
@@ -255,10 +304,12 @@ class Init::Child : Child_policy, Routed_service::Wakeup
struct Requested_resources
{
Ram_quota const ram;
+ Cap_quota const caps;
Requested_resources(Parent::Resource_args const &args)
:
- ram (ram_quota_from_args(args.string()))
+ ram (ram_quota_from_args(args.string())),
+ caps(cap_quota_from_args(args.string()))
{ }
};
@@ -266,16 +317,20 @@ class Init::Child : Child_policy, Routed_service::Wakeup
Genode::Child _child { _env.rm(), _env.ep().rpc_ep(), *this };
- struct Ram_accessor : Routed_service::Ram_accessor
+ struct Ram_pd_accessor : Routed_service::Ram_accessor,
+ Routed_service::Pd_accessor
{
Genode::Child &_child;
- Ram_accessor(Genode::Child &child) : _child(child) { }
+ Ram_pd_accessor(Genode::Child &child) : _child(child) { }
Ram_session &ram() override { return _child.ram(); }
Ram_session_capability ram_cap() const override { return _child.ram_session_cap(); }
- } _ram_accessor { _child };
+ Pd_session &pd() override { return _child.pd(); }
+ Pd_session_capability pd_cap() const override { return _child.pd_session_cap(); }
+
+ } _ram_pd_accessor { _child };
/**
* Async_service::Wakeup callback
@@ -343,7 +398,7 @@ class Init::Child : Child_policy, Routed_service::Wakeup
new (_alloc)
Routed_service(_child_services, this->name(),
- _ram_accessor,
+ _ram_pd_accessor, _ram_pd_accessor,
_session_requester.id_space(),
_child.session_factory(),
name, *this);
@@ -375,8 +430,10 @@ class Init::Child : Child_policy, Routed_service::Wakeup
Report_update_trigger &report_update_trigger,
Xml_node start_node,
Default_route_accessor &default_route_accessor,
+ Default_caps_accessor &default_caps_accessor,
Name_registry &name_registry,
Ram_quota ram_limit,
+ Cap_quota cap_limit,
Ram_limit_accessor &ram_limit_accessor,
Prio_levels prio_levels,
Affinity::Space const &affinity_space,
@@ -391,6 +448,7 @@ class Init::Child : Child_policy, Routed_service::Wakeup
bool has_name(Child_policy::Name const &str) const { return str == name(); }
Ram_quota ram_quota() const { return _resources.assigned_ram_quota; }
+ Cap_quota cap_quota() const { return _resources.assigned_cap_quota; }
void initiate_env_ram_session()
{
@@ -451,9 +509,13 @@ class Init::Child : Child_policy, Routed_service::Wakeup
Child_policy::Name name() const override { return _unique_name; }
+ Pd_session &ref_pd() override { return _env.pd(); }
+ Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
+
Ram_session &ref_ram() override { return _env.ram(); }
Ram_session_capability ref_ram_cap() const override { return _env.ram_session_cap(); }
+ void init(Pd_session &, Pd_session_capability) override;
void init(Ram_session &, Ram_session_capability) override;
void init(Cpu_session &, Cpu_session_capability) override;
diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc
index 5d8816e33..b193d10a7 100644
--- a/repos/os/src/init/main.cc
+++ b/repos/os/src/init/main.cc
@@ -26,7 +26,7 @@ namespace Init { struct Main; }
struct Init::Main : State_reporter::Producer, Child::Default_route_accessor,
- Child::Ram_limit_accessor
+ Child::Default_caps_accessor, Child::Ram_limit_accessor
{
Env &_env;
@@ -42,6 +42,8 @@ struct Init::Main : State_reporter::Producer, Child::Default_route_accessor,
Constructible _default_route;
+ Cap_quota _default_caps { 0 };
+
unsigned _child_cnt = 0;
static Ram_quota _preserved_ram_from_config(Xml_node config)
@@ -70,6 +72,32 @@ struct Init::Main : State_reporter::Producer, Child::Default_route_accessor,
return Ram_quota { avail_ram.value - preserved_ram.value };
}
+ static Cap_quota _preserved_caps_from_config(Xml_node config)
+ {
+ size_t preserve = 20;
+
+ config.for_each_sub_node("resource", [&] (Xml_node node) {
+ if (node.attribute_value("name", String<16>()) == "CAP")
+ preserve = node.attribute_value("preserve", preserve); });
+
+ return Cap_quota { preserve };
+ }
+
+ Cap_quota _avail_caps()
+ {
+ Cap_quota const preserved_caps = _preserved_caps_from_config(_config.xml());
+
+ Cap_quota avail_caps { _env.pd().avail_caps().value };
+
+ if (preserved_caps.value > avail_caps.value) {
+ error("Capability preservation exceeds available capabilities");
+ return Cap_quota { 0 };
+ }
+
+ /* deduce preserved quota from available quota */
+ return Cap_quota { avail_caps.value - preserved_caps.value };
+ }
+
/**
* Child::Ram_limit_accessor interface
*/
@@ -80,7 +108,10 @@ struct Init::Main : State_reporter::Producer, Child::Default_route_accessor,
void produce_state_report(Xml_generator &xml, Report_detail const &detail) const
{
if (detail.init_ram())
- xml.node("ram", [&] () { generate_ram_info(xml, _env.ram()); });
+ xml.node("ram", [&] () { generate_ram_info (xml, _env.ram()); });
+
+ if (detail.init_caps())
+ xml.node("caps", [&] () { generate_caps_info(xml, _env.pd()); });
if (detail.children())
_children.report_state(xml, detail);
@@ -95,6 +126,11 @@ struct Init::Main : State_reporter::Producer, Child::Default_route_accessor,
: Xml_node("");
}
+ /**
+ * Default_caps_accessor interface
+ */
+ Cap_quota default_caps() override { return _default_caps; }
+
State_reporter _state_reporter { _env, *this };
Signal_handler _resource_avail_handler {
@@ -258,6 +294,12 @@ void Init::Main::_handle_config()
_default_route.construct(_heap, _config.xml().sub_node("default-route")); }
catch (...) { }
+ _default_caps = Cap_quota { 0 };
+ try {
+ _default_caps = Cap_quota { _config.xml().sub_node("default")
+ .attribute_value("caps", 0UL) }; }
+ catch (...) { }
+
Prio_levels const prio_levels = prio_levels_from_xml(_config.xml());
Affinity::Space const affinity_space = affinity_space_from_xml(_config.xml());
@@ -278,9 +320,11 @@ void Init::Main::_handle_config()
/* initial RAM and caps limit before starting new children */
Ram_quota const avail_ram = _avail_ram();
+ Cap_quota const avail_caps = _avail_caps();
/* variable used to track the RAM and caps taken by new started children */
Ram_quota used_ram { 0 };
+ Cap_quota used_caps { 0 };
/* create new children */
try {
@@ -300,12 +344,18 @@ void Init::Main::_handle_config()
throw Out_of_ram();
}
+ if (used_caps.value > avail_caps.value) {
+ error("capabilities exhausted while starting childen");
+ throw Out_of_caps();
+ }
+
try {
Init::Child &child = *new (_heap)
Init::Child(_env, _heap, *_verbose,
Init::Child::Id { ++_child_cnt }, _state_reporter,
- start_node, *this, _children,
- Ram_quota { avail_ram.value - used_ram.value },
+ start_node, *this, *this, _children,
+ Ram_quota { avail_ram.value - used_ram.value },
+ Cap_quota { avail_caps.value - used_caps.value },
*this, prio_levels, affinity_space,
_parent_services, _child_services);
_children.insert(&child);
@@ -317,6 +367,9 @@ void Init::Main::_handle_config()
used_ram = Ram_quota { used_ram.value
+ child.ram_quota().value
+ metadata_overhead };
+
+ used_caps = Cap_quota { used_caps.value
+ + child.cap_quota().value };
}
catch (Rom_connection::Rom_connection_failed) {
/*
@@ -326,6 +379,8 @@ void Init::Main::_handle_config()
}
catch (Out_of_ram) {
warning("memory exhausted during child creation"); }
+ catch (Out_of_caps) {
+ warning("local capabilities exhausted during child creation"); }
catch (Child::Missing_name_attribute) {
warning("skipped startup of nameless child"); }
catch (Region_map::Attach_failed) {
diff --git a/repos/os/src/init/report.h b/repos/os/src/init/report.h
index fcb6b0857..cfb81104f 100644
--- a/repos/os/src/init/report.h
+++ b/repos/os/src/init/report.h
@@ -33,7 +33,9 @@ class Init::Report_detail : Genode::Noncopyable
bool _provided = false;
bool _session_args = false;
bool _child_ram = false;
+ bool _child_caps = false;
bool _init_ram = false;
+ bool _init_caps = false;
public:
@@ -47,7 +49,9 @@ class Init::Report_detail : Genode::Noncopyable
_provided = report.attribute_value("provided", false);
_session_args = report.attribute_value("session_args", false);
_child_ram = report.attribute_value("child_ram", false);
+ _child_caps = report.attribute_value("child_caps", false);
_init_ram = report.attribute_value("init_ram", false);
+ _init_caps = report.attribute_value("init_caps", false);
}
bool children() const { return _children; }
@@ -56,7 +60,9 @@ class Init::Report_detail : Genode::Noncopyable
bool provided() const { return _provided; }
bool session_args() const { return _session_args; }
bool child_ram() const { return _child_ram; }
+ bool child_caps() const { return _child_caps; }
bool init_ram() const { return _init_ram; }
+ bool init_caps() const { return _init_caps; }
};
diff --git a/repos/os/src/init/server.cc b/repos/os/src/init/server.cc
index 9f5738666..b6e8664be 100644
--- a/repos/os/src/init/server.cc
+++ b/repos/os/src/init/server.cc
@@ -12,6 +12,7 @@
*/
/* Genode includes */
+#include
#include
/* local includes */
@@ -149,10 +150,14 @@ void Init::Server::session_closed(Session_state &session)
_report_update_trigger.trigger_report_update();
Ram_transfer::Account &service_ram_account = session.service();
+ Cap_transfer::Account &service_cap_account = session.service();
service_ram_account.try_transfer(_env.ram_session_cap(),
session.donated_ram_quota());
+ service_cap_account.try_transfer(_env.pd_session_cap(),
+ session.donated_cap_quota());
+
Parent::Server::Id id { session.id_at_client().value };
session.destroy();
@@ -183,7 +188,9 @@ void Init::Server::_handle_create_session_request(Xml_node request,
char argbuf[Parent::Session_args::MAX_SIZE];
strncpy(argbuf, args.string(), sizeof(argbuf));
+ Cap_quota const cap_quota = cap_quota_from_args(argbuf);
Ram_quota const ram_quota = ram_quota_from_args(argbuf);
+
size_t const keep_quota = route.service.factory().session_costs();
if (ram_quota.value < keep_quota)
@@ -201,10 +208,13 @@ void Init::Server::_handle_create_session_request(Xml_node request,
/* transfer session quota */
try {
Ram_transfer::Remote_account env_ram_account(_env.ram(), _env.ram_session_cap());
+ Cap_transfer::Remote_account env_cap_account(_env.pd(), _env.pd_session_cap());
Ram_transfer ram_transfer(forward_ram_quota, env_ram_account, route.service);
+ Cap_transfer cap_transfer(cap_quota, env_cap_account, route.service);
ram_transfer.acknowledge();
+ cap_transfer.acknowledge();
}
catch (...) {
/*
@@ -212,7 +222,8 @@ void Init::Server::_handle_create_session_request(Xml_node request,
* transfor the session quota to us prior issuing the session
* request.
*/
- warning("unable to transfer session quota (", ram_quota, " bytes) "
+ warning("unable to transfer session quota "
+ "(", ram_quota, " bytes, ", cap_quota, " caps) "
"of forwarded ", name, " session");
session.destroy();
throw Parent::Service_denied();
@@ -233,6 +244,9 @@ void Init::Server::_handle_create_session_request(Xml_node request,
if (session.phase == Session_state::INSUFFICIENT_RAM_QUOTA)
throw Genode::Insufficient_ram_quota();
+
+ if (session.phase == Session_state::INSUFFICIENT_CAP_QUOTA)
+ throw Genode::Insufficient_cap_quota();
}
catch (Parent::Service_denied) {
_env.parent().session_response(Parent::Server::Id { id.value },
@@ -240,6 +254,9 @@ void Init::Server::_handle_create_session_request(Xml_node request,
catch (Genode::Insufficient_ram_quota) {
_env.parent().session_response(Parent::Server::Id { id.value },
Parent::INSUFFICIENT_RAM_QUOTA); }
+ catch (Genode::Insufficient_cap_quota) {
+ _env.parent().session_response(Parent::Server::Id { id.value },
+ Parent::INSUFFICIENT_CAP_QUOTA); }
}
@@ -249,23 +266,28 @@ void Init::Server::_handle_upgrade_session_request(Xml_node request,
_client_id_space.apply(id, [&] (Session_state &session) {
Ram_quota const ram_quota { request.attribute_value("ram_quota", 0UL) };
+ Cap_quota const cap_quota { request.attribute_value("cap_quota", 0UL) };
session.phase = Session_state::UPGRADE_REQUESTED;
try {
Ram_transfer::Remote_account env_ram_account(_env.ram(), _env.ram_session_cap());
+ Cap_transfer::Remote_account env_cap_account(_env.pd(), _env.pd_session_cap());
Ram_transfer ram_transfer(ram_quota, env_ram_account, session.service());
+ Cap_transfer cap_transfer(cap_quota, env_cap_account, session.service());
ram_transfer.acknowledge();
+ cap_transfer.acknowledge();
}
catch (...) {
- warning("unable to upgrade session quota (", ram_quota, " bytes) "
+ warning("unable to upgrade session quota "
+ "(", ram_quota, " bytes, ", cap_quota, " caps) "
"of forwarded ", session.service().name(), " session");
return;
}
- session.increase_donated_quota(ram_quota);
+ session.increase_donated_quota(ram_quota, cap_quota);
session.service().initiate_request(session);
session.service().wakeup();
});
diff --git a/repos/os/src/init/service.h b/repos/os/src/init/service.h
index 8f4da4370..6559f52cd 100644
--- a/repos/os/src/init/service.h
+++ b/repos/os/src/init/service.h
@@ -71,11 +71,18 @@ class Init::Routed_service : public Async_service, public Abandonable
virtual Ram_session_capability ram_cap() const = 0;
};
+ struct Pd_accessor
+ {
+ virtual Pd_session &pd() = 0;
+ virtual Pd_session_capability pd_cap() const = 0;
+ };
+
private:
Child_name _child_name;
Ram_accessor &_ram_accessor;
+ Pd_accessor &_pd_accessor;
Session_state::Factory &_factory;
@@ -94,6 +101,7 @@ class Init::Routed_service : public Async_service, public Abandonable
Routed_service(Registry &services,
Child_name const &child_name,
Ram_accessor &ram_accessor,
+ Pd_accessor &pd_accessor,
Id_space &server_id_space,
Session_state::Factory &factory,
Service::Name const &name,
@@ -101,7 +109,7 @@ class Init::Routed_service : public Async_service, public Abandonable
:
Async_service(name, server_id_space, factory, wakeup),
_child_name(child_name),
- _ram_accessor(ram_accessor),
+ _ram_accessor(ram_accessor), _pd_accessor(pd_accessor),
_factory(factory), _registry_element(services, *this)
{ }
@@ -124,6 +132,22 @@ class Init::Routed_service : public Async_service, public Abandonable
{
return _ram_accessor.ram_cap();
}
+
+ /**
+ * Cap_transfer::Account interface
+ */
+ void transfer(Pd_session_capability to, Cap_quota amount) override
+ {
+ if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount);
+ }
+
+ /**
+ * Cap_transfer::Account interface
+ */
+ Pd_session_capability cap(Cap_quota) const override
+ {
+ return _pd_accessor.pd_cap();
+ }
};
#endif /* _SRC__INIT__SERVICE_H_ */
diff --git a/repos/os/src/init/types.h b/repos/os/src/init/types.h
index b39915ae9..27c0d19c3 100644
--- a/repos/os/src/init/types.h
+++ b/repos/os/src/init/types.h
@@ -16,6 +16,7 @@
#include
#include
+#include
namespace Init {
diff --git a/repos/os/src/init/utils.h b/repos/os/src/init/utils.h
index 7e3a8e98f..7468b9803 100644
--- a/repos/os/src/init/utils.h
+++ b/repos/os/src/init/utils.h
@@ -136,13 +136,20 @@ namespace Init {
inline void generate_ram_info(Xml_generator &xml, Ram_session const &ram)
{
-
typedef String<32> Value;
xml.attribute("quota", Value(ram.ram_quota()));
xml.attribute("used", Value(ram.used_ram()));
xml.attribute("avail", Value(ram.avail_ram()));
}
+ inline void generate_caps_info(Xml_generator &xml, Pd_session const &pd)
+ {
+ typedef String<32> Value;
+ xml.attribute("quota", Value(pd.cap_quota()));
+ xml.attribute("used", Value(pd.used_caps()));
+ xml.attribute("avail", Value(pd.avail_caps()));
+ }
+
/**
* Read priority-levels declaration from config
*/
diff --git a/repos/os/src/server/loader/child.h b/repos/os/src/server/loader/child.h
index 4e9e573dd..a4a00c03f 100644
--- a/repos/os/src/server/loader/child.h
+++ b/repos/os/src/server/loader/child.h
@@ -45,6 +45,7 @@ class Loader::Child : public Child_policy
Session_label const _label;
Name const _binary_name;
+ Cap_quota const _cap_quota;
Ram_quota const _ram_quota;
Parent_services &_parent_services;
@@ -62,6 +63,7 @@ class Loader::Child : public Child_policy
Allocator &alloc,
Name const &binary_name,
Session_label const &label,
+ Cap_quota cap_quota,
Ram_quota ram_quota,
Parent_services &parent_services,
Service &local_rom_service,
@@ -74,6 +76,7 @@ class Loader::Child : public Child_policy
_alloc(alloc),
_label(label),
_binary_name(binary_name),
+ _cap_quota(Genode::Child::effective_quota(cap_quota)),
_ram_quota(Genode::Child::effective_quota(ram_quota)),
_parent_services(parent_services),
_local_nitpicker_service(local_nitpicker_service),
@@ -94,9 +97,18 @@ class Loader::Child : public Child_policy
Binary_name binary_name() const override { return _binary_name; }
+ Pd_session &ref_pd() override { return _env.pd(); }
+ Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
+
Ram_session &ref_ram() override { return _env.ram(); }
Ram_session_capability ref_ram_cap() const override { return _env.ram_session_cap(); }
+ void init(Pd_session &pd, Pd_session_capability pd_cap) override
+ {
+ pd.ref_account(ref_pd_cap());
+ ref_pd().transfer_quota(pd_cap, _cap_quota);
+ }
+
void init(Ram_session &ram, Ram_session_capability ram_cap) override
{
ram.ref_account(ref_ram_cap());
diff --git a/repos/os/src/server/loader/main.cc b/repos/os/src/server/loader/main.cc
index bbbcd0e8f..1fe5df3e8 100644
--- a/repos/os/src/server/loader/main.cc
+++ b/repos/os/src/server/loader/main.cc
@@ -14,7 +14,6 @@
/* Genode includes */
#include
#include
-#include
#include
#include
#include
@@ -204,9 +203,11 @@ class Loader::Session_component : public Rpc_object
Env &_env;
Session_label const _label;
Xml_node const _config;
+ Cap_quota const _cap_quota;
Ram_quota const _ram_quota;
Ram_session_client_guard _local_ram { _env.ram_session_cap(), _ram_quota };
Heap _md_alloc { _local_ram, _env.rm() };
+ size_t _subsystem_cap_quota_limit = 0;
size_t _subsystem_ram_quota_limit = 0;
Parent_services _parent_services;
Rom_module_registry _rom_modules { _env, _config, _local_ram, _md_alloc };
@@ -243,10 +244,11 @@ class Loader::Session_component : public Rpc_object
/**
* Constructor
*/
- Session_component(Env &env, Session_label const &label,
- Xml_node config, Ram_quota quota)
+ Session_component(Env &env, Session_label const &label, Xml_node config,
+ Cap_quota cap_quota, Ram_quota ram_quota)
:
- _env(env), _label(label), _config(config), _ram_quota(quota)
+ _env(env), _label(label), _config(config),
+ _cap_quota(cap_quota), _ram_quota(ram_quota)
{
/* fetch all parent-provided ROMs according to the config */
config.for_each_sub_node("parent-rom", [&] (Xml_node rom)
@@ -287,6 +289,11 @@ class Loader::Session_component : public Rpc_object
throw Rom_module_does_not_exist(); }
}
+ void cap_quota(Cap_quota caps) override
+ {
+ _subsystem_cap_quota_limit = caps.value;
+ }
+
void ram_quota(Ram_quota quantum) override
{
_subsystem_ram_quota_limit = quantum.value;
@@ -334,6 +341,10 @@ class Loader::Session_component : public Rpc_object
return;
}
+ size_t const cap_quota = (_subsystem_cap_quota_limit > 0)
+ ? min(_subsystem_cap_quota_limit, _cap_quota.value)
+ : _cap_quota.value;
+
size_t const ram_quota = (_subsystem_ram_quota_limit > 0)
? min(_subsystem_ram_quota_limit, _ram_quota.value)
: _ram_quota.value;
@@ -341,7 +352,7 @@ class Loader::Session_component : public Rpc_object
try {
_child.construct(_env, _md_alloc, binary_name.string(),
prefixed_label(_label, Session_label(label.string())),
- Ram_quota{ram_quota},
+ Cap_quota{cap_quota}, Ram_quota{ram_quota},
_parent_services, _rom_service,
_cpu_service, _pd_service, _nitpicker_service,
_fault_sigh);
@@ -381,6 +392,7 @@ class Loader::Root : public Root_component
catch (...) { }
return new (md_alloc()) Session_component(_env, label, session_config,
+ cap_quota_from_args(args),
ram_quota_from_args(args));
}
diff --git a/repos/os/src/test/bomb/main.cc b/repos/os/src/test/bomb/main.cc
index 960733e10..f600da3b2 100644
--- a/repos/os/src/test/bomb/main.cc
+++ b/repos/os/src/test/bomb/main.cc
@@ -32,6 +32,7 @@ class Bomb_child : public Child_policy
Env &_env;
Binary_name const _binary_name;
Name const _label;
+ Cap_quota const _cap_quota;
Ram_quota const _ram_quota;
Registry > &_parent_services;
@@ -45,11 +46,13 @@ class Bomb_child : public Child_policy
Bomb_child(Env &env,
Name const &binary_name,
Name const &label,
+ Cap_quota const cap_quota,
Ram_quota const ram_quota,
Registry > &parent_services,
unsigned generation)
:
_env(env), _binary_name(binary_name), _label(label),
+ _cap_quota(Child::effective_quota(cap_quota)),
_ram_quota(Child::effective_quota(ram_quota)),
_parent_services(parent_services)
{
@@ -68,12 +71,21 @@ class Bomb_child : public Child_policy
Binary_name binary_name() const override { return _binary_name; }
+ void init(Pd_session &pd, Pd_session_capability pd_cap) override
+ {
+ pd.ref_account(_env.pd_session_cap());
+ _env.pd().transfer_quota(pd_cap, _cap_quota);
+ }
+
void init(Ram_session &ram, Ram_session_capability ram_cap) override
{
ram.ref_account(_env.ram_session_cap());
_env.ram().transfer_quota(ram_cap, _ram_quota);
}
+ Pd_session &ref_pd() override { return _env.pd(); }
+ Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
+
Ram_session &ref_ram() override { return _env.ram(); }
Ram_session_capability ref_ram_cap() const override { return _env.ram_session_cap(); }
@@ -154,10 +166,10 @@ struct Bomb
Attached_rom_dataspace config { env, "config" };
unsigned round = 0;
- unsigned const rounds = config.xml().attribute_value("rounds", 1U);
- unsigned const generation = config.xml().attribute_value("generations", 1U);
- unsigned const children = config.xml().attribute_value("children", 2U);
- unsigned const sleeptime = config.xml().attribute_value("sleep", 2000U);
+ unsigned const rounds = config.xml().attribute_value("rounds", 1U);
+ unsigned const generation = config.xml().attribute_value("generations", 1U);
+ unsigned const children = config.xml().attribute_value("children", 2U);
+ unsigned const sleeptime = config.xml().attribute_value("sleep", 2000U);
size_t const ram_demand = config.xml().attribute_value("demand", 1024UL * 1024);
Heap heap { env.ram(), env.rm() };
@@ -177,6 +189,17 @@ struct Bomb
" - not enough memory.");
return;
}
+
+ size_t const avail_caps = env.pd().avail_caps().value;
+ size_t const preserved_caps = children*10;
+
+ if (avail_caps < preserved_caps) {
+ log("I ran out of capabilities.");
+ return;
+ }
+
+ Cap_quota const cap_quota { (avail_caps - preserved_caps) / children };
+
if (generation == 0) {
log("I'm a leaf node - generation 0");
return;
@@ -192,7 +215,7 @@ struct Bomb
unique_child_name(child_registry,
binary_name,
generation - 1),
- ram_amount,
+ cap_quota, ram_amount,
parent_services, generation - 1);
}
diff --git a/repos/os/src/test/dynamic_config/loader/main.cc b/repos/os/src/test/dynamic_config/loader/main.cc
index f2706ae0b..c39cdec09 100644
--- a/repos/os/src/test/dynamic_config/loader/main.cc
+++ b/repos/os/src/test/dynamic_config/loader/main.cc
@@ -24,7 +24,7 @@ struct Main
Env &env;
int counter { -1 };
- Loader::Connection loader { env, Ram_quota{8*1024*1024} };
+ Loader::Connection loader { env, Ram_quota{8*1024*1024}, Cap_quota{100} };
Timer::Connection timer { env };
Signal_handler timer_handler { env.ep(), *this, &Main::handle_timer };
diff --git a/repos/os/src/test/dynamic_config/master/main.cc b/repos/os/src/test/dynamic_config/master/main.cc
index cf351cb7d..a3d8face2 100644
--- a/repos/os/src/test/dynamic_config/master/main.cc
+++ b/repos/os/src/test/dynamic_config/master/main.cc
@@ -36,6 +36,7 @@ struct Test::Policy
Policy(Env &env, Name const &name)
:
Slave::Policy(name, name, *this, env.ep().rpc_ep(), env.rm(),
+ env.pd(), env.pd_session_cap(), Cap_quota{100},
env.ram(), env.ram_session_cap(), Ram_quota{1024*1024})
{ }
};
diff --git a/repos/os/src/test/fault_detection/main.cc b/repos/os/src/test/fault_detection/main.cc
index f5960fd08..12df2ae81 100644
--- a/repos/os/src/test/fault_detection/main.cc
+++ b/repos/os/src/test/fault_detection/main.cc
@@ -70,6 +70,7 @@ class Test_child : public Genode::Child_policy
private:
Env &_env;
+ Cap_quota const _cap_quota { 30 };
Ram_quota const _ram_quota { 1024*1024 };
Binary_name const _binary_name;
Signal_context_capability _sigh;
@@ -101,6 +102,9 @@ class Test_child : public Genode::Child_policy
Binary_name binary_name() const override { return _binary_name; }
+ Pd_session &ref_pd() override { return _env.pd(); }
+ Pd_session_capability ref_pd_cap() const override { return _env.pd_session_cap(); }
+
Ram_session &ref_ram() override { return _env.ram(); }
Ram_session_capability ref_ram_cap() const override { return _env.ram_session_cap(); }
@@ -116,8 +120,11 @@ class Test_child : public Genode::Child_policy
cpu.exception_sigh(_sigh);
}
- void init(Pd_session &pd, Pd_session_capability) override
+ void init(Pd_session &pd, Pd_session_capability pd_cap) override
{
+ pd.ref_account(ref_pd_cap());
+ ref_pd().transfer_quota(pd_cap, _cap_quota);
+
/* register handler for unresolvable page faults */
Region_map_client address_space(pd.address_space());
address_space.fault_handler(_sigh);
@@ -162,7 +169,7 @@ struct Faulting_loader_child_test
void start_iteration(Env &env, Signal_context_capability fault_sigh)
{
- loader.construct(env, Ram_quota{1024*1024});
+ loader.construct(env, Ram_quota{1024*1024}, Cap_quota{100});
/* register fault handler at loader session */
loader->fault_sigh(fault_sigh);
@@ -207,7 +214,7 @@ struct Faulting_loader_grand_child_test
void start_iteration(Env &env, Signal_context_capability fault_sigh)
{
- loader.construct(env, Ram_quota{2*1024*1024});
+ loader.construct(env, Ram_quota{2*1024*1024}, Cap_quota{100});
/* import config into loader session */
{
diff --git a/repos/os/src/test/loader/main.cc b/repos/os/src/test/loader/main.cc
index 1de7a9007..f0c5e3bc0 100644
--- a/repos/os/src/test/loader/main.cc
+++ b/repos/os/src/test/loader/main.cc
@@ -25,7 +25,7 @@ struct Test::Main
{
Env &_env;
- Loader::Connection _loader { _env, Ram_quota{8*1024*1024} };
+ Loader::Connection _loader { _env, Ram_quota{8*1024*1024}, Cap_quota{100} };
Timer::Connection _timer { _env };
Loader::Area _size;
diff --git a/repos/os/src/test/resource_request/main.cc b/repos/os/src/test/resource_request/main.cc
index 7ebf56d35..14f2be577 100644
--- a/repos/os/src/test/resource_request/main.cc
+++ b/repos/os/src/test/resource_request/main.cc
@@ -70,6 +70,7 @@ struct Test::Monitor
xml.node("start", [&] () {
xml.attribute("name", "test-resource_request");
+ xml.attribute("caps", 3000);
xml.node("resource", [&] () {
xml.attribute("name", "RAM");
xml.attribute("quantum", _ram_quota);
diff --git a/repos/os/src/test/resource_yield/main.cc b/repos/os/src/test/resource_yield/main.cc
index 9f6b6ab2f..bf9e99243 100644
--- a/repos/os/src/test/resource_yield/main.cc
+++ b/repos/os/src/test/resource_yield/main.cc
@@ -285,7 +285,7 @@ class Test::Parent
{
Parent &_parent;
- enum { SLAVE_QUOTA = 10*1024*1024 };
+ enum { SLAVE_CAPS = 50, SLAVE_RAM = 10*1024*1024 };
void yield_response() override
{
@@ -296,7 +296,8 @@ class Test::Parent
:
Slave::Policy(Label("child"), "test-resource_yield",
*this, env.ep().rpc_ep(), env.rm(),
- env.ram(), env.ram_session_cap(), Ram_quota{SLAVE_QUOTA}),
+ env.pd(), env.pd_session_cap(), Cap_quota{SLAVE_CAPS},
+ env.ram(), env.ram_session_cap(), Ram_quota{SLAVE_RAM}),
_parent(parent)
{
configure("");
diff --git a/repos/ports/src/app/gdb_monitor/app_child.h b/repos/ports/src/app/gdb_monitor/app_child.h
index cd97f2c93..865ad9605 100644
--- a/repos/ports/src/app/gdb_monitor/app_child.h
+++ b/repos/ports/src/app/gdb_monitor/app_child.h
@@ -50,8 +50,11 @@ class Gdb_monitor::App_child : public Child_policy
Allocator &_alloc;
+ Pd_session_capability _ref_pd_cap { _env.pd_session_cap() };
+ Pd_session &_ref_pd { _env.pd() };
+
Ram_session_capability _ref_ram_cap { _env.ram_session_cap() };
- Ram_session_client _ref_ram { _ref_ram_cap };
+ Ram_session &_ref_ram { _env.ram() };
const char *_unique_name;
@@ -60,6 +63,7 @@ class Gdb_monitor::App_child : public Child_policy
Region_map &_rm;
Ram_quota _ram_quota;
+ Cap_quota _cap_quota;
Rpc_entrypoint _entrypoint;
@@ -112,6 +116,7 @@ class Gdb_monitor::App_child : public Child_policy
Allocator &alloc,
char const *unique_name,
Ram_quota ram_quota,
+ Cap_quota cap_quota,
Signal_receiver &signal_receiver,
Xml_node target_node)
:
@@ -119,7 +124,7 @@ class Gdb_monitor::App_child : public Child_policy
_alloc(alloc),
_unique_name(unique_name),
_rm(_env.rm()),
- _ram_quota(ram_quota),
+ _ram_quota(ram_quota), _cap_quota(cap_quota),
_entrypoint(&_env.pd(), STACK_SIZE, "GDB monitor entrypoint"),
_child_config(env.ram(), _rm, target_node),
_config_policy("config", _child_config.dataspace(), &_entrypoint),
@@ -155,6 +160,10 @@ class Gdb_monitor::App_child : public Child_policy
Name name() const override { return _unique_name; }
+ Pd_session &ref_pd() override { return _ref_pd; }
+
+ Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; }
+
Ram_session &ref_ram() override { return _ref_ram; }
Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
@@ -166,6 +175,13 @@ class Gdb_monitor::App_child : public Child_policy
_ref_ram.transfer_quota(cap, _ram_quota);
}
+ void init(Pd_session &session,
+ Pd_session_capability cap) override
+ {
+ session.ref_account(_ref_pd_cap);
+ _ref_pd.transfer_quota(cap, _cap_quota);
+ }
+
Service &resolve_session_request(Service::Name const &service_name,
Session_state::Args const &args) override
{
diff --git a/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc b/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc
index a1154a5a7..79ac2e357 100644
--- a/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc
+++ b/repos/ports/src/app/gdb_monitor/gdbserver/genode-low.cc
@@ -469,6 +469,17 @@ extern "C" int fork()
Number_of_bytes ram_quota = genode_env->ram().avail_ram().value - preserved_ram_quota;
+ Cap_quota const avail_cap_quota = genode_env->pd().avail_caps();
+
+ Genode::size_t const preserved_caps = 100;
+
+ if (avail_cap_quota.value < preserved_caps) {
+ error("not enough available caps for preservation of ", preserved_caps);
+ return -1;
+ }
+
+ Cap_quota const cap_quota { avail_cap_quota.value - preserved_caps };
+
/* start the application */
static Heap alloc(genode_env->ram(), genode_env->rm());
@@ -483,6 +494,7 @@ extern "C" int fork()
alloc,
filename,
Ram_quota{ram_quota},
+ cap_quota,
signal_receiver,
target_node);
diff --git a/repos/ports/src/app/gdb_monitor/pd_session_component.h b/repos/ports/src/app/gdb_monitor/pd_session_component.h
index 9d9ab86f4..9b0130547 100644
--- a/repos/ports/src/app/gdb_monitor/pd_session_component.h
+++ b/repos/ports/src/app/gdb_monitor/pd_session_component.h
@@ -116,6 +116,15 @@ class Gdb_monitor::Pd_session_component : public Rpc_object
Capability linker_area() override {
return _linker_area.Rpc_object::cap(); }
+ void ref_account(Capability pd) override {
+ warning("Pd_session::ref_account not implemented"); }
+
+ void transfer_quota(Capability pd, Cap_quota amount) override {
+ warning("Pd_session::transfer_quota not implemented"); }
+
+ Cap_quota cap_quota() const { return _pd.cap_quota(); }
+ Cap_quota used_caps() const { return _pd.used_caps(); }
+
Capability native_pd() override {
return _pd.native_pd(); }
};
diff --git a/repos/ports/src/noux/child.h b/repos/ports/src/noux/child.h
index e63b02092..f54beb522 100644
--- a/repos/ports/src/noux/child.h
+++ b/repos/ports/src/noux/child.h
@@ -143,6 +143,9 @@ class Noux::Child : public Rpc_object,
enum { STACK_SIZE = 8*1024*sizeof(long) };
Rpc_entrypoint _ep { &_env.pd(), STACK_SIZE, "noux_process", false };
+ Pd_session &_ref_pd;
+ Pd_session_capability const _ref_pd_cap;
+
Ram_session &_ref_ram;
Ram_session_capability const _ref_ram_cap;
@@ -334,6 +337,8 @@ class Noux::Child : public Rpc_object,
Args const &args,
Sysio::Env const &sysio_env,
Allocator &heap,
+ Pd_session &ref_pd,
+ Pd_session_capability ref_pd_cap,
Ram_session &ref_ram,
Ram_session_capability ref_ram_cap,
Parent_services &parent_services,
@@ -354,6 +359,7 @@ class Noux::Child : public Rpc_object,
_root_dir(root_dir),
_destruct_queue(destruct_queue),
_heap(heap),
+ _ref_pd (ref_pd), _ref_pd_cap (ref_pd_cap),
_ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap),
_args(ref_ram, _env.rm(), ARGS_DS_SIZE, args),
_sysio_env(_ref_ram, _env.rm(), sysio_env),
@@ -368,7 +374,8 @@ class Noux::Child : public Rpc_object,
_noux_service, _empty_rom_service,
_rom_service, _parent_services,
*this, parent_exit, *this, _destruct_handler,
- ref_ram, ref_ram_cap, _verbose.enabled()),
+ ref_pd, ref_pd_cap, ref_ram, ref_ram_cap,
+ _verbose.enabled()),
_child(_env.rm(), _ep, _child_policy)
{
if (_verbose.enabled())
@@ -534,6 +541,7 @@ class Noux::Child : public Rpc_object,
args,
env,
_heap,
+ _ref_pd, _ref_pd_cap,
_ref_ram, _ref_ram_cap,
_parent_services,
false,
diff --git a/repos/ports/src/noux/child_policy.h b/repos/ports/src/noux/child_policy.h
index a87f79dec..7615d2812 100644
--- a/repos/ports/src/noux/child_policy.h
+++ b/repos/ports/src/noux/child_policy.h
@@ -58,6 +58,8 @@ class Noux::Child_policy : public Genode::Child_policy
Parent_exit *_parent_exit;
File_descriptor_registry &_file_descriptor_registry;
Signal_context_capability _destruct_context_cap;
+ Pd_session &_ref_pd;
+ Pd_session_capability _ref_pd_cap;
Ram_session &_ref_ram;
Ram_session_capability _ref_ram_cap;
int _exit_value;
@@ -93,6 +95,8 @@ class Noux::Child_policy : public Genode::Child_policy
Parent_exit *parent_exit,
File_descriptor_registry &file_descriptor_registry,
Signal_context_capability destruct_context_cap,
+ Pd_session &ref_pd,
+ Pd_session_capability ref_pd_cap,
Ram_session &ref_ram,
Ram_session_capability ref_ram_cap,
bool verbose)
@@ -109,6 +113,7 @@ class Noux::Child_policy : public Genode::Child_policy
_parent_exit(parent_exit),
_file_descriptor_registry(file_descriptor_registry),
_destruct_context_cap(destruct_context_cap),
+ _ref_pd (ref_pd), _ref_pd_cap (ref_pd_cap),
_ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap),
_exit_value(~0),
_verbose(verbose)
@@ -122,8 +127,10 @@ class Noux::Child_policy : public Genode::Child_policy
Name name() const override { return _name; }
- Ram_session &ref_ram() override { return _ref_ram; }
+ Pd_session &ref_pd() override { return _ref_pd; }
+ Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; }
+ Ram_session &ref_ram() override { return _ref_ram; }
Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
void init(Ram_session &session, Ram_session_capability cap) override
diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc
index db9042cb5..0e24098c3 100644
--- a/repos/ports/src/noux/main.cc
+++ b/repos/ports/src/noux/main.cc
@@ -272,6 +272,8 @@ struct Noux::Main
_args_of_init_process(),
env_string_of_init_process(_config.xml()),
_heap,
+ _env.pd(),
+ _env.pd_session_cap(),
_ref_ram,
Ram_session_capability(),
_parent_services,
diff --git a/repos/ports/src/noux/pd_session_component.h b/repos/ports/src/noux/pd_session_component.h
index 2f850e0b4..43631201a 100644
--- a/repos/ports/src/noux/pd_session_component.h
+++ b/repos/ports/src/noux/pd_session_component.h
@@ -33,10 +33,23 @@ class Noux::Pd_session_component : public Rpc_object
Pd_connection _pd;
+ Pd_session &_ref_pd;
+
Region_map_component _address_space;
Region_map_component _stack_area;
Region_map_component _linker_area;
+ template
+ auto _with_automatic_cap_upgrade(FUNC func) -> decltype(func())
+ {
+ Cap_quota upgrade { 10 };
+ enum { NUM_ATTEMPTS = 3 };
+ return retry(
+ [&] () { return func(); },
+ [&] () { _ref_pd.transfer_quota(_pd, upgrade); },
+ NUM_ATTEMPTS);
+ }
+
public:
/**
@@ -46,12 +59,20 @@ class Noux::Pd_session_component : public Rpc_object
Child_policy::Name const &name,
Dataspace_registry &ds_registry)
:
- _ep(ep), _pd(env, name.string()),
+ _ep(ep), _pd(env, name.string()), _ref_pd(env.pd()),
_address_space(alloc, _ep, ds_registry, _pd, _pd.address_space()),
_stack_area (alloc, _ep, ds_registry, _pd, _pd.stack_area()),
_linker_area (alloc, _ep, ds_registry, _pd, _pd.linker_area())
{
_ep.manage(this);
+
+ /*
+ * Equip the PD with an initial cap quota that suffices in the
+ * common case. Further capabilities are provisioned on demand
+ * via '_with_automatic_cap_upgrade'.
+ */
+ _pd.ref_account(env.pd_session_cap());
+ _ref_pd.transfer_quota(_pd, Cap_quota{10});
}
~Pd_session_component()
@@ -115,15 +136,21 @@ class Noux::Pd_session_component : public Rpc_object
bool assign_pci(addr_t addr, uint16_t bdf) override {
return _pd.assign_pci(addr, bdf); }
- Signal_source_capability alloc_signal_source() override {
- return _pd.alloc_signal_source(); }
+ Signal_source_capability alloc_signal_source() override
+ {
+ return _with_automatic_cap_upgrade([&] () {
+ return _pd.alloc_signal_source(); });
+ }
void free_signal_source(Signal_source_capability cap) override {
_pd.free_signal_source(cap); }
Capability alloc_context(Signal_source_capability source,
- unsigned long imprint) override {
- return _pd.alloc_context(source, imprint); }
+ unsigned long imprint) override
+ {
+ return _with_automatic_cap_upgrade([&] () {
+ return _pd.alloc_context(source, imprint); });
+ }
void free_context(Capability cap) override {
_pd.free_context(cap); }
@@ -131,8 +158,11 @@ class Noux::Pd_session_component : public Rpc_object
void submit(Capability context, unsigned cnt) override {
_pd.submit(context, cnt); }
- Native_capability alloc_rpc_cap(Native_capability ep) override {
- return _pd.alloc_rpc_cap(ep); }
+ Native_capability alloc_rpc_cap(Native_capability ep) override
+ {
+ return _with_automatic_cap_upgrade([&] () {
+ return _pd.alloc_rpc_cap(ep); });
+ }
void free_rpc_cap(Native_capability cap) override {
_pd.free_rpc_cap(cap); }
@@ -146,6 +176,13 @@ class Noux::Pd_session_component : public Rpc_object
Capability linker_area() override {
return _linker_area.Rpc_object::cap(); }
+ void ref_account(Capability pd) override { }
+
+ void transfer_quota(Capability pd, Cap_quota amount) override { }
+
+ Cap_quota cap_quota() const { return _pd.cap_quota(); }
+ Cap_quota used_caps() const { return _pd.used_caps(); }
+
Capability native_pd() override {
return _pd.native_pd(); }
};
diff --git a/repos/ports/src/noux/syscall.cc b/repos/ports/src/noux/syscall.cc
index 8812eb55e..83467a801 100644
--- a/repos/ports/src/noux/syscall.cc
+++ b/repos/ports/src/noux/syscall.cc
@@ -498,6 +498,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
_args,
_sysio_env.env(),
_heap,
+ _ref_pd, _ref_pd_cap,
_ref_ram, _ref_ram_cap,
_parent_services,
true,