Remove Pd_session::Invalid_signal_source exception

While changing 'Pd_session::alloc_context', this patch also tightens the
type of the imprint argument.

Issue #5245
This commit is contained in:
Norman Feske 2024-06-12 18:06:45 +02:00
parent a52c2ce141
commit 8a0689d832
7 changed files with 84 additions and 43 deletions

View File

@ -17,6 +17,7 @@
#include <base/signal.h>
#include <base/env.h>
#include <base/trace/events.h>
#include <base/sleep.h>
/* base-internal includes */
#include <base/internal/native_thread.h>
@ -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;
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<Signal_context> cap) {
c->_cap = cap;
c->_receiver = &this_receiver;
_contexts.insert_as_tail(c);
return c->_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;
}
catch (Out_of_ram) { ram_upgrade = Ram_quota { 1024*sizeof(long) }; }
catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
});
if (c->_cap.valid())
return c->_cap;
env().upgrade(Parent::Env::pd(),
String<100>("ram_quota=", ram_upgrade, ", "

View File

@ -39,8 +39,8 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
void free_signal_source(Signal_source_capability cap) override {
call<Rpc_free_signal_source>(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<Rpc_alloc_context>(source, imprint); }
void free_context(Signal_context_capability cap) override {

View File

@ -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<Capability<Signal_context>, 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<Signal_context>
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<Signal_context>, 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<Signal_context>);
GENODE_RPC(Rpc_submit, void, submit, Capability<Signal_context>, unsigned);

View File

@ -223,21 +223,24 @@ class Core::Pd_session_component : public Session_object<Pd_session>
}
}
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

View File

@ -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<Signal_context> 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;
}
catch (Out_of_ram) { ram_upgrade = Ram_quota { 1024*sizeof(long) }; }
catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; }
});
if (context._cap.valid())
break;
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;
}

View File

@ -207,8 +207,8 @@ struct Monitor::Inferior_pd : Monitored_pd_session
void free_signal_source(Signal_source_capability cap) override {
_real.call<Rpc_free_signal_source>(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<Rpc_alloc_context>(source, imprint); }
void free_context(Signal_context_capability cap) override {

View File

@ -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__); };