diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc
index e764578ec..8cace8526 100644
--- a/repos/base-hw/src/core/kernel/cpu.cc
+++ b/repos/base-hw/src/core/kernel/cpu.cc
@@ -140,7 +140,8 @@ Cpu_job & Cpu::schedule()
_scheduler.update(_timer.time());
time_t t = _scheduler.head_quota();
_timer.set_timeout(this, t);
- _timer.schedule_timeout();
+ time_t duration = _timer.schedule_timeout();
+ old_job.update_execution_time(duration);
}
/* return new job */
diff --git a/repos/base-hw/src/core/kernel/cpu.h b/repos/base-hw/src/core/kernel/cpu.h
index 409a77557..531884b17 100644
--- a/repos/base-hw/src/core/kernel/cpu.h
+++ b/repos/base-hw/src/core/kernel/cpu.h
@@ -178,6 +178,11 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
Inter_processor_work_list & work_list() {
return _local_work_list; }
+
+ /**
+ * Return CPU's idle thread object
+ */
+ Kernel::Thread &idle_thread() { return _idle; }
};
diff --git a/repos/base-hw/src/core/kernel/cpu_context.h b/repos/base-hw/src/core/kernel/cpu_context.h
index aaf5384a5..a9ecc262e 100644
--- a/repos/base-hw/src/core/kernel/cpu_context.h
+++ b/repos/base-hw/src/core/kernel/cpu_context.h
@@ -35,6 +35,8 @@ class Kernel::Cpu_job : private Cpu_share
friend class Cpu; /* static_cast from 'Cpu_share' to 'Cpu_job' */
+ time_t _execution_time { 0 };
+
/*
* Noncopyable
*/
@@ -112,6 +114,16 @@ class Kernel::Cpu_job : private Cpu_share
*/
bool own_share_active() { return Cpu_share::ready(); }
+ /**
+ * Update total execution time
+ */
+ void update_execution_time(time_t duration) { _execution_time += duration; }
+
+ /**
+ * Return total execution time
+ */
+ time_t execution_time() const { return _execution_time; }
+
/***************
** Accessors **
diff --git a/repos/base-hw/src/core/kernel/timer.cc b/repos/base-hw/src/core/kernel/timer.cc
index 6854135fe..ffc153626 100644
--- a/repos/base-hw/src/core/kernel/timer.cc
+++ b/repos/base-hw/src/core/kernel/timer.cc
@@ -60,16 +60,19 @@ void Timer::set_timeout(Timeout * const timeout, time_t const duration)
}
-void Timer::schedule_timeout()
+time_t Timer::schedule_timeout()
{
/* get the timeout with the nearest end time */
Timeout * timeout = _timeout_list.first();
assert(timeout);
/* install timeout at timer hardware */
- _time += _duration();
+ time_t duration = _duration();
+ _time += duration;
_last_timeout_duration = (timeout->_end > _time) ? timeout->_end - _time : 1;
_start_one_shot(_last_timeout_duration);
+
+ return duration;
}
diff --git a/repos/base-hw/src/core/kernel/timer.h b/repos/base-hw/src/core/kernel/timer.h
index e6e9455e5..1f7348c75 100644
--- a/repos/base-hw/src/core/kernel/timer.h
+++ b/repos/base-hw/src/core/kernel/timer.h
@@ -91,7 +91,10 @@ class Kernel::Timer
Timer(Cpu & cpu);
- void schedule_timeout();
+ /**
+ * Return duration from last call of this function
+ */
+ time_t schedule_timeout();
void process_timeouts();
diff --git a/repos/base-hw/src/core/platform.cc b/repos/base-hw/src/core/platform.cc
index 46520f1f2..bbdc5a41b 100644
--- a/repos/base-hw/src/core/platform.cc
+++ b/repos/base-hw/src/core/platform.cc
@@ -12,8 +12,6 @@
* under the terms of the GNU Affero General Public License version 3.
*/
-/* Genode includes */
-#include
/* core includes */
#include
@@ -32,6 +30,10 @@
#include
#include
+/* Genode includes */
+#include
+#include
+
using namespace Genode;
@@ -205,6 +207,40 @@ Platform::Platform()
init_core_log(Core_log_range { core_local_addr, log_size } );
}
+ struct Trace_source : public Trace::Source::Info_accessor,
+ private Trace::Control,
+ private Trace::Source
+ {
+ Kernel::Thread &thread;
+ Affinity::Location const affinity;
+
+ /**
+ * Trace::Source::Info_accessor interface
+ */
+ Info trace_source_info() const override
+ {
+ Trace::Execution_time execution_time { thread.execution_time(), 0 };
+ return { Session_label("kernel"), thread.label(), execution_time,
+ affinity };
+ }
+
+ Trace_source(Trace::Source_registry ®istry,
+ Kernel::Thread &thread, Affinity::Location affinity)
+ :
+ Trace::Control(),
+ Trace::Source(*this, *this),
+ thread(thread), affinity(affinity)
+ {
+ registry.insert(this);
+ }
+ };
+
+ /* create trace sources for idle threads */
+ Kernel::cpu_pool().for_each_cpu([&] (Kernel::Cpu & cpu) {
+ new (core_mem_alloc()) Trace_source(Trace::sources(), cpu.idle_thread(),
+ Affinity::Location(cpu.id(), 0));
+ });
+
log(_rom_fs);
}
diff --git a/repos/base-hw/src/core/platform_thread.h b/repos/base-hw/src/core/platform_thread.h
index 70a1b4e1a..921cef46d 100644
--- a/repos/base-hw/src/core/platform_thread.h
+++ b/repos/base-hw/src/core/platform_thread.h
@@ -208,8 +208,11 @@ namespace Genode {
/**
* Return execution time consumed by the thread
*/
- Trace::Execution_time execution_time() const {
- return { 0, 0, _quota, _priority }; }
+ Trace::Execution_time execution_time() const
+ {
+ Genode::uint64_t execution_time =
+ const_cast(this)->_kobj->execution_time();
+ return { execution_time, 0, _quota, _priority }; }
/***************