diff --git a/repos/base-hw/src/lib/base/signal_receiver.cc b/repos/base-hw/src/lib/base/signal_receiver.cc
index bb3415deda..83595c7c87 100644
--- a/repos/base-hw/src/lib/base/signal_receiver.cc
+++ b/repos/base-hw/src/lib/base/signal_receiver.cc
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
/* base-internal includes */
#include
@@ -104,20 +105,41 @@ Signal_context_capability Signal_receiver::manage(Signal_context * const c)
if (c->_receiver)
throw Context_already_in_use();
+ Signal_receiver &this_receiver = *this;
+
for (;;) {
Ram_quota ram_upgrade { 0 };
Cap_quota cap_upgrade { 0 };
- try {
- /* use signal context as imprint */
- c->_cap = env().pd().alloc_context(_cap, (unsigned long)c);
- c->_receiver = this;
- _contexts.insert_as_tail(c);
+ using Error = Pd_session::Alloc_context_error;
+
+ /* use pointer to signal context as imprint */
+ Pd_session::Imprint const imprint { addr_t(c) };
+
+ _pd.alloc_context(_cap, imprint).with_result(
+ [&] (Capability cap) {
+ c->_cap = cap;
+ c->_receiver = &this_receiver;
+ _contexts.insert_as_tail(c);
+ },
+ [&] (Error e) {
+ switch (e) {
+ case Error::OUT_OF_RAM:
+ ram_upgrade = Ram_quota { 1024*sizeof(long) };
+ break;
+ case Error::OUT_OF_CAPS:
+ cap_upgrade = Cap_quota { 4 };
+ break;
+ case Error::INVALID_SIGNAL_SOURCE:
+ error("ill-attempt to create context for invalid signal source");
+ sleep_forever();
+ break;
+ }
+ });
+
+ if (c->_cap.valid())
return c->_cap;
- }
- catch (Out_of_ram) { ram_upgrade = Ram_quota { 1024*sizeof(long) }; }
- catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
env().upgrade(Parent::Env::pd(),
String<100>("ram_quota=", ram_upgrade, ", "
diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h
index bd6a9608cf..70a8006409 100644
--- a/repos/base/include/pd_session/client.h
+++ b/repos/base/include/pd_session/client.h
@@ -39,8 +39,8 @@ struct Genode::Pd_session_client : Rpc_client
void free_signal_source(Signal_source_capability cap) override {
call(cap); }
- Signal_context_capability alloc_context(Signal_source_capability source,
- unsigned long imprint) override {
+ Alloc_context_result alloc_context(Signal_source_capability source,
+ Imprint imprint) override {
return call(source, imprint); }
void free_context(Signal_context_capability cap) override {
diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h
index bb1a02d560..8b16b6f725 100644
--- a/repos/base/include/pd_session/pd_session.h
+++ b/repos/base/include/pd_session/pd_session.h
@@ -94,7 +94,6 @@ struct Genode::Pd_session : Session, Ram_allocator
class Invalid_session : public Exception { };
class Undefined_ref_account : public Exception { };
- class Invalid_signal_source : public Exception { };
/**
* Create a new signal source
@@ -115,22 +114,22 @@ struct Genode::Pd_session : Session, Ram_allocator
*/
virtual void free_signal_source(Signal_source_capability cap) = 0;
+ enum class Alloc_context_error { OUT_OF_RAM, OUT_OF_CAPS, INVALID_SIGNAL_SOURCE };
+ using Alloc_context_result = Attempt, Alloc_context_error>;
+
+ struct Imprint { addr_t value; };
+
/**
* Allocate signal context
*
* \param source signal source that shall provide the new context
*
- *
* \param imprint opaque value that gets delivered with signals
* originating from the allocated signal-context capability
* \return new signal-context capability
- *
- * \throw Out_of_ram
- * \throw Out_of_caps
- * \throw Invalid_signal_source
*/
- virtual Capability
- alloc_context(Signal_source_capability source, unsigned long imprint) = 0;
+ virtual Alloc_context_result alloc_context(Signal_source_capability source,
+ Imprint imprint) = 0;
/**
* Free signal-context
@@ -373,9 +372,8 @@ struct Genode::Pd_session : Session, Ram_allocator
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_ram, Out_of_caps, Invalid_signal_source),
- Signal_source_capability, unsigned long);
+ GENODE_RPC(Rpc_alloc_context, Alloc_context_result, alloc_context,
+ Signal_source_capability, Imprint);
GENODE_RPC(Rpc_free_context, void, free_context,
Capability);
GENODE_RPC(Rpc_submit, void, submit, Capability, unsigned);
diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h
index d8c2d5d06b..58a5821dd8 100644
--- a/repos/base/src/core/include/pd_session_component.h
+++ b/repos/base/src/core/include/pd_session_component.h
@@ -223,21 +223,24 @@ class Core::Pd_session_component : public Session_object
}
}
- Signal_context_capability
- alloc_context(Signal_source_capability sig_rec_cap, unsigned long imprint) override
+ Alloc_context_result
+ alloc_context(Signal_source_capability sig_rec_cap, Imprint imprint) override
{
- Cap_quota_guard::Reservation cap_costs(_cap_quota_guard(), Cap_quota{1});
try {
- /* may throw 'Out_of_ram' or 'Invalid_signal_source' */
+ Cap_quota_guard::Reservation cap_costs(_cap_quota_guard(), Cap_quota{1});
+
+ /* may throw 'Out_of_ram', 'Out_of_caps', or 'Invalid_signal_source' */
Signal_context_capability cap =
- _signal_broker.alloc_context(sig_rec_cap, imprint);
+ _signal_broker.alloc_context(sig_rec_cap, imprint.value);
cap_costs.acknowledge();
diag("consumed signal-context cap (", _cap_account, ")");
return cap;
}
catch (Signal_broker::Invalid_signal_source) {
- throw Pd_session::Invalid_signal_source(); }
+ return Alloc_context_error::INVALID_SIGNAL_SOURCE; }
+ catch (Out_of_ram) { return Alloc_context_error::OUT_OF_RAM; }
+ catch (Out_of_caps) { return Alloc_context_error::OUT_OF_CAPS; }
}
void free_context(Signal_context_capability cap) override
diff --git a/repos/base/src/lib/base/signal.cc b/repos/base/src/lib/base/signal.cc
index 57ab8e75b0..7b8e6f4230 100644
--- a/repos/base/src/lib/base/signal.cc
+++ b/repos/base/src/lib/base/signal.cc
@@ -214,33 +214,52 @@ Signal_receiver::Signal_receiver() : _pd(*_pd_ptr)
}
-Signal_context_capability Signal_receiver::manage(Signal_context *context)
+Signal_context_capability Signal_receiver::manage(Signal_context *context_ptr)
{
- if (context->_receiver)
+ Signal_context &context = *context_ptr;
+
+ if (context._receiver)
throw Context_already_in_use();
- context->_receiver = this;
+ context._receiver = this;
Mutex::Guard contexts_guard(_contexts_mutex);
/* insert context into context list */
- _contexts.insert_as_tail(context);
+ _contexts.insert_as_tail(&context);
/* register context at process-wide registry */
- signal_context_registry()->insert(&context->_registry_le);
+ signal_context_registry()->insert(&context._registry_le);
for (;;) {
Ram_quota ram_upgrade { 0 };
Cap_quota cap_upgrade { 0 };
- try {
- /* use signal context as imprint */
- context->_cap = _pd.alloc_context(_cap, (long)context);
+ using Error = Pd_session::Alloc_context_error;
+
+ /* use pointer to signal context as imprint */
+ Pd_session::Imprint const imprint { addr_t(&context) };
+
+ _pd.alloc_context(_cap, imprint).with_result(
+ [&] (Capability cap) { context._cap = cap; },
+ [&] (Error e) {
+ switch (e) {
+ case Error::OUT_OF_RAM:
+ ram_upgrade = Ram_quota { 1024*sizeof(long) };
+ break;
+ case Error::OUT_OF_CAPS:
+ cap_upgrade = Cap_quota { 4 };
+ break;
+ case Error::INVALID_SIGNAL_SOURCE:
+ error("ill-attempt to create context for invalid signal source");
+ sleep_forever();
+ break;
+ }
+ });
+
+ if (context._cap.valid())
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)");
@@ -249,8 +268,7 @@ Signal_context_capability Signal_receiver::manage(Signal_context *context)
String<100>("ram_quota=", ram_upgrade, ", "
"cap_quota=", cap_upgrade).string());
}
-
- return context->_cap;
+ return context._cap;
}
diff --git a/repos/os/src/monitor/inferior_pd.h b/repos/os/src/monitor/inferior_pd.h
index b3d6056d5b..3e25315082 100644
--- a/repos/os/src/monitor/inferior_pd.h
+++ b/repos/os/src/monitor/inferior_pd.h
@@ -207,8 +207,8 @@ struct Monitor::Inferior_pd : Monitored_pd_session
void free_signal_source(Signal_source_capability cap) override {
_real.call(cap); }
- Signal_context_capability alloc_context(Signal_source_capability source,
- unsigned long imprint) override {
+ Alloc_context_result alloc_context(Signal_source_capability source,
+ Imprint imprint) override {
return _real.call(source, imprint); }
void free_context(Signal_context_capability cap) override {
diff --git a/repos/os/src/monitor/pd_intrinsics.h b/repos/os/src/monitor/pd_intrinsics.h
index 9dfaceb63a..e75d516e6f 100644
--- a/repos/os/src/monitor/pd_intrinsics.h
+++ b/repos/os/src/monitor/pd_intrinsics.h
@@ -46,7 +46,7 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics
void map(addr_t, addr_t) override { never_called(__func__); };
Sig_src_cap alloc_signal_source() override { never_called(__func__); };
void free_signal_source(Sig_src_cap) override { never_called(__func__); };
- Sig_ctx_cap alloc_context(Sig_src_cap, unsigned long) override { never_called(__func__); };
+ Alloc_context_result alloc_context(Sig_src_cap, Imprint) override { never_called(__func__); };
void free_context(Sig_ctx_cap) override { never_called(__func__); };
void submit(Sig_ctx_cap, unsigned) override { never_called(__func__); };
Native_capability alloc_rpc_cap(Native_capability) override { never_called(__func__); };