diff --git a/repos/base-nova/src/core/include/vm_session_component.h b/repos/base-nova/src/core/include/vm_session_component.h index a320975b9f..ec5bc2e4bb 100644 --- a/repos/base-nova/src/core/include/vm_session_component.h +++ b/repos/base-nova/src/core/include/vm_session_component.h @@ -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 { }; public: diff --git a/repos/base-nova/src/core/vm_session_component.cc b/repos/base-nova/src/core/vm_session_component.cc index a833957e5c..9ca6467ffa 100644 --- a/repos/base-nova/src/core/vm_session_component.cc +++ b/repos/base-nova/src/core/vm_session_component.cc @@ -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}); diff --git a/repos/base/src/core/cpu_session_component.cc b/repos/base/src/core/cpu_session_component.cc index edcb431d79..16813d2dee 100644 --- a/repos/base/src/core/cpu_session_component.cc +++ b/repos/base/src/core/cpu_session_component.cc @@ -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); diff --git a/repos/base/src/core/cpu_thread_component.cc b/repos/base/src/core/cpu_thread_component.cc index 568bc4e947..cc4873bff7 100644 --- a/repos/base/src/core/cpu_thread_component.cc +++ b/repos/base/src/core/cpu_thread_component.cc @@ -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( + [&] (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(); } diff --git a/repos/base/src/core/include/cpu_thread_component.h b/repos/base/src/core/include/cpu_thread_component.h index 1850e32175..2a8d181b90 100644 --- a/repos/base/src/core/include/cpu_thread_component.h +++ b/repos/base/src/core/include/cpu_thread_component.h @@ -69,32 +69,9 @@ class Core::Cpu_thread_component : public Rpc_object, */ 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_registry &_trace_sources; @@ -164,7 +141,7 @@ class Core::Cpu_thread_component : public Rpc_object, _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, _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); diff --git a/repos/base/src/core/include/trace/control_area.h b/repos/base/src/core/include/trace/control_area.h index afdf1841d8..2d6ce8430b 100644 --- a/repos/base/src/core/include/trace/control_area.h +++ b/repos/base/src/core/include/trace/control_area.h @@ -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 _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()[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(); } + ~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; + 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_ */