From 959572968de0a932dd051a1a1f279061666a6217 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 11 Jun 2015 23:05:02 +0200 Subject: [PATCH] core: provide thread exec times via TRACE service This patch enable clients of core's TRACE service to obtain the execution times of trace subjects (i.e., threads). The execution time is delivered as part of the 'Subject_info' structure. Right now, the feature is available solely on NOVA. On all other base platforms, the returned execution times are 0. Issue #813 --- .../src/core/include/platform_thread.h | 7 ++- .../src/core/include/platform_thread.h | 7 ++- .../src/core/include/cpu_session_component.h | 22 +++++++-- .../src/core/include/platform_thread.h | 7 ++- repos/base-foc/src/core/platform_thread.cc | 2 +- .../src/core/include/platform_thread.h | 5 +++ .../src/core/include/cpu_session_component.h | 22 +++++++-- .../src/core/include/platform_thread.h | 7 ++- .../src/core/include/cpu_session_component.h | 26 +++++++++-- .../src/core/include/platform_thread.h | 7 ++- repos/base-nova/src/core/platform_thread.cc | 17 ++++++- .../src/core/include/platform_thread.h | 7 ++- .../src/core/include/platform_thread.h | 7 ++- .../src/core/platform_thread.cc | 2 +- .../src/core/include/platform_thread.h | 7 ++- repos/base/include/base/trace/types.h | 45 ++++++++++++++----- .../src/core/include/cpu_session_component.h | 21 +++++++-- .../src/core/include/trace/source_registry.h | 38 +++++++++++----- .../src/core/include/trace/subject_registry.h | 16 ++++++- repos/os/src/test/trace/main.cc | 5 ++- 20 files changed, 226 insertions(+), 51 deletions(-) diff --git a/repos/base-codezero/src/core/include/platform_thread.h b/repos/base-codezero/src/core/include/platform_thread.h index 8651bd013..ae2e8c386 100644 --- a/repos/base-codezero/src/core/include/platform_thread.h +++ b/repos/base-codezero/src/core/include/platform_thread.h @@ -139,7 +139,7 @@ namespace Genode { /** * Get the executing CPU for this thread */ - Affinity::Location affinity() { return Affinity::Location(); } + Affinity::Location affinity() const { return Affinity::Location(); } /** * Get thread name @@ -157,6 +157,11 @@ namespace Genode { * Set CPU quota of the thread to 'quota' */ void quota(size_t const quota) { /* not supported*/ } + + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } }; } diff --git a/repos/base-fiasco/src/core/include/platform_thread.h b/repos/base-fiasco/src/core/include/platform_thread.h index 8f6fb54eb..e134ec9ae 100644 --- a/repos/base-fiasco/src/core/include/platform_thread.h +++ b/repos/base-fiasco/src/core/include/platform_thread.h @@ -126,7 +126,7 @@ namespace Genode { /** * Request the affinity of this thread */ - Affinity::Location affinity() { return Affinity::Location(); } + Affinity::Location affinity() const { return Affinity::Location(); } /** * Return the address space to which the thread is bound @@ -155,6 +155,11 @@ namespace Genode { */ void quota(size_t const quota) { /* not supported*/ } + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } + /******************************* ** Fiasco-specific Accessors ** diff --git a/repos/base-foc/src/core/include/cpu_session_component.h b/repos/base-foc/src/core/include/cpu_session_component.h index 2852b58ef..7661c0134 100644 --- a/repos/base-foc/src/core/include/cpu_session_component.h +++ b/repos/base-foc/src/core/include/cpu_session_component.h @@ -46,7 +46,8 @@ namespace Genode { class Cpu_thread_component : public Rpc_object, - public List::Element + public List::Element, + public Trace::Source::Info_accessor { public: @@ -55,6 +56,7 @@ namespace Genode { private: + Session_label const _session_label; Thread_name const _name; Platform_thread _platform_thread; bool _bound; /* pd binding flag */ @@ -73,15 +75,27 @@ namespace Genode { unsigned trace_control_index, Trace::Control &trace_control) : - _name(name), + _session_label(label), _name(name), _platform_thread(name.string(), priority, utcb), _bound(false), _sigh(sigh), _trace_control_index(trace_control_index), - _trace_source(label, _name, trace_control) + _trace_source(*this, trace_control) { update_exception_sigh(); } + /******************************************** + ** Trace::Source::Info_accessor interface ** + ********************************************/ + + Trace::Source::Info trace_source_info() const + { + return { _session_label, _name, + _platform_thread.execution_time(), + _platform_thread.affinity() }; + } + + /************************ ** Accessor functions ** ************************/ @@ -228,7 +242,7 @@ namespace Genode { Dataspace_capability trace_buffer(Thread_capability); Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); - int transfer_quota(Cpu_session_capability c, size_t q); + int transfer_quota(Cpu_session_capability, size_t); Quota quota() override; diff --git a/repos/base-foc/src/core/include/platform_thread.h b/repos/base-foc/src/core/include/platform_thread.h index 1e94e559b..fe4da4fdc 100644 --- a/repos/base-foc/src/core/include/platform_thread.h +++ b/repos/base-foc/src/core/include/platform_thread.h @@ -143,7 +143,7 @@ namespace Genode { /** * Get the executing CPU for this thread */ - Affinity::Location affinity(); + Affinity::Location affinity() const; /** * Return the address space to which the thread is bound @@ -172,6 +172,11 @@ namespace Genode { */ void quota(size_t const quota) { /* not supported*/ } + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } + /******************************* ** Fiasco-specific Accessors ** diff --git a/repos/base-foc/src/core/platform_thread.cc b/repos/base-foc/src/core/platform_thread.cc index 151104122..320173b85 100644 --- a/repos/base-foc/src/core/platform_thread.cc +++ b/repos/base-foc/src/core/platform_thread.cc @@ -213,7 +213,7 @@ void Platform_thread::affinity(Affinity::Location location) } -Affinity::Location Platform_thread::affinity() +Affinity::Location Platform_thread::affinity() const { return _location; } diff --git a/repos/base-hw/src/core/include/platform_thread.h b/repos/base-hw/src/core/include/platform_thread.h index 5dbb89c40..cc72cfa0a 100644 --- a/repos/base-hw/src/core/include/platform_thread.h +++ b/repos/base-hw/src/core/include/platform_thread.h @@ -178,6 +178,11 @@ namespace Genode { */ Weak_ptr address_space(); + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } + /*************** ** Accessors ** diff --git a/repos/base-linux/src/core/include/cpu_session_component.h b/repos/base-linux/src/core/include/cpu_session_component.h index 266c788e5..f3dfe8bfb 100644 --- a/repos/base-linux/src/core/include/cpu_session_component.h +++ b/repos/base-linux/src/core/include/cpu_session_component.h @@ -45,7 +45,8 @@ namespace Genode { class Cpu_thread_component : public Rpc_object, - public List::Element + public List::Element, + public Trace::Source::Info_accessor { public: @@ -54,6 +55,7 @@ namespace Genode { private: + Session_label const _session_label; Thread_name const _name; Platform_thread _platform_thread; bool _bound; /* pd binding flag */ @@ -72,15 +74,27 @@ namespace Genode { unsigned trace_control_index, Trace::Control &trace_control) : - _name(name), + _session_label(label), _name(name), _platform_thread(name.string(), priority, utcb), _bound(false), _sigh(sigh), _trace_control_index(trace_control_index), - _trace_source(label, _name, trace_control) + _trace_source(*this, trace_control) { update_exception_sigh(); } + /******************************************** + ** Trace::Source::Info_accessor interface ** + ********************************************/ + + Trace::Source::Info trace_source_info() const + { + return { _session_label, _name, + _platform_thread.execution_time(), + _platform_thread.affinity() }; + } + + /************************ ** Accessor functions ** ************************/ @@ -218,7 +232,7 @@ namespace Genode { Dataspace_capability trace_buffer(Thread_capability); Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); - int transfer_quota(Cpu_session_capability c, size_t q); + int transfer_quota(Cpu_session_capability, size_t); Quota quota() override; diff --git a/repos/base-linux/src/core/include/platform_thread.h b/repos/base-linux/src/core/include/platform_thread.h index 71257d964..0a45b6605 100644 --- a/repos/base-linux/src/core/include/platform_thread.h +++ b/repos/base-linux/src/core/include/platform_thread.h @@ -126,7 +126,7 @@ namespace Genode { /** * Request the affinity of this thread */ - Affinity::Location affinity() { return Affinity::Location(); } + Affinity::Location affinity() const { return Affinity::Location(); } /** * Register process ID and thread ID of thread @@ -158,6 +158,11 @@ namespace Genode { * Set CPU quota of the thread to 'quota' */ void quota(size_t const quota) { /* not supported*/ } + + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } }; } diff --git a/repos/base-nova/src/core/include/cpu_session_component.h b/repos/base-nova/src/core/include/cpu_session_component.h index df888df19..1bdc0189b 100644 --- a/repos/base-nova/src/core/include/cpu_session_component.h +++ b/repos/base-nova/src/core/include/cpu_session_component.h @@ -46,7 +46,8 @@ namespace Genode { class Cpu_thread_component : public Rpc_object, - public List::Element + public List::Element, + public Trace::Source::Info_accessor { public: @@ -55,6 +56,7 @@ namespace Genode { private: + Session_label const _session_label; Thread_name const _name; Platform_thread _platform_thread; bool _bound; /* pd binding flag */ @@ -73,15 +75,27 @@ namespace Genode { unsigned trace_control_index, Trace::Control &trace_control) : - _name(name), + _session_label(label), _name(name), _platform_thread(name.string(), priority, utcb), _bound(false), _sigh(sigh), _trace_control_index(trace_control_index), - _trace_source(label, _name, trace_control) + _trace_source(*this, trace_control) { update_exception_sigh(); } + /******************************************** + ** Trace::Source::Info_accessor interface ** + ********************************************/ + + Trace::Source::Info trace_source_info() const + { + return { _session_label, _name, + _platform_thread.execution_time(), + _platform_thread.affinity() }; + } + + /************************ ** Accessor functions ** ************************/ @@ -142,6 +156,10 @@ namespace Genode { Trace::Source_registry &_trace_sources; Trace::Control_area _trace_control_area; + /* + * Members for quota accounting + */ + size_t _weight; size_t _quota; Cpu_session_component * _ref; @@ -226,7 +244,7 @@ namespace Genode { Dataspace_capability trace_buffer(Thread_capability); Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); - int transfer_quota(Cpu_session_capability c, size_t q); + int transfer_quota(Cpu_session_capability, size_t); Quota quota() override; diff --git a/repos/base-nova/src/core/include/platform_thread.h b/repos/base-nova/src/core/include/platform_thread.h index 9bf58d9ae..cc8763a6c 100644 --- a/repos/base-nova/src/core/include/platform_thread.h +++ b/repos/base-nova/src/core/include/platform_thread.h @@ -146,7 +146,7 @@ namespace Genode { /** * Get the executing CPU for this thread */ - Affinity::Location affinity(); + Affinity::Location affinity() const; /** * Get thread name @@ -169,6 +169,11 @@ namespace Genode { * Set CPU quota of the thread to 'quota' */ void quota(size_t const quota) { /* not supported*/ } + + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const; }; } diff --git a/repos/base-nova/src/core/platform_thread.cc b/repos/base-nova/src/core/platform_thread.cc index e48a126a2..bd5b8ecb6 100644 --- a/repos/base-nova/src/core/platform_thread.cc +++ b/repos/base-nova/src/core/platform_thread.cc @@ -45,7 +45,7 @@ void Platform_thread::affinity(Affinity::Location location) } -Affinity::Location Platform_thread::affinity() { return _location; } +Affinity::Location Platform_thread::affinity() const { return _location; } int Platform_thread::start(void *ip, void *sp) @@ -295,6 +295,21 @@ Weak_ptr Platform_thread::address_space() } +unsigned long long Platform_thread::execution_time() const +{ + unsigned long long time = 0; + + /* + * Ignore the return value, which indicates success only for global ECs. + * For local ECs, we simply return 0 as local ECs are executed with the + * time of their callers. + */ + (void) Nova::sc_ctrl(_sel_sc(), time); + + return time; +} + + Platform_thread::Platform_thread(const char *name, unsigned prio, int thread_id) : _pd(0), _pager(0), _id_base(cap_map()->insert(1)), diff --git a/repos/base-okl4/src/core/include/platform_thread.h b/repos/base-okl4/src/core/include/platform_thread.h index ff386d734..4762f94f1 100644 --- a/repos/base-okl4/src/core/include/platform_thread.h +++ b/repos/base-okl4/src/core/include/platform_thread.h @@ -145,13 +145,18 @@ namespace Genode { /** * Request the affinity of this thread */ - Affinity::Location affinity() { return Affinity::Location(); } + Affinity::Location affinity() const { return Affinity::Location(); } /** * Set CPU quota of the thread */ void quota(size_t) { /* not supported */ } + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } + /***************************** ** OKL4-specific Accessors ** diff --git a/repos/base-pistachio/src/core/include/platform_thread.h b/repos/base-pistachio/src/core/include/platform_thread.h index e5b78672b..1632cda63 100644 --- a/repos/base-pistachio/src/core/include/platform_thread.h +++ b/repos/base-pistachio/src/core/include/platform_thread.h @@ -146,13 +146,18 @@ namespace Genode { /** * Request the affinity of this thread */ - Affinity::Location affinity(); + Affinity::Location affinity() const; /** * Set CPU quota of the thread to 'quota' */ void quota(size_t const quota) { /* not supported*/ } + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } + /********************************** ** Pistachio-specific Accessors ** diff --git a/repos/base-pistachio/src/core/platform_thread.cc b/repos/base-pistachio/src/core/platform_thread.cc index 3274e5d35..e0b75699b 100644 --- a/repos/base-pistachio/src/core/platform_thread.cc +++ b/repos/base-pistachio/src/core/platform_thread.cc @@ -56,7 +56,7 @@ void Platform_thread::affinity(Affinity::Location location) } -Affinity::Location Platform_thread::affinity() +Affinity::Location Platform_thread::affinity() const { return _location; } diff --git a/repos/base-sel4/src/core/include/platform_thread.h b/repos/base-sel4/src/core/include/platform_thread.h index 00ff3fecd..cd57e0763 100644 --- a/repos/base-sel4/src/core/include/platform_thread.h +++ b/repos/base-sel4/src/core/include/platform_thread.h @@ -126,6 +126,11 @@ class Genode::Platform_thread : public List::Element */ Weak_ptr address_space(); + /** + * Return execution time consumed by the thread + */ + unsigned long long execution_time() const { return 0; } + /************************ ** Accessor functions ** @@ -151,7 +156,7 @@ class Genode::Platform_thread : public List::Element /** * Get the executing CPU for this thread */ - Affinity::Location affinity() { return Affinity::Location(); } + Affinity::Location affinity() const { return Affinity::Location(); } /** * Set CPU quota of the thread diff --git a/repos/base/include/base/trace/types.h b/repos/base/include/base/trace/types.h index c11080223..ec7c15ab3 100644 --- a/repos/base/include/base/trace/types.h +++ b/repos/base/include/base/trace/types.h @@ -9,6 +9,7 @@ /* Genode includes */ #include +#include namespace Genode { namespace Trace { @@ -26,10 +27,11 @@ namespace Genode { namespace Trace { struct Subject_not_traced : Exception { }; typedef String<160> Session_label; - typedef String<64> Thread_name; + typedef String<32> Thread_name; struct Policy_id; struct Subject_id; + struct Execution_time; struct Subject_info; } } @@ -62,6 +64,20 @@ struct Genode::Trace::Subject_id }; +/** + * Execution time of trace subject + * + * The value is kernel specific. + */ +struct Genode::Trace::Execution_time +{ + unsigned long long value; + + Execution_time() : value(0) { } + Execution_time(unsigned long long value) : value(value) { } +}; + + /** * Subject information */ @@ -86,10 +102,12 @@ class Genode::Trace::Subject_info private: - Session_label _session_label; - Thread_name _thread_name; - State _state; - Policy_id _policy_id; + Session_label _session_label; + Thread_name _thread_name; + State _state; + Policy_id _policy_id; + Execution_time _execution_time; + Affinity::Location _affinity; public: @@ -97,16 +115,21 @@ class Genode::Trace::Subject_info Subject_info(Session_label const &session_label, Thread_name const &thread_name, - State state, Policy_id policy_id) + State state, Policy_id policy_id, + Execution_time execution_time, + Affinity::Location affinity) : _session_label(session_label), _thread_name(thread_name), - _state(state), _policy_id(policy_id) + _state(state), _policy_id(policy_id), + _execution_time(execution_time), _affinity(affinity) { } - Session_label const &session_label() const { return _session_label; } - Thread_name const &thread_name() const { return _thread_name; } - State state() const { return _state; } - Policy_id policy_id() const { return _policy_id; } + Session_label const &session_label() const { return _session_label; } + Thread_name const &thread_name() const { return _thread_name; } + State state() const { return _state; } + Policy_id policy_id() const { return _policy_id; } + Execution_time execution_time() const { return _execution_time; } + Affinity::Location affinity() const { return _affinity; } }; #endif /* _INCLUDE__BASE__TRACE__TYPES_H_ */ diff --git a/repos/base/src/core/include/cpu_session_component.h b/repos/base/src/core/include/cpu_session_component.h index b9bd5e4da..82d808353 100644 --- a/repos/base/src/core/include/cpu_session_component.h +++ b/repos/base/src/core/include/cpu_session_component.h @@ -44,7 +44,8 @@ namespace Genode { class Cpu_thread_component : public Rpc_object, - public List::Element + public List::Element, + public Trace::Source::Info_accessor { public: @@ -54,6 +55,7 @@ namespace Genode { private: size_t const _weight; + Session_label const _session_label; Thread_name const _name; Platform_thread _platform_thread; bool _bound; /* pd binding flag */ @@ -83,16 +85,29 @@ namespace Genode { unsigned trace_control_index, Trace::Control &trace_control) : - _weight(weight), _name(name), + _weight(weight), + _session_label(label), _name(name), _platform_thread(quota, name.string(), priority, utcb), _bound(false), _sigh(sigh), _trace_control_index(trace_control_index), - _trace_source(label, _name, trace_control) + _trace_source(*this, trace_control) { update_exception_sigh(); } + /******************************************** + ** Trace::Source::Info_accessor interface ** + ********************************************/ + + Trace::Source::Info trace_source_info() const + { + return { _session_label, _name, + _platform_thread.execution_time(), + _platform_thread.affinity() }; + } + + /************************ ** Accessor functions ** ************************/ diff --git a/repos/base/src/core/include/trace/source_registry.h b/repos/base/src/core/include/trace/source_registry.h index 2ebbfe0b3..a76505c93 100644 --- a/repos/base/src/core/include/trace/source_registry.h +++ b/repos/base/src/core/include/trace/source_registry.h @@ -43,25 +43,40 @@ class Genode::Trace::Source public Genode::Weak_object, public Genode::List::Element { + public: + + struct Info + { + Session_label label; + Thread_name name; + Execution_time execution_time; + Affinity::Location affinity; + }; + + /** + * Interface for querying trace-source information + */ + struct Info_accessor + { + virtual Info trace_source_info() const = 0; + }; + private: unsigned const _unique_id; - Session_label const &_label; - Thread_name const _name; + Info_accessor const &_info; Control &_control; Dataspace_capability _policy; Dataspace_capability _buffer; - Source_owner const *_owner; + Source_owner const *_owner = nullptr; static unsigned _alloc_unique_id(); public: - Source(Session_label const &label, Thread_name const &name, - Control &control) + Source(Info_accessor const &info, Control &control) : - _unique_id(_alloc_unique_id()), - _label(label), _name(name), _control(control), _owner(0) + _unique_id(_alloc_unique_id()), _info(info), _control(control) { } @@ -69,8 +84,7 @@ class Genode::Trace::Source ** Interface used by TRACE service ** *************************************/ - Session_label const &label() const { return _label; } - Thread_name const &name() const { return _name; } + Info const info() const { return _info.trace_source_info(); } void trace(Dataspace_capability policy, Dataspace_capability buffer) { @@ -153,8 +167,10 @@ class Genode::Trace::Source_registry void export_sources(TEST &test, INSERT &insert) { for (Source *s = _entries.first(); s; s = s->next()) - if (!test(s->unique_id())) - insert(s->unique_id(), s->weak_ptr(), s->label(), s->name()); + if (!test(s->unique_id())) { + Source::Info const info = s->info(); + insert(s->unique_id(), s->weak_ptr(), info.label, info.name); + } } }; diff --git a/repos/base/src/core/include/trace/subject_registry.h b/repos/base/src/core/include/trace/subject_registry.h index 3c4fb96e2..caafcb27f 100644 --- a/repos/base/src/core/include/trace/subject_registry.h +++ b/repos/base/src/core/include/trace/subject_registry.h @@ -236,7 +236,21 @@ class Genode::Trace::Subject Subject_info info() { - return Subject_info(_label, _name, _state(), _policy_id); + Execution_time execution_time; + Affinity::Location affinity; + + { + Locked_ptr source(_source); + + if (source.is_valid()) { + Trace::Source::Info const info = source->info(); + execution_time = info.execution_time; + affinity = info.affinity; + } + } + + return Subject_info(_label, _name, _state(), _policy_id, + execution_time, affinity); } Dataspace_capability buffer() const { return _buffer.dataspace(); } diff --git a/repos/os/src/test/trace/main.cc b/repos/os/src/test/trace/main.cc index 195d836fa..304f48249 100644 --- a/repos/os/src/test/trace/main.cc +++ b/repos/os/src/test/trace/main.cc @@ -184,12 +184,13 @@ int main(int argc, char **argv) for (size_t i = 0; i < num_subjects; i++) { Trace::Subject_info info = trace.subject_info(subjects[i]); - printf("ID:%d label:\"%s\" name:\"%s\" state:%s policy:%d\n", + printf("ID:%d label:\"%s\" name:\"%s\" state:%s policy:%d time:%lld\n", subjects[i].id, info.session_label().string(), info.thread_name().string(), state_name(info.state()), - info.policy_id().id); + info.policy_id().id, + info.execution_time().value); /* enable tracing */ if (!policy_set