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
This commit is contained in:
Norman Feske 2015-06-11 23:05:02 +02:00 committed by Christian Helmuth
parent fbe44f08d4
commit 959572968d
20 changed files with 226 additions and 51 deletions

View File

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

View File

@ -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 **

View File

@ -46,7 +46,8 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
public List<Cpu_thread_component>::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;

View File

@ -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 **

View File

@ -213,7 +213,7 @@ void Platform_thread::affinity(Affinity::Location location)
}
Affinity::Location Platform_thread::affinity()
Affinity::Location Platform_thread::affinity() const
{
return _location;
}

View File

@ -178,6 +178,11 @@ namespace Genode {
*/
Weak_ptr<Address_space> address_space();
/**
* Return execution time consumed by the thread
*/
unsigned long long execution_time() const { return 0; }
/***************
** Accessors **

View File

@ -45,7 +45,8 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
public List<Cpu_thread_component>::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;

View File

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

View File

@ -46,7 +46,8 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
public List<Cpu_thread_component>::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;

View File

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

View File

@ -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<Address_space> 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)),

View File

@ -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 **

View File

@ -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 **

View File

@ -56,7 +56,7 @@ void Platform_thread::affinity(Affinity::Location location)
}
Affinity::Location Platform_thread::affinity()
Affinity::Location Platform_thread::affinity() const
{
return _location;
}

View File

@ -126,6 +126,11 @@ class Genode::Platform_thread : public List<Platform_thread>::Element
*/
Weak_ptr<Address_space> 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<Platform_thread>::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

View File

@ -9,6 +9,7 @@
/* Genode includes */
#include <util/string.h>
#include <base/affinity.h>
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_ */

View File

@ -44,7 +44,8 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
public List<Cpu_thread_component>::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 **
************************/

View File

@ -43,25 +43,40 @@ class Genode::Trace::Source
public Genode::Weak_object<Genode::Trace::Source>,
public Genode::List<Genode::Trace::Source>::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);
}
}
};

View File

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

View File

@ -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