mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-13 22:23:45 +00:00
core: remove exception from Trace::Control alloc
This patch models the 'Trace::Control_area' as an allocator of slots using the new 'Allocation' utility and thereby removes the former exception-based error propagation. Issue #5245
This commit is contained in:
parent
b4a746bc89
commit
08010003e3
@ -62,32 +62,8 @@ class Core::Vm_session_component
|
||||
Session_label const &_label;
|
||||
addr_t const _pd_sel;
|
||||
|
||||
struct Trace_control_slot
|
||||
{
|
||||
unsigned index = 0;
|
||||
Trace::Control_area &_trace_control_area;
|
||||
|
||||
Trace_control_slot(Trace::Control_area &trace_control_area)
|
||||
: _trace_control_area(trace_control_area)
|
||||
{
|
||||
if (!_trace_control_area.alloc(index))
|
||||
throw Out_of_ram();
|
||||
}
|
||||
|
||||
~Trace_control_slot()
|
||||
{
|
||||
_trace_control_area.free(index);
|
||||
}
|
||||
|
||||
Trace::Control &control()
|
||||
{
|
||||
return *_trace_control_area.at(index);
|
||||
}
|
||||
};
|
||||
|
||||
Trace_control_slot _trace_control_slot;
|
||||
|
||||
Trace::Source _trace_source { *this, _trace_control_slot.control() };
|
||||
Trace::Control_area::Result _trace_control_slot;
|
||||
Constructible<Trace::Source> _trace_source { };
|
||||
|
||||
public:
|
||||
|
||||
|
@ -162,7 +162,7 @@ Vm_session_component::Vcpu::Vcpu(Rpc_entrypoint &ep,
|
||||
_priority(priority),
|
||||
_label(label),
|
||||
_pd_sel(pd_sel),
|
||||
_trace_control_slot(trace_control_area)
|
||||
_trace_control_slot(trace_control_area.alloc())
|
||||
{
|
||||
/* account caps required to setup vCPU */
|
||||
Cap_quota_guard::Reservation caps(_cap_alloc, Cap_quota{CAP_RANGE});
|
||||
@ -220,7 +220,12 @@ Vm_session_component::Vcpu::Vcpu(Rpc_entrypoint &ep,
|
||||
|
||||
_ep.manage(this);
|
||||
|
||||
_trace_sources.insert(&_trace_source);
|
||||
trace_control_area.with_control(_trace_control_slot,
|
||||
[&] (Trace::Control &control) {
|
||||
_trace_source.construct(*this, control);
|
||||
Trace::Source &source = *_trace_source;
|
||||
_trace_sources.insert(&source);
|
||||
});
|
||||
|
||||
caps.acknowledge();
|
||||
}
|
||||
@ -230,7 +235,10 @@ Vm_session_component::Vcpu::~Vcpu()
|
||||
{
|
||||
_ep.dissolve(this);
|
||||
|
||||
_trace_sources.remove(&_trace_source);
|
||||
if (_trace_source.constructed()) {
|
||||
Trace::Source &source = *_trace_source;
|
||||
_trace_sources.remove(&source);
|
||||
}
|
||||
|
||||
if (_sel_sm_ec_sc != invalid_sel()) {
|
||||
_cap_alloc.replenish(Cap_quota{CAP_RANGE});
|
||||
|
@ -274,6 +274,9 @@ Cpu_session_component::Cpu_session_component(Rpc_entrypoint &session_ep,
|
||||
_quota(quota), _ref(0),
|
||||
_native_cpu(*this, args)
|
||||
{
|
||||
if (!_trace_control_area.valid())
|
||||
raise(_trace_control_area.error);
|
||||
|
||||
Arg a = Arg_string::find_arg(args, "priority");
|
||||
if (a.valid()) {
|
||||
_priority = (unsigned)a.ulong_value(0);
|
||||
|
@ -93,18 +93,24 @@ void Cpu_thread_component::affinity(Affinity::Location location)
|
||||
|
||||
unsigned Cpu_thread_component::trace_control_index()
|
||||
{
|
||||
return _trace_control_slot.index;
|
||||
return _trace_control_slot.convert<unsigned>(
|
||||
[&] (Trace::Control_area::Slot const &slot) { return slot.index; },
|
||||
[&] (Trace::Control_area::Error) { return 0u; });
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_thread_component::trace_buffer()
|
||||
{
|
||||
return _trace_source.buffer();
|
||||
if (!_trace_source.constructed())
|
||||
return { };
|
||||
return _trace_source->buffer();
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_thread_component::trace_policy()
|
||||
{
|
||||
return _trace_source.policy();
|
||||
if (!_trace_source.constructed())
|
||||
return { };
|
||||
return _trace_source->policy();
|
||||
}
|
||||
|
||||
|
@ -69,32 +69,9 @@ class Core::Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
*/
|
||||
Signal_context_capability _thread_sigh { };
|
||||
|
||||
struct Trace_control_slot
|
||||
{
|
||||
unsigned index = 0;
|
||||
Trace::Control_area &trace_control_area;
|
||||
Trace::Control_area::Result _trace_control_slot;
|
||||
|
||||
Trace_control_slot(Trace::Control_area &trace_control_area)
|
||||
: trace_control_area(trace_control_area)
|
||||
{
|
||||
if (!trace_control_area.alloc(index))
|
||||
throw Out_of_ram();
|
||||
}
|
||||
|
||||
~Trace_control_slot()
|
||||
{
|
||||
trace_control_area.free(index);
|
||||
}
|
||||
|
||||
Trace::Control &control()
|
||||
{
|
||||
return *trace_control_area.at(index);
|
||||
}
|
||||
};
|
||||
|
||||
Trace_control_slot _trace_control_slot;
|
||||
|
||||
Trace::Source _trace_source { *this, _trace_control_slot.control() };
|
||||
Constructible<Trace::Source> _trace_source { };
|
||||
|
||||
Trace::Source_registry &_trace_sources;
|
||||
|
||||
@ -164,7 +141,7 @@ class Core::Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
_pd_element(pd_threads, *this),
|
||||
_platform_thread(platform_pd, ep, cpu_ram, core_rm, quota, name.string(),
|
||||
priority, location, utcb),
|
||||
_trace_control_slot(trace_control_area),
|
||||
_trace_control_slot(trace_control_area.alloc()),
|
||||
_trace_sources(trace_sources),
|
||||
_managed_thread_cap(_ep, *this),
|
||||
_rm_client(cpu_session_cap, _managed_thread_cap.cap(),
|
||||
@ -177,12 +154,20 @@ class Core::Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
|
||||
_address_space_region_map.add_client(_rm_client);
|
||||
_platform_thread.pager(_rm_client);
|
||||
_trace_sources.insert(&_trace_source);
|
||||
trace_control_area.with_control(_trace_control_slot,
|
||||
[&] (Trace::Control &control) {
|
||||
_trace_source.construct(*this, control);
|
||||
Trace::Source &source = *_trace_source;
|
||||
_trace_sources.insert(&source);
|
||||
});
|
||||
}
|
||||
|
||||
~Cpu_thread_component()
|
||||
{
|
||||
_trace_sources.remove(&_trace_source);
|
||||
if (_trace_source.constructed()) {
|
||||
Trace::Source &source = *_trace_source;
|
||||
_trace_sources.remove(&source);
|
||||
}
|
||||
_pager_ep.dissolve(_rm_client);
|
||||
|
||||
_address_space_region_map.remove_client(_rm_client);
|
||||
|
@ -24,67 +24,79 @@
|
||||
namespace Genode { namespace Trace { class Control_area; } }
|
||||
|
||||
|
||||
class Genode::Trace::Control_area
|
||||
struct Genode::Trace::Control_area : Noncopyable
|
||||
{
|
||||
public:
|
||||
enum { SIZE = 8192 };
|
||||
|
||||
enum { SIZE = 8192 };
|
||||
Alloc_error error = Alloc_error::DENIED;
|
||||
Constructible<Attached_ram_dataspace> _area { };
|
||||
|
||||
private:
|
||||
bool _index_valid(unsigned const index) const {
|
||||
return index < SIZE / sizeof(Control); }
|
||||
|
||||
Ram_allocator &_ram;
|
||||
Region_map &_rm;
|
||||
Attached_ram_dataspace const _area;
|
||||
auto _with_control_at_index(unsigned i, auto const &fn,
|
||||
auto const &missing_fn) const
|
||||
-> decltype(missing_fn())
|
||||
{
|
||||
if (!_area.constructed() || !_index_valid(i))
|
||||
return missing_fn();
|
||||
|
||||
bool _index_valid(unsigned const index) const {
|
||||
return index < SIZE / sizeof(Trace::Control); }
|
||||
return fn(_area->local_addr<Control>()[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Control_area(Control_area const &);
|
||||
Control_area &operator = (Control_area const &);
|
||||
Control_area(Ram_allocator &ram, Region_map &rm)
|
||||
{
|
||||
try { _area.construct(ram, rm, SIZE); }
|
||||
catch (Out_of_ram) { error = Alloc_error::OUT_OF_RAM; }
|
||||
catch (Out_of_caps) { error = Alloc_error::OUT_OF_CAPS; }
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
Trace::Control * _local_base() const {
|
||||
return _area.local_addr<Trace::Control>(); }
|
||||
~Control_area() { }
|
||||
|
||||
public:
|
||||
bool valid() const { return _area.constructed(); }
|
||||
|
||||
Control_area(Ram_allocator &ram, Region_map &rm)
|
||||
:
|
||||
_ram(ram), _rm(rm), _area(ram, rm, SIZE)
|
||||
{ }
|
||||
Ram::Capability dataspace() const
|
||||
{
|
||||
return _area.constructed() ? _area->cap() : Ram::Capability();
|
||||
}
|
||||
|
||||
~Control_area() { }
|
||||
struct Attr { unsigned index; };
|
||||
|
||||
Dataspace_capability dataspace() const { return _area.cap(); }
|
||||
using Error = Denied;
|
||||
using Slot = Allocation<Control_area>;
|
||||
using Result = Slot::Attempt;
|
||||
|
||||
bool alloc(unsigned &index_out)
|
||||
Result alloc()
|
||||
{
|
||||
auto try_alloc = [&] (Control &control)
|
||||
{
|
||||
for (unsigned index = 0; _index_valid(index); index++) {
|
||||
if (!_local_base()[index].is_free()) {
|
||||
continue;
|
||||
}
|
||||
if (!control.is_free())
|
||||
return false;
|
||||
control.alloc();
|
||||
return true;
|
||||
};
|
||||
|
||||
_local_base()[index].alloc();
|
||||
index_out = index;
|
||||
return true;
|
||||
}
|
||||
for (unsigned i = 0; _index_valid(i); i++)
|
||||
if (_with_control_at_index(i, try_alloc, [&] { return false; }))
|
||||
return { *this, { i } };
|
||||
|
||||
error("trace-control allocation failed");
|
||||
return false;
|
||||
}
|
||||
return Error();
|
||||
}
|
||||
|
||||
void free(unsigned index)
|
||||
{
|
||||
if (_index_valid(index))
|
||||
_local_base()[index].reset();
|
||||
}
|
||||
void _free(Slot &slot)
|
||||
{
|
||||
_with_control_at_index(slot.index,
|
||||
[&] (Control &control) { control.reset(); }, [] { });
|
||||
}
|
||||
|
||||
Trace::Control *at(unsigned index)
|
||||
{
|
||||
return _index_valid(index) ? &(_local_base()[index]) : nullptr;
|
||||
}
|
||||
void with_control(Result const &slot, auto const &fn) const
|
||||
{
|
||||
slot.with_result(
|
||||
[&] (Slot const &slot) {
|
||||
_with_control_at_index(slot.index, fn, [&] { }); },
|
||||
[&] (Error) { });
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__TRACE__CONTROL_AREA_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user