160 lines
3.8 KiB
C++
160 lines
3.8 KiB
C++
/*
|
|
* \brief Monitoring of a trace subject
|
|
* \author Martin Stein
|
|
* \date 2018-01-12
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2018 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
/* local includes */
|
|
#include <monitor.h>
|
|
|
|
/* Genode includes */
|
|
#include <trace_session/connection.h>
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
/******************
|
|
** Monitor_base **
|
|
******************/
|
|
|
|
Monitor_base::Monitor_base(Trace::Connection &trace,
|
|
Region_map &rm,
|
|
Trace::Subject_id subject_id)
|
|
:
|
|
_trace(trace), _rm(rm),
|
|
_buffer_raw(*(Trace::Buffer *)rm.attach(_trace.buffer(subject_id)))
|
|
{ }
|
|
|
|
|
|
Monitor_base::~Monitor_base()
|
|
{
|
|
_rm.detach(&_buffer_raw);
|
|
}
|
|
|
|
|
|
/*************
|
|
** Monitor **
|
|
*************/
|
|
|
|
Monitor &Monitor::find_by_subject_id(Trace::Subject_id const subject_id)
|
|
{
|
|
if (subject_id.id == _subject_id.id) {
|
|
return *this; }
|
|
|
|
bool const side = subject_id.id > _subject_id.id;
|
|
|
|
Monitor *const monitor = Avl_node<Monitor>::child(side);
|
|
if (!monitor) {
|
|
throw Monitor_tree::No_match(); }
|
|
|
|
return monitor->find_by_subject_id(subject_id);
|
|
}
|
|
|
|
|
|
Monitor::Monitor(Trace::Connection &trace,
|
|
Region_map &rm,
|
|
Trace::Subject_id subject_id)
|
|
:
|
|
Monitor_base(trace, rm, subject_id),
|
|
_subject_id(subject_id), _buffer(_buffer_raw)
|
|
{
|
|
_update_info();
|
|
}
|
|
|
|
|
|
void Monitor::_update_info()
|
|
{
|
|
try {
|
|
Trace::Subject_info const &info =
|
|
_trace.subject_info(_subject_id);
|
|
|
|
uint64_t const last_execution_time =
|
|
_info.execution_time().thread_context;
|
|
|
|
_info = info;
|
|
_recent_exec_time =
|
|
_info.execution_time().thread_context - last_execution_time;
|
|
}
|
|
catch (Trace::Nonexistent_subject) { warning("Cannot update subject info: Nonexistent_subject"); }
|
|
}
|
|
|
|
|
|
void Monitor::print(bool activity, bool affinity)
|
|
{
|
|
_update_info();
|
|
|
|
/* print general subject information */
|
|
typedef Trace::Subject_info Subject_info;
|
|
Subject_info::State const state = _info.state();
|
|
log("<subject label=\"", _info.session_label().string(),
|
|
"\" thread=\"", _info.thread_name().string(),
|
|
"\" id=\"", _subject_id.id,
|
|
"\" state=\"", Subject_info::state_name(state),
|
|
"\">");
|
|
|
|
/* print subjects activity if desired */
|
|
if (activity)
|
|
log(" <activity total=\"", _info.execution_time().thread_context,
|
|
"\" recent=\"", _recent_exec_time,
|
|
"\">");
|
|
|
|
/* print subjects affinity if desired */
|
|
if (affinity)
|
|
log(" <affinity xpos=\"", _info.affinity().xpos(),
|
|
"\" ypos=\"", _info.affinity().ypos(),
|
|
"\">");
|
|
|
|
/* print all buffer entries that we haven't yet printed */
|
|
bool printed_buf_entries = false;
|
|
_buffer.for_each_new_entry([&] (Trace::Buffer::Entry entry) {
|
|
|
|
/* get readable data length and skip empty entries */
|
|
size_t length = min(entry.length(), (unsigned)MAX_ENTRY_LENGTH - 1);
|
|
if (!length)
|
|
return;
|
|
|
|
/* copy entry data from buffer and add terminating '0' */
|
|
memcpy(_curr_entry_data, entry.data(), length);
|
|
_curr_entry_data[length] = '\0';
|
|
|
|
/* avoid output of empty lines due to end of line character at end */
|
|
if (_curr_entry_data[length - 1] == '\n')
|
|
_curr_entry_data[length - 1] = '\0';
|
|
|
|
/* print copied entry data out to log */
|
|
if (!printed_buf_entries) {
|
|
log(" <buffer>");
|
|
printed_buf_entries = true;
|
|
}
|
|
log(Cstring(_curr_entry_data));
|
|
});
|
|
/* print end tags */
|
|
if (printed_buf_entries)
|
|
log(" </buffer>");
|
|
else
|
|
log(" <buffer />");
|
|
log("</subject>");
|
|
}
|
|
|
|
|
|
/******************
|
|
** Monitor_tree **
|
|
******************/
|
|
|
|
Monitor &Monitor_tree::find_by_subject_id(Trace::Subject_id const subject_id)
|
|
{
|
|
Monitor *const monitor = first();
|
|
|
|
if (!monitor)
|
|
throw No_match();
|
|
|
|
return monitor->find_by_subject_id(subject_id);
|
|
}
|