168 lines
3.8 KiB
C++
168 lines
3.8 KiB
C++
/*
|
|
* \brief Event tracing control interface between CPU client and CPU server
|
|
* \author Norman Feske
|
|
* \date 2013-08-09
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2013 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifndef _TRACE_CONTROL_H_
|
|
#define _TRACE_CONTROL_H_
|
|
|
|
namespace Genode { namespace Trace { class Control; } }
|
|
|
|
|
|
/**
|
|
* Structure shared between core and CPU session client
|
|
*
|
|
* The 'Trace_control' structure allows core to propagate control
|
|
* information to the threads of a process in an asynchronous way,
|
|
* for example to enable/disable tracing or setting the tracing
|
|
* policy.
|
|
*/
|
|
class Genode::Trace::Control
|
|
{
|
|
private:
|
|
|
|
enum State { FREE, DISABLED, ENABLED, ERROR };
|
|
|
|
unsigned volatile _policy_version;
|
|
|
|
State volatile _designated_state;
|
|
State volatile _acknowledged_state;
|
|
|
|
bool volatile _inhibit;
|
|
|
|
public:
|
|
|
|
/*************************************************
|
|
** Interface used by by the CPU session client **
|
|
*************************************************/
|
|
|
|
/**
|
|
* Facility to temporarily inhibit tracing
|
|
*
|
|
* This utility is used by a thread during the initialization of its
|
|
* 'Trace::Logger' to prevent recursion. During initialiation, the
|
|
* logger performs a few RPCs (e.g., to obtain the trace-control
|
|
* index). Because an RPC is a trace point, this would result in the
|
|
* re-entering the logger initialization.
|
|
*/
|
|
struct Inhibit_guard
|
|
{
|
|
Control &_control;
|
|
Inhibit_guard(Control &control) : _control(control)
|
|
{
|
|
_control._inhibit = true;
|
|
}
|
|
|
|
~Inhibit_guard() { _control._inhibit = false; }
|
|
};
|
|
|
|
/**
|
|
* Request current policy version
|
|
*
|
|
* To be compared to the version currently installed at the
|
|
* client.
|
|
*/
|
|
unsigned policy_version() const { return _policy_version; }
|
|
|
|
/**
|
|
* Called after having updated the policy
|
|
*/
|
|
void acknowledge_policy_version(unsigned version) { _policy_version = version; }
|
|
|
|
/**
|
|
* Detect state change
|
|
*/
|
|
bool state_changed() const { return _designated_state != _acknowledged_state; }
|
|
|
|
/**
|
|
* Return true if CPU client thread should stop tracing
|
|
*/
|
|
bool to_be_disabled() const
|
|
{
|
|
return state_changed() && (_designated_state == DISABLED);
|
|
}
|
|
|
|
/**
|
|
* Return true if CPU client thread should start tracing
|
|
*/
|
|
bool to_be_enabled() const
|
|
{
|
|
return state_changed() && (_designated_state == ENABLED);
|
|
}
|
|
|
|
/**
|
|
* Confirm that the CPU client has enabled the tracing
|
|
*/
|
|
void acknowledge_enabled() { _acknowledged_state = ENABLED; };
|
|
|
|
/**
|
|
* Confirm that the CPU client has disabled the tracing
|
|
*
|
|
* After acknowledging that we disabled the policy, core is
|
|
* safe to free the policy dataspace.
|
|
*/
|
|
void acknowledge_disabled() { _acknowledged_state = DISABLED; };
|
|
|
|
/**
|
|
* State set when trace buffer or policy could not be successfully
|
|
* obtained.
|
|
*/
|
|
void error() { _acknowledged_state = ERROR; }
|
|
|
|
/**
|
|
* Return true if the corresponding thread should suppress trace events
|
|
*/
|
|
bool tracing_inhibited() const { return _inhibit; }
|
|
|
|
|
|
/*****************************************
|
|
** Accessors called by the CPU service **
|
|
*****************************************/
|
|
|
|
bool is_free() const { return _designated_state == FREE; }
|
|
|
|
void alloc()
|
|
{
|
|
_policy_version = 0;
|
|
_designated_state = DISABLED;
|
|
_acknowledged_state = DISABLED;
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
_policy_version = 0;
|
|
_designated_state = FREE;
|
|
_acknowledged_state = FREE;
|
|
}
|
|
|
|
void trace()
|
|
{
|
|
_policy_version++;
|
|
enable();
|
|
}
|
|
|
|
void enable()
|
|
{
|
|
_designated_state = ENABLED;
|
|
}
|
|
|
|
void disable()
|
|
{
|
|
_designated_state = DISABLED;
|
|
}
|
|
|
|
bool has_error() const { return _acknowledged_state == ERROR; }
|
|
|
|
bool is_enabled() const { return _acknowledged_state == ENABLED; }
|
|
};
|
|
|
|
#endif /* _TRACE_CONTROL_H_ */
|