core: TRACE service interface and implementation

devel
Norman Feske 10 years ago
parent fe4a6d7d81
commit 149356f7ab

@ -23,6 +23,7 @@ SRC_CC += \
irq_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
core_rm_session.cc \
core_mem_alloc.cc \
dump_alloc.cc \
@ -32,7 +33,8 @@ LIBS += core_printf base-common
INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
$(REP_DIR)/include/codezero/dummies
$(REP_DIR)/include/codezero/dummies \
$(BASE_DIR)/src/base/thread
vpath main.cc $(GEN_CORE_DIR)
vpath ram_session_component.cc $(GEN_CORE_DIR)
@ -45,6 +47,7 @@ vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath platform_services.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)

@ -24,13 +24,15 @@ SRC_CC += main.cc \
irq_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
dump_alloc.cc \
context_area.cc \
core_printf.cc
INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
$(REP_DIR)/src/base/console
$(REP_DIR)/src/base/console \
$(BASE_DIR)/src/base/thread
LIBS += base-common
@ -45,6 +47,7 @@ vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath context_area.cc $(GEN_CORE_DIR)

@ -1,6 +1,7 @@
/*
* \brief Core-specific instance of the CPU session/thread interfaces
* \author Christian Helmuth
* \author Norman Feske
* \author Stefan Kalkowski
* \date 2006-07-17
*/
@ -26,6 +27,8 @@
/* core includes */
#include <platform_thread.h>
#include <trace/control_area.h>
#include <trace/source_registry.h>
namespace Genode {
@ -45,18 +48,33 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
{
public:
typedef Trace::Session_label Session_label;
typedef Trace::Thread_name Thread_name;
private:
Thread_name const _name;
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
unsigned const _trace_control_index;
Trace::Source _trace_source;
public:
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
Cpu_thread_component(Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
unsigned trace_control_index,
Trace::Control &trace_control)
:
_platform_thread(name, priority), _bound(false), _sigh(sigh)
_name(name),
_platform_thread(name.string(), priority, utcb), _bound(false),
_sigh(sigh), _trace_control_index(trace_control_index),
_trace_source(label, _name, trace_control)
{
update_exception_sigh();
}
@ -66,9 +84,10 @@ namespace Genode {
** Accessor functions **
************************/
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
Platform_thread *platform_thread() { return &_platform_thread; }
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
void sigh(Signal_context_capability sigh)
{
@ -80,11 +99,20 @@ namespace Genode {
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
/**
* Return index within the CPU-session's trace control area
*/
unsigned trace_control_index() const { return _trace_control_index; }
};
class Cpu_session_component : public Rpc_object<Foc_cpu_session>
{
public:
typedef Cpu_thread_component::Session_label Session_label;
private:
/**
@ -93,11 +121,12 @@ namespace Genode {
*/
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
Session_label _label;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
Lock _thread_alloc_lock; /* protect alloc access */
Lock _thread_alloc_lock; /* protect allocator access */
List<Cpu_thread_component> _thread_list;
Lock _thread_list_lock; /* protect thread list */
unsigned _priority; /* priority of threads
@ -105,6 +134,8 @@ namespace Genode {
session */
Affinity::Location _location; /* CPU affinity of this
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
/**
* Exception handler that will be invoked unless overridden by a
@ -127,10 +158,11 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc, const char *args,
Affinity const &affinity);
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
/**
* Destructor

@ -65,7 +65,7 @@ namespace Genode {
/**
* Constructor for non-core threads
*/
Platform_thread(const char *name, unsigned priority);
Platform_thread(const char *name, unsigned priority, addr_t);
/**
* Constructor for core main-thread

@ -261,8 +261,7 @@ Weak_ptr<Address_space> Platform_thread::address_space()
}
Platform_thread::Platform_thread(const char *name,
unsigned prio)
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t)
: _state(DEAD),
_core_thread(false),
_thread(true),

@ -31,6 +31,7 @@ SRC_CC = cap_session_component.cc \
rom_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
thread_start.cc \
thread_context_area.cc \
core_printf.cc
@ -39,6 +40,7 @@ INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
$(REP_DIR)/src/base/lock \
$(BASE_DIR)/src/base/lock \
$(BASE_DIR)/src/base/thread \
$(REP_DIR)/src/base/console
vpath context_area.cc $(GEN_CORE_DIR)
@ -54,6 +56,7 @@ vpath ram_session_component.cc $(GEN_CORE_DIR)
vpath rm_session_component.cc $(GEN_CORE_DIR)
vpath rom_session_component.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath %.cc $(REP_DIR)/src/core
vpath %.cc $(REP_DIR)/src/base/thread

@ -24,7 +24,8 @@ INC_DIR += $(REP_DIR)/src/core \
$(REP_DIR)/src/base \
$(BASE_DIR)/src/core/include \
$(BASE_DIR)/include \
$(BASE_DIR)/src/platform
$(BASE_DIR)/src/platform \
$(BASE_DIR)/src/base/thread
# add C++ sources
SRC_CC += console.cc \
@ -46,6 +47,7 @@ SRC_CC += console.cc \
rm_session_component.cc \
rom_session_component.cc \
signal_session_component.cc \
trace_session_component.cc \
thread.cc \
kernel.cc \
rm_session_support.cc \
@ -65,6 +67,7 @@ vpath pd_session_component.cc $(BASE_DIR)/src/core
vpath ram_session_component.cc $(BASE_DIR)/src/core
vpath rm_session_component.cc $(BASE_DIR)/src/core
vpath rom_session_component.cc $(BASE_DIR)/src/core
vpath trace_session_component.cc $(BASE_DIR)/src/core
vpath dump_alloc.cc $(BASE_DIR)/src/core
vpath console.cc $(REP_DIR)/src/base
vpath pager.cc $(REP_DIR)/src/base

@ -26,6 +26,8 @@
/* core includes */
#include <cpu_thread_allocator.h>
#include <platform_thread.h>
#include <trace/control_area.h>
#include <trace/source_registry.h>
namespace Genode {
@ -45,18 +47,33 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
{
public:
typedef Trace::Session_label Session_label;
typedef Trace::Thread_name Thread_name;
private:
Thread_name const _name;
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
unsigned const _trace_control_index;
Trace::Source _trace_source;
public:
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
Cpu_thread_component(Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
unsigned trace_control_index,
Trace::Control &trace_control)
:
_platform_thread(name, priority, utcb), _bound(false), _sigh(sigh)
_name(name),
_platform_thread(name.string(), priority, utcb), _bound(false),
_sigh(sigh), _trace_control_index(trace_control_index),
_trace_source(label, _name, trace_control)
{
update_exception_sigh();
}
@ -66,9 +83,10 @@ namespace Genode {
** Accessor functions **
************************/
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
Platform_thread *platform_thread() { return &_platform_thread; }
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
void sigh(Signal_context_capability sigh)
{
@ -80,13 +98,23 @@ namespace Genode {
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
/**
* Return index within the CPU-session's trace control area
*/
unsigned trace_control_index() const { return _trace_control_index; }
};
class Cpu_session_component : public Rpc_object<Linux_cpu_session>
{
public:
typedef Cpu_thread_component::Session_label Session_label;
private:
Session_label _label;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
@ -99,6 +127,8 @@ namespace Genode {
session */
Affinity::Location _location; /* CPU affinity of this
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
/**
* Exception handler that will be invoked unless overridden by a
@ -121,10 +151,11 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc, const char *args,
Affinity const &affinity);
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
/**
* Destructor

@ -18,6 +18,7 @@ SRC_CC = main.cc \
io_mem_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
thread_linux.cc \
context_area.cc \
core_printf.cc \
@ -29,6 +30,7 @@ INC_DIR += $(REP_DIR)/src/core/include \
$(REP_DIR)/src/base/ipc \
$(REP_DIR)/src/base/env \
$(REP_DIR)/src/base/console \
$(BASE_DIR)/src/base/thread \
HOST_INC_DIR += /usr/include
@ -48,6 +50,7 @@ vpath cpu_session_component.cc $(GEN_CORE_DIR)
vpath platform_services.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath thread.cc $(BASE_DIR)/src/base/thread
vpath trace.cc $(BASE_DIR)/src/base/thread

@ -1,6 +1,7 @@
/*
* \brief Core-specific instance of the CPU session/thread interfaces
* \author Christian Helmuth
\author Norman Feske
* \author Alexander Boettcher
* \date 2006-07-17
*/
@ -26,6 +27,8 @@
/* core includes */
#include <platform_thread.h>
#include <trace/control_area.h>
#include <trace/source_registry.h>
namespace Genode {
@ -45,18 +48,33 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
{
public:
typedef Trace::Session_label Session_label;
typedef Trace::Thread_name Thread_name;
private:
Thread_name const _name;
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
unsigned const _trace_control_index;
Trace::Source _trace_source;
public:
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
Cpu_thread_component(Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
unsigned trace_control_index,
Trace::Control &trace_control)
:
_platform_thread(name, priority, utcb), _bound(false), _sigh(sigh)
_name(name),
_platform_thread(name.string(), priority, utcb), _bound(false),
_sigh(sigh), _trace_control_index(trace_control_index),
_trace_source(label, _name, trace_control)
{
update_exception_sigh();
}
@ -66,9 +84,10 @@ namespace Genode {
** Accessor functions **
************************/
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
Platform_thread *platform_thread() { return &_platform_thread; }
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
void sigh(Signal_context_capability sigh)
{
@ -80,11 +99,20 @@ namespace Genode {
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
/**
* Return index within the CPU-session's trace control area
*/
unsigned trace_control_index() const { return _trace_control_index; }
};
class Cpu_session_component : public Rpc_object<Nova_cpu_session>
{
public:
typedef Cpu_thread_component::Session_label Session_label;
private:
/**
@ -93,11 +121,12 @@ namespace Genode {
*/
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
Session_label _label;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
Lock _thread_alloc_lock; /* protect alloc access */
Lock _thread_alloc_lock; /* protect allocator access */
List<Cpu_thread_component> _thread_list;
Lock _thread_list_lock; /* protect thread list */
unsigned _priority; /* priority of threads
@ -105,6 +134,9 @@ namespace Genode {
session */
Affinity::Location _location; /* CPU affinity of this
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
@ -126,10 +158,11 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc, const char *args,
Affinity const &affinity);
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
/**
* Destructor

@ -25,6 +25,7 @@ SRC_CC = main.cc \
irq_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
core_rm_session.cc \
cap_sel_alloc.cc \
main_thread.cc \
@ -38,6 +39,7 @@ SRC_CC = main.cc \
INC_DIR = $(REP_DIR)/src/core/include \
$(REP_DIR)/src/base/console \
$(BASE_DIR)/src/base/thread \
$(GEN_CORE_DIR)/include
vpath main.cc $(GEN_CORE_DIR)
@ -47,6 +49,7 @@ vpath cpu_session_component.cc $(GEN_CORE_DIR)
vpath pd_session_component.cc $(GEN_CORE_DIR)
vpath rm_session_component.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath io_port_session_component.cc $(GEN_CORE_DIR)/x86
vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)

@ -25,6 +25,7 @@ SRC_CC += main.cc \
irq_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
core_rm_session.cc \
core_mem_alloc.cc \
core_printf.cc \
@ -34,6 +35,7 @@ SRC_CC += main.cc \
INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
$(REP_DIR)/src/base/console \
$(BASE_DIR)/src/base/thread \
$(BASE_DIR)/src/platform \
$(REP_DIR)/src/platform
@ -47,6 +49,7 @@ vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)

@ -25,6 +25,7 @@ SRC_CC = main.cc \
irq_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
dump_alloc.cc \
context_area.cc \
core_printf.cc \
@ -32,6 +33,7 @@ SRC_CC = main.cc \
INC_DIR += $(REP_DIR)/src/core/include \
$(REP_DIR)/src/base/console \
$(BASE_DIR)/src/base/thread \
$(GEN_CORE_DIR)/include
vpath main.cc $(GEN_CORE_DIR)
@ -44,6 +46,7 @@ vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath context_area.cc $(GEN_CORE_DIR)

@ -0,0 +1,119 @@
/*
* \brief Basic types used by the tracing infrastructure
* \author Norman Feske
* \date 2013-08-12
*/
#ifndef _INCLUDE__BASE__TRACE__TYPES_H_
#define _INCLUDE__BASE__TRACE__TYPES_H_
/* Genode includes */
#include <util/string.h>
namespace Genode { namespace Trace {
/*********************
** Exception types **
*********************/
struct Policy_too_large : Exception { };
struct Out_of_metadata : Exception { };
struct Nonexistent_subject : Exception { };
struct Already_traced : Exception { };
struct Source_is_dead : Exception { };
struct Nonexistent_policy : Exception { };
struct Traced_by_other_session : Exception { };
struct Subject_not_traced : Exception { };
template <size_t MAX>
struct String
{
enum { MAX_SIZE = MAX };
char buf[MAX];
size_t length;
String() : length(0) { }
String(char const *str) : length(min(strlen(str) + 1, MAX))
{
strncpy(buf, str, length);
}
bool valid() const {
return (length < MAX) && (length > 0) && (buf[length - 1] == '\0'); }
char const *string() const { return valid() ? buf : ""; }
};
typedef String<160> Session_label;
typedef String<64> Thread_name;
struct Policy_id;
struct Subject_id;
struct Subject_info;
} }
/**
* Session-local policy identifier
*/
struct Genode::Trace::Policy_id
{
unsigned id;
Policy_id() : id(0) { }
Policy_id(unsigned id) : id(id) { }
bool operator == (Policy_id const &other) { return id == other.id; }
};
/**
* Session-local trace-subject identifier
*/
struct Genode::Trace::Subject_id
{
unsigned id;
Subject_id() : id(0) { }
Subject_id(unsigned id) : id(id) { }
bool operator == (Subject_id const &other) { return id == other.id; }
};
/**
* Subject information
*/
class Genode::Trace::Subject_info
{
public:
enum State { INVALID, UNTRACED, TRACED, FOREIGN, ERROR, DEAD };
private:
Session_label _session_label;
Thread_name _thread_name;
State _state;
Policy_id _policy_id;
public:
Subject_info() : _state(INVALID) { }
Subject_info(Session_label const &session_label,
Thread_name const &thread_name,
State state, Policy_id policy_id)
:
_session_label(session_label), _thread_name(thread_name),
_state(state), _policy_id(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; }
};
#endif /* _INCLUDE__BASE__TRACE__TYPES_H_ */

@ -35,7 +35,7 @@ namespace Genode {
Affinity const &affinity = Affinity())
:
Connection<Cpu_session>(
session(affinity, "priority=0x%lx, ram_quota=32K, label=\"%s\"",
session(affinity, "priority=0x%lx, ram_quota=36K, label=\"%s\"",
priority, label)),
Cpu_session_client(cap()) { }
};

@ -0,0 +1,106 @@
/*
* \brief Client-side TRACE session interface
* \author Norman Feske
* \date 2013-08-12
*/
/*
* 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 _INCLUDE__TRACE_SESSION__CLIENT_H_
#define _INCLUDE__TRACE_SESSION__CLIENT_H_
#include <trace_session/trace_session.h>
#include <base/rpc_client.h>
#include <base/env.h>
namespace Genode { namespace Trace { struct Session_client; } }
struct Genode::Trace::Session_client : Genode::Rpc_client<Genode::Trace::Session>
{
private:
/**
* Shared-memory buffer used for carrying the payload of the
* 'subjects()' RPC function.
*/
struct Argument_buffer
{
char *base;
size_t size;
Argument_buffer(Dataspace_capability ds)
:
base(env()->rm_session()->attach(ds)),
size(ds.call<Dataspace::Rpc_size>())
{ }
~Argument_buffer()
{
env()->rm_session()->detach(base);
}
};
Argument_buffer _argument_buffer;
public:
/**
* Constructor
*/
explicit Session_client(Capability<Trace::Session> session)
:
Rpc_client<Trace::Session>(session),
_argument_buffer(call<Rpc_dataspace>())
{ }
/**
* Retrieve subject directory
*/
size_t subjects(Subject_id *dst, size_t dst_len)
{
size_t const num_subjects = min(call<Rpc_subjects>(), dst_len);
memcpy(dst, _argument_buffer.base, dst_len*sizeof(Subject_id));
return num_subjects;
}
Policy_id alloc_policy(size_t size) {
return call<Rpc_alloc_policy>(size); }
Dataspace_capability policy(Policy_id policy_id) {
return call<Rpc_policy>(policy_id); }
void unload_policy(Policy_id policy_id) {
call<Rpc_unload_policy>(policy_id); }
void trace(Subject_id s, Policy_id p, size_t buffer_size) {
call<Rpc_trace>(s, p, buffer_size); }
void rule(Session_label const &label, Thread_name const &thread,
Policy_id policy, size_t buffer_size) {
call<Rpc_rule>(label, thread, policy, buffer_size); }
void pause(Subject_id subject) {
call<Rpc_pause>(subject); }
void resume(Subject_id subject) {
call<Rpc_resume>(subject); }
Subject_info subject_info(Subject_id subject) {
return call<Rpc_subject_info>(subject); }
Dataspace_capability buffer(Subject_id subject) {
return call<Rpc_buffer>(subject); }
void free(Subject_id subject) {
call<Rpc_free>(subject); }
};
#endif /* _INCLUDE__TRACE_SESSION__CLIENT_H_ */

@ -0,0 +1,39 @@
/*
* \brief Connection to TRACE service
* \author Norman Feske
* \date 2013-08-11
*/
/*
* 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 _INCLUDE__TRACE_SESSION__CONNECTION_H_
#define _INCLUDE__TRACE_SESSION__CONNECTION_H_
#include <trace_session/client.h>
#include <base/connection.h>
namespace Genode { namespace Trace { struct Connection; } }
struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
Genode::Trace::Session_client
{
/**
* Constructor
*
* \param ram_quota RAM donated for tracing purposes
* \param arg_buffer_size session argument-buffer size
* \param parent_levels number of parent levels to trace
*/
Connection(size_t ram_quota, size_t arg_buffer_size, unsigned parent_levels) :
Genode::Connection<Session>(
session("ram_quota=%zd, arg_buffer_size=%zd, parent_levels=%u",
ram_quota, arg_buffer_size, parent_levels)),
Session_client(cap()) { }
};
#endif /* _INCLUDE__TRACE_SESSION__CONNECTION_H_ */

@ -0,0 +1,159 @@
/*
* \brief TRACE session interface
* \author Norman Feske
* \date 2013-08-11
*/
/*
* 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 _INCLUDE__TRACE_SESSION__TRACE_SESSION_H_
#define _INCLUDE__TRACE_SESSION__TRACE_SESSION_H_
#include <base/exception.h>
#include <base/trace/types.h>
#include <dataspace/capability.h>
#include <session/session.h>
namespace Genode { namespace Trace { struct Session; } }
struct Genode::Trace::Session : Genode::Session
{
static const char *service_name() { return "TRACE"; }
/**
* Allocate policy-module backing store
*
* \throw Out_of_metadata
*/
virtual Policy_id alloc_policy(size_t size) = 0;
/**
* Request policy-module backing store
*
* \throw Nonexistent_policy
*/
virtual Dataspace_capability policy(Policy_id) = 0;
/**
* Remove a policy module from the TRACE service
*/
virtual void unload_policy(Policy_id) = 0;
/**
* Start tracing of a subject
*
* \throw Out_of_metadata
* \throw Already_traced
* \throw Source_is_dead
* \throw Nonexistent_policy
* \throw Traced_by_other_session
*/
virtual void trace(Subject_id, Policy_id, size_t buffer_size) = 0;
/**
* Install a matching rule for automatically tracing new threads
*/
virtual void rule(Session_label const &, Thread_name const &,
Policy_id, size_t buffer_size) = 0;
/**
* Pause generation of tracing data
*
* \throw Nonexistent_subject
*/
virtual void pause(Subject_id) = 0;
/**
* Resume generation of tracing data
*
* \throw Nonexistent_subject
* \throw Source_is_dead
*/
virtual void resume(Subject_id) = 0;
/**
* Obtain details about tracing subject
*
* \throw Nonexistent_subject
*/
virtual Subject_info subject_info(Subject_id) = 0;
/**
* Obtain trace buffer of given subject
*
* \throw Nonexistent_subject
*/
virtual Dataspace_capability buffer(Subject_id) = 0;
/**
* Release subject and free buffers
*
* If the source still exists, the buffers are freed but the subject
* stays intact.
*
* \throw Nonexistent_subject
*/
virtual void free(Subject_id) = 0;
virtual ~Session() { }
/*********************
** RPC declaration **
*********************/
GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace);
GENODE_RPC_THROW(Rpc_alloc_policy, Policy_id, alloc_policy,
GENODE_TYPE_LIST(Out_of_metadata),
size_t);
GENODE_RPC_THROW(Rpc_policy, Dataspace_capability, policy,
GENODE_TYPE_LIST(Nonexistent_policy),
Policy_id);
GENODE_RPC_THROW(Rpc_unload_policy, void, unload_policy,
GENODE_TYPE_LIST(Nonexistent_policy), Policy_id);
GENODE_RPC_THROW(Rpc_trace, void, trace,
GENODE_TYPE_LIST(Out_of_metadata, Already_traced,
Source_is_dead, Nonexistent_policy,
Traced_by_other_session),
Subject_id, Policy_id, size_t);
GENODE_RPC_THROW(Rpc_rule, void, rule,
GENODE_TYPE_LIST(Out_of_metadata),
Session_label const &, Thread_name const &,
Policy_id, size_t);
GENODE_RPC_THROW(Rpc_pause, void, pause,
GENODE_TYPE_LIST(Nonexistent_subject), Subject_id);
GENODE_RPC_THROW(Rpc_resume, void, resume,
GENODE_TYPE_LIST(Nonexistent_subject, Source_is_dead),
Subject_id);
GENODE_RPC(Rpc_subjects, size_t, subjects);
GENODE_RPC_THROW(Rpc_subject_info, Subject_info, subject_info,
GENODE_TYPE_LIST(Nonexistent_subject), Subject_id);
GENODE_RPC_THROW(Rpc_buffer, Dataspace_capability, buffer,
GENODE_TYPE_LIST(Nonexistent_subject, Subject_not_traced),
Subject_id);
GENODE_RPC_THROW(Rpc_free, void, free,
GENODE_TYPE_LIST(Nonexistent_subject), Subject_id);
typedef Meta::Type_tuple<Rpc_dataspace,
Meta::Type_tuple<Rpc_alloc_policy,
Meta::Type_tuple<Rpc_policy,
Meta::Type_tuple<Rpc_unload_policy,
Meta::Type_tuple<Rpc_trace,
Meta::Type_tuple<Rpc_rule,
Meta::Type_tuple<Rpc_pause,
Meta::Type_tuple<Rpc_resume,
Meta::Type_tuple<Rpc_subjects,
Meta::Type_tuple<Rpc_subject_info,
Meta::Type_tuple<Rpc_buffer,
Meta::Type_tuple<Rpc_free,
Meta::Empty>
> > > > > > > > > > > Rpc_functions;
};
#endif /* _INCLUDE__TRACE_SESSION__TRACE_SESSION_H_ */

@ -32,15 +32,27 @@ void Cpu_thread_component::update_exception_sigh()
};
Thread_capability Cpu_session_component::create_thread(Name const &name,
addr_t utcb)
Thread_capability Cpu_session_component::create_thread(Name const &name,
addr_t utcb)
{
unsigned trace_control_index = 0;
if (!_trace_control_area.alloc(trace_control_index))
throw Out_of_metadata();
Trace::Control * const trace_control =
_trace_control_area.at(trace_control_index);
Trace::Thread_name thread_name(name.string());
Cpu_thread_component *thread = 0;
try {
Lock::Guard slab_lock_guard(_thread_alloc_lock);
thread = new(&_thread_alloc) Cpu_thread_component(name.string(),
thread = new(&_thread_alloc) Cpu_thread_component(_label,
thread_name,
_priority, utcb,
_default_exception_handler);
_default_exception_handler,
trace_control_index,
*trace_control);
} catch (Allocator::Out_of_memory) {
throw Out_of_metadata();
}
@ -48,6 +60,8 @@ Thread_capability Cpu_session_component::create_thread(Name const &name,
Lock::Guard thread_list_lock_guard(_thread_list_lock);
_thread_list.insert(thread);
_trace_sources.insert(thread->trace_source());
return _thread_ep->manage(thread);
}
@ -57,8 +71,14 @@ void Cpu_session_component::_unsynchronized_kill_thread(Cpu_thread_component *th
_thread_ep->dissolve(thread);
_thread_list.remove(thread);
_trace_sources.remove(thread->trace_source());
unsigned const trace_control_index = thread->trace_control_index();
Lock::Guard lock_guard(_thread_alloc_lock);
destroy(&_thread_alloc, thread);
_trace_control_area.free(trace_control_index);
}
@ -199,8 +219,8 @@ void Cpu_session_component::affinity(Thread_capability thread_cap,
/* convert session-local location to physical location */
int const x1 = location.xpos() + _location.xpos(),
y1 = location.ypos() + _location.ypos(),
x2 = location.xpos() + location.width(),
y2 = location.ypos() + location.height();
x2 = location.xpos() + location.width(),
y2 = location.ypos() + location.height();
int const clipped_x1 = max(_location.xpos(), x1),
clipped_y1 = max(_location.ypos(), y1),
@ -215,45 +235,69 @@ void Cpu_session_component::affinity(Thread_capability thread_cap,
Dataspace_capability Cpu_session_component::trace_control()
{
/* not implemented */
return Dataspace_capability();
return _trace_control_area.dataspace();
}
unsigned Cpu_session_component::trace_control_index(Thread_capability thread)
unsigned Cpu_session_component::trace_control_index(Thread_capability thread_cap)
{
/* not implemented */
return 0;
Object_pool<Cpu_thread_component>::Guard thread(_thread_ep->lookup_and_lock(thread_cap));
if (!thread) return 0;
return thread->trace_control_index();
}
Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread)
Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread_cap)
{
/* not implemented */
return Dataspace_capability();
Object_pool<Cpu_thread_component>::Guard thread(_thread_ep->lookup_and_lock(thread_cap));
if (!thread) return Dataspace_capability();
return thread->trace_source()->buffer();
}
Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread)
Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread_cap)
{
/* not implemented */
return Dataspace_capability();
Object_pool<Cpu_thread_component>::Guard thread(_thread_ep->lookup_and_lock(thread_cap));
if (!thread) return Dataspace_capability();
return thread->trace_source()->policy();
}
Cpu_session_component::Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
char const *args,
Affinity const &affinity)
static size_t remaining_session_ram_quota(char const *args)
{
/*
* We don't need to consider an underflow here because
* 'Cpu_root::_create_session' already checks for the condition.
*/
return Arg_string::find_arg(args, "ram_quota").long_value(0)
- Trace::Control_area::SIZE;
}
Cpu_session_component::Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
char const *args,
Affinity const &affinity)
:
_thread_ep(thread_ep), _pager_ep(pager_ep),
_md_alloc(md_alloc, Arg_string::find_arg(args, "ram_quota").long_value(0)),
_md_alloc(md_alloc, remaining_session_ram_quota(args)),
_thread_alloc(&_md_alloc), _priority(0),
/* map affinity to a location within the physical affinity space */
_location(affinity.scale_to(platform()->affinity_space()))
_location(affinity.scale_to(platform()->affinity_space())),
_trace_sources(trace_sources)
{
/* remember session label */
char buf[Session_label::MAX_SIZE];
Arg_string::find_arg(args, "label").string(buf, sizeof(buf), "");
_label = Session_label(buf);
Arg a = Arg_string::find_arg(args, "priority");
if (a.valid()) {
_priority = a.ulong_value(0);
@ -277,3 +321,17 @@ Cpu_session_component::~Cpu_session_component()
for (Cpu_thread_component *thread; (thread = _thread_list.first()); )
_unsynchronized_kill_thread(thread);
}
/****************************
** Trace::Source_registry **
****************************/
unsigned Trace::Source::_alloc_unique_id()
{
static Lock lock;
static unsigned cnt;
Lock::Guard guard(lock);
return cnt++;
}

@ -26,17 +26,25 @@ namespace Genode {
{
private:
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator *_md_alloc;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator *_md_alloc;
Trace::Source_registry &_trace_sources;
protected:
Cpu_session_component *_create_session(char const *args,
Affinity const &affinity) {
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota").long_value(0);
if (ram_quota < Trace::Control_area::SIZE)
throw Root::Quota_exceeded();
return new (md_alloc())
Cpu_session_component(_thread_ep, _pager_ep, _md_alloc,
args, affinity); }
_trace_sources, args, affinity); }
void _upgrade_session(Cpu_session_component *cpu, const char *args)
{
@ -53,13 +61,15 @@ namespace Genode {
* \param thread_ep entry point for managing threads
* \param md_alloc meta data allocator to be used by root component
*/
Cpu_root(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc)
Cpu_root(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources)
:
Root_component<Cpu_session_component>(session_ep, md_alloc),
_thread_ep(thread_ep), _pager_ep(pager_ep), _md_alloc(md_alloc)
_thread_ep(thread_ep), _pager_ep(pager_ep), _md_alloc(md_alloc),
_trace_sources(trace_sources)
{ }
};
}

@ -22,9 +22,11 @@
#include <base/rpc_server.h>
#include <cpu_session/cpu_session.h>
/* Core includes */
/* core includes */
#include <cpu_thread_allocator.h>
#include <platform_thread.h>
#include <trace/control_area.h>
#include <trace/source_registry.h>
namespace Genode {
@ -44,18 +46,33 @@ namespace Genode {
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
{
public:
typedef Trace::Session_label Session_label;
typedef Trace::Thread_name Thread_name;
private:
Thread_name const _name;
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
unsigned const _trace_control_index;
Trace::Source _trace_source;
public:
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
Cpu_thread_component(Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
unsigned trace_control_index,
Trace::Control &trace_control)
:
_platform_thread(name, priority, utcb), _bound(false), _sigh(sigh)
_name(name),
_platform_thread(name.string(), priority, utcb), _bound(false),
_sigh(sigh), _trace_control_index(trace_control_index),
_trace_source(label, _name, trace_control)
{
update_exception_sigh();
}
@ -65,9 +82,10 @@ namespace Genode {
** Accessor functions **
************************/
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
Platform_thread *platform_thread() { return &_platform_thread; }
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
void sigh(Signal_context_capability sigh)
{
@ -79,13 +97,23 @@ namespace Genode {
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
/**
* Return index within the CPU-session's trace control area
*/
unsigned trace_control_index() const { return _trace_control_index; }
};
class Cpu_session_component : public Rpc_object<Cpu_session>
{
public:
typedef Cpu_thread_component::Session_label Session_label;
private:
Session_label _label;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
@ -98,6 +126,8 @@ namespace Genode {
session */
Affinity::Location _location; /* CPU affinity of this
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
/**
* Exception handler that will be invoked unless overridden by a
@ -120,10 +150,11 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc, const char *args,
Affinity const &);
Cpu_session_component(Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
/**
* Destructor
@ -140,7 +171,7 @@ namespace Genode {
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t utcb);
Thread_capability create_thread(Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);