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 8651bd013a..ae2e8c3862 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 8f6fb54eb2..e134ec9aef 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 2852b58ef1..7661c0134e 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 1e94e559b7..fe4da4fdce 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 1511041221..320173b85a 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 5dbb89c40a..cc72cfa0a8 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 266c788e54..f3dfe8bfb8 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 71257d9643..0a45b66059 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 df888df195..1bdc0189b9 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 9bf58d9ae9..cc8763a6cc 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 e48a126a29..bd5b8ecb61 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 ff386d7342..4762f94f1f 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 e5b78672bc..1632cda63b 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 3274e5d35b..e0b75699b0 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 00ff3fecdb..cd57e07634 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 c110802231..ec7c15ab37 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 b9bd5e4da4..82d8083535 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 2ebbfe0b3a..a76505c93d 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 3c4fb96e21..caafcb27f3 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 195d836fa1..304f482491 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