base: User-level tracing support

This commit is contained in:
Norman Feske 2013-08-09 20:48:32 +02:00
parent a2b15349fd
commit fe4a6d7d81
19 changed files with 816 additions and 21 deletions

View File

@ -20,12 +20,13 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
SRC_CC += env/utcb.cc
SRC_CC += lock/cmpxchg.cc
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/include/codezero/dummies
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
INC_DIR += $(REP_DIR)/include/codezero/dummies
vpath cap_copy.cc $(BASE_DIR)/src/platform
vpath %.cc $(REP_DIR)/src/base

View File

@ -20,9 +20,10 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap_empty.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap_empty.cc thread/trace.cc
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
vpath cap_copy.cc $(BASE_DIR)/src/platform
vpath %.cc $(REP_DIR)/src/base

View File

@ -20,9 +20,11 @@ SRC_CC += lock/lock.cc
SRC_CC += env/spin_lock.cc env/cap_map.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
vpath %.cc $(REP_DIR)/src/base
vpath %.cc $(BASE_DIR)/src/base

View File

@ -182,7 +182,8 @@ void Thread_base::name(char *dst, size_t dst_len)
}
Thread_base *Thread_base::myself() {
Thread_base *Thread_base::myself()
{
using namespace Fiasco;
return reinterpret_cast<Thread_base*>(l4_utcb_tcr()->user[UTCB_TCR_THREAD_OBJ]);

View File

@ -18,9 +18,11 @@ SRC_CC += console/console.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread_bootstrap.cc
SRC_CC += thread/thread_bootstrap.cc thread/trace.cc
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
vpath %.cc $(REP_DIR)/src/base
vpath %.cc $(BASE_DIR)/src/base

View File

@ -19,11 +19,13 @@ SRC_CC += lock/lock.cc
SRC_CC += env/rm_session_mmap.cc env/debug.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/trace.cc
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/ipc
INC_DIR += $(REP_DIR)/src/base/env
INC_DIR += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/ipc
INC_DIR += $(REP_DIR)/src/base/env
INC_DIR += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform
INC_DIR += $(BASE_DIR)/src/base/thread
vpath %.cc $(REP_DIR)/src/base
vpath %.cc $(BASE_DIR)/src/base

View File

@ -28,7 +28,7 @@ INC_DIR += $(REP_DIR)/src/core/include \
$(REP_DIR)/src/platform \
$(REP_DIR)/src/base/ipc \
$(REP_DIR)/src/base/env \
$(REP_DIR)/src/base/console
$(REP_DIR)/src/base/console \
HOST_INC_DIR += /usr/include
@ -50,4 +50,5 @@ vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_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
vpath %.cc $(PRG_DIR)

View File

@ -18,9 +18,11 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc
SRC_CC += thread/thread.cc thread/thread_context.cc
SRC_CC += thread/thread.cc thread/thread_context.cc thread/trace.cc
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
vpath %.cc $(REP_DIR)/src/base
vpath %.cc $(BASE_DIR)/src/base

View File

@ -20,9 +20,10 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
vpath cap_copy.cc $(BASE_DIR)/src/platform
vpath %.cc $(REP_DIR)/src/base

View File

@ -20,9 +20,10 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc
SRC_CC += thread/thread.cc thread/trace.cc thread/thread_bootstrap.cc
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/thread
vpath cap_copy.cc $(BASE_DIR)/src/platform
vpath %.cc $(REP_DIR)/src/base

View File

@ -55,6 +55,7 @@
#include <base/exception.h>
#include <base/lock.h>
#include <base/native_types.h>
#include <base/trace/logger.h>
#include <util/list.h>
#include <ram_session/ram_session.h> /* for 'Ram_dataspace_capability' type */
#include <cpu_session/cpu_session.h> /* for 'Thread_capability' type */
@ -259,6 +260,17 @@ namespace Genode {
*/
Genode::Lock _join_lock;
private:
Trace::Logger _trace_logger;
/**
* Return 'Trace::Logger' instance of calling thread
*
* This function is used by the tracing framework internally.
*/
static Trace::Logger *_logger();
public:
/**
@ -355,6 +367,22 @@ namespace Genode {
* undefined behaviour.
*/
void join();
/**
* Log null-terminated string as trace event
*/
static void trace(char const *);
/**
* Log binary data as trace event
*/
static void trace(char const *, size_t len);
/**
* Log trace event as defined in base/trace.h
*/
template <typename EVENT>
static void trace(EVENT const *event) { _logger()->log(event); }
};

View File

@ -0,0 +1,96 @@
/*
* \brief Event tracing infrastructure
* \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 _INCLUDE__BASE__TRACE__BUFFER_H_
#define _INCLUDE__BASE__TRACE__BUFFER_H_
#include <base/stdint.h>
#include <base/thread.h>
#include <cpu_session/cpu_session.h>
namespace Genode { namespace Trace { class Buffer; } }
/**
* Buffer shared between CPU client thread and TRACE client
*/
class Genode::Trace::Buffer
{
private:
unsigned volatile _head_offset; /* in bytes, relative to 'entries' */
unsigned volatile _size; /* in bytes */
struct Entry
{
size_t len;
char data[0];
};
Entry _entries[0];
Entry *_head_entry() { return (Entry *)((addr_t)_entries + _head_offset); }
/*
* The 'entries' member marks the beginning of the trace buffer
* entries. No other member variables must follow.
*/
public:
/******************************************
** Functions called from the CPU client **
******************************************/
void init(size_t size)
{
_head_offset = 0;
/* compute number of bytes available for tracing data */
size_t const header_size = (addr_t)&_entries - (addr_t)this;
_size = size - header_size;
}
char *reserve(size_t len)
{
if (_head_offset + sizeof(Entry) + len <= _size)
return _head_entry()->data;
/* mark last entry with len 0 and wrap */
_head_entry()->len = 0;
_head_offset = 0;
return _head_entry()->data;
}
void commit(size_t len)
{
_head_entry()->len = len;
/* advance head offset, wrap when reaching buffer boundary */
_head_offset += sizeof(Entry) + len;
if (_head_offset == _size)
_head_offset = 0;
}
/********************************************
** Functions called from the TRACE client **
********************************************/
addr_t entries() const { return (addr_t)_entries; }
addr_t head_offset() const { return (addr_t)_head_offset; }
};
#endif /* _INCLUDE__BASE__TRACE__BUFFER_H_ */

View File

@ -0,0 +1,124 @@
/*
* \brief Trace-event definitions
* \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 _INCLUDE__BASE__TRACE__EVENTS_H_
#define _INCLUDE__BASE__TRACE__EVENTS_H_
#include <base/thread.h>
#include <base/trace/policy.h>
namespace Genode { namespace Trace {
struct Rpc_call;
struct Rpc_returned;
struct Rpc_dispatch;
struct Rpc_reply;
struct Signal_submit;
struct Signal_received;
} }
struct Genode::Trace::Rpc_call
{
char const *rpc_name;
Msgbuf_base const &msg;
Rpc_call(char const *rpc_name, Msgbuf_base const &msg)
: rpc_name(rpc_name), msg(msg)
{
Thread_base::trace(this);
}
size_t generate(Policy_module &policy, char *dst) const {
return policy.rpc_call(dst, rpc_name, msg); }
};
struct Genode::Trace::Rpc_returned
{
char const *rpc_name;
Msgbuf_base const &msg;
Rpc_returned(char const *rpc_name, Msgbuf_base const &msg)
: rpc_name(rpc_name), msg(msg)
{
Thread_base::trace(this);
}
size_t generate(Policy_module &policy, char *dst) const {
return policy.rpc_returned(dst, rpc_name, msg); }
};
struct Genode::Trace::Rpc_dispatch
{
char const *rpc_name;
Rpc_object_base const &obj;
Msgbuf_base const &msg;
Rpc_dispatch(char const *rpc_name, Rpc_object_base const &obj,
Msgbuf_base const &msg)
:
rpc_name(rpc_name), obj(obj), msg(msg)
{
Thread_base::trace(this);
}
size_t generate(Policy_module &policy, char *dst) const {
return policy.rpc_dispatch(dst, rpc_name, obj, msg); }
};
struct Genode::Trace::Rpc_reply
{
char const *rpc_name;
Rpc_object_base const &obj;
Msgbuf_base const &msg;
Rpc_reply(char const *rpc_name, Rpc_object_base const &obj,
Msgbuf_base const &msg)
:
rpc_name(rpc_name), obj(obj), msg(msg)
{
Thread_base::trace(this);
}
size_t generate(Policy_module &policy, char *dst) const {
return policy.rpc_reply(dst, rpc_name, obj, msg); }
};
struct Genode::Trace::Signal_submit
{
unsigned const num;
Signal_submit(unsigned const num) : num(num)
{ Thread_base::trace(this); }
size_t generate(Policy_module &policy, char *dst) const {
return policy.signal_submit(dst, num); }
};
struct Genode::Trace::Signal_received
{
Signal const &signal;;
Signal_received(Signal const &signal) : signal(signal)
{ Thread_base::trace(this); }
size_t generate(Policy_module &policy, char *dst) const {
return policy.signal_received(dst, signal); }
};
#endif /* _INCLUDE__BASE__TRACE__EVENTS_H_ */

View File

@ -0,0 +1,76 @@
/*
* \brief Event tracing infrastructure
* \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 _INCLUDE__BASE__TRACE__LOGGER_H_
#define _INCLUDE__BASE__TRACE__LOGGER_H_
#include <base/trace/buffer.h>
#include <cpu_session/cpu_session.h>
namespace Genode { namespace Trace {
class Control;
class Policy_module;
class Logger;
} }
/**
* Facility for logging events to a thread-specific buffer
*/
struct Genode::Trace::Logger
{
private:
Thread_capability thread_cap;
Control *control;
bool enabled;
unsigned policy_version;
Policy_module *policy_module;
Buffer *buffer;
size_t max_event_size;
bool pending_init;
bool _evaluate_control();
public:
Logger();
bool is_initialized() { return control != 0; }
bool is_init_pending() { return pending_init; }
void init_pending(bool val) { pending_init = val; }
void init(Thread_capability);
/**
* Log binary data to trace buffer
*/
void log(char const *, size_t);
/**
* Log event to trace buffer
*/
template <typename EVENT>
void log(EVENT const *event)
{
if (!this || !_evaluate_control()) return;
buffer->commit(event->generate(*policy_module, buffer->reserve(max_event_size)));
}
};
#endif /* _INCLUDE__BASE__TRACE__LOGGER_H_ */

View File

@ -0,0 +1,43 @@
/*
* \brief Event tracing infrastructure
* \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 _INCLUDE__BASE__TRACE__POLICY_H_
#define _INCLUDE__BASE__TRACE__POLICY_H_
#include <base/stdint.h>
namespace Genode {
class Msgbuf_base;
class Signal;
class Rpc_object_base;
namespace Trace { class Policy_module; }
}
/**
* Header of tracing policy
*/
struct Genode::Trace::Policy_module
{
size_t (*max_event_size) ();
size_t (*rpc_call) (char *, char const *, Msgbuf_base const &);
size_t (*rpc_returned) (char *, char const *, Msgbuf_base const &);
size_t (*rpc_dispatch) (char *, char const *);
size_t (*rpc_reply) (char *, char const *);
size_t (*signal_submit) (char *, unsigned const);
size_t (*signal_received) (char *, Signal const &);
};
#endif /* _INCLUDE__BASE__TRACE__POLICY_H_ */

View File

@ -0,0 +1,231 @@
/*
* \brief Event-tracing support
* \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.
*/
/* Genode includes */
#include <base/env.h>
#include <base/thread.h>
#include <base/trace/policy.h>
#include <dataspace/client.h>
/* local includes */
#include <trace/control.h>
using namespace Genode;
namespace Genode { bool inhibit_tracing = true; /* cleared by '_main' */ }
/**
* Return trace-control structure for specified thread
*/
static Trace::Control *trace_control(Cpu_session *cpu, Rm_session *rm,
Thread_capability thread_cap)
{
struct Area
{
Cpu_session &cpu;
Rm_session &rm;
Dataspace_capability ds;
size_t const size;
Trace::Control * const base;
Area(Cpu_session &cpu, Rm_session &rm)
:
cpu(cpu), rm(rm),
ds(cpu.trace_control()),
size(ds.valid() ? Dataspace_client(ds).size() : 0),
base(ds.valid() ? (Trace::Control * const)rm.attach(ds) : 0)
{ }
Trace::Control *slot(Thread_capability thread)
{
if (!thread.valid() || base == 0)
return 0;
unsigned const index = cpu.trace_control_index(thread);
if ((index + 1)*sizeof(Trace::Control) > size) {
PERR("thread control index is out of range");
return 0;
}
return base + index;
}
};
static Area area(*cpu, *rm);
return area.slot(thread_cap);
}
/*******************
** Trace::Logger **
*******************/
bool Trace::Logger::_evaluate_control()
{
/* check process-global and thread-specific tracing condition */
if (inhibit_tracing || !control || control->tracing_inhibited())
return false;
if (control->state_changed()) {
/* suppress tracing during initialization */
Control::Inhibit_guard guard(*control);
if (control->to_be_disabled()) {
/* unload policy */
if (policy_module) {
env()->rm_session()->detach(policy_module);
policy_module = 0;
}
/* unmap trace buffer */
if (buffer) {
env()->rm_session()->detach(buffer);
buffer = 0;
}
/* inhibit generation of trace events */
enabled = false;
control->acknowledge_disabled();
}
else if (control->to_be_enabled()) {
control->acknowledge_enabled();
enabled = true;
}
}
if (enabled && (policy_version != control->policy_version())) {
/* suppress tracing during policy change */
Control::Inhibit_guard guard(*control);
/* obtain policy */
Dataspace_capability policy_ds = env()->cpu_session()->trace_policy(thread_cap);
if (!policy_ds.valid()) {
PWRN("could not obtain trace policy");
control->error();
enabled = false;
return false;
}
try {
max_event_size = 0;
policy_module = 0;
policy_module = env()->rm_session()->attach(policy_ds);
/* relocate function pointers of policy callback table */
for (unsigned i = 0; i < sizeof(Trace::Policy_module)/sizeof(void *); i++) {
((addr_t *)policy_module)[i] += (addr_t)(policy_module);
}
max_event_size = policy_module->max_event_size();
} catch (...) { }
/* obtain buffer */
buffer = 0;
Dataspace_capability buffer_ds = env()->cpu_session()->trace_buffer(thread_cap);
if (!buffer_ds.valid()) {
PWRN("could not obtain trace buffer");
control->error();
enabled = false;
return false;
}
try {
buffer = env()->rm_session()->attach(buffer_ds);
buffer->init(Dataspace_client(buffer_ds).size());
} catch (...) { }
policy_version = control->policy_version();
}
return enabled && policy_module;
}
void Trace::Logger::log(char const *msg, size_t len)
{
if (!this || !_evaluate_control()) return;
memcpy(buffer->reserve(len), msg, len);
buffer->commit(len);
}
void Trace::Logger::init(Thread_capability thread)
{
thread_cap = thread;
control = trace_control(env()->cpu_session(), env()->rm_session(), thread);
}
Trace::Logger::Logger()
:
thread_cap(thread_cap),
control(0),
enabled(false),
policy_version(0),
policy_module(0),
max_event_size(0),
pending_init(false)
{ }
/*****************
** Thread_base **
*****************/
/**
* return logger instance for the main thread **
*/
static Trace::Logger *main_trace_logger()
{
static Trace::Logger logger;
return &logger;
}
Trace::Logger *Thread_base::_logger()
{
if (inhibit_tracing)
return 0;
Thread_base * const myself = Thread_base::myself();
Trace::Logger * const logger = myself ? &myself->_trace_logger
: main_trace_logger();
/* logger is already being initialized */
if (logger->is_init_pending())
return logger;
/* lazily initialize trace object */
if (!logger->is_initialized()) {
logger->init_pending(true);
logger->init(myself ? myself->_thread_cap : env()->parent()->main_thread_cap());
}
return logger;
}

View File

@ -0,0 +1,167 @@
/*
* \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_ */

View File

@ -171,8 +171,15 @@ class Core_child : public Child_policy
** Core main **
***************/
namespace Genode { extern bool inhibit_tracing; }
int main()
{
/**
* Disable tracing within core because it is currently not fully implemented.
*/
inhibit_tracing = true;
PDBG("--- create local services ---");
/*

View File

@ -220,6 +220,9 @@ int genode_argc = 1;
char **genode_envp = 0;
namespace Genode { extern bool inhibit_tracing; }
/**
* C entry function called by the crt0 startup code
*/
@ -227,6 +230,9 @@ extern "C" int _main()
{
main_thread_bootstrap();
/* call env() explicitly to setup the environment */
(void*)env();
/* initialize exception handling */
init_exception_handling();
@ -258,6 +264,9 @@ extern "C" int _main()
/* create the thread context area RM session */
env_context_area_rm_session();
/* enable tracing support */
inhibit_tracing = false;
/* call real main function */
int ret = main(genode_argc, genode_argv, genode_envp);