genode/repos/base/src/lib/base/default_log.cc

123 lines
2.8 KiB
C++

/*
* \brief Access to the component's LOG session
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016-2017 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.
*/
/* Genode includes */
#include <util/construct_at.h>
#include <base/log.h>
#include <base/buffered_output.h>
#include <base/sleep.h>
#include <log_session/client.h>
/* base-internal includes */
#include <base/internal/globals.h>
#include <base/internal/unmanaged_singleton.h>
using namespace Genode;
namespace {
/**
* Singleton back end for writing messages to the component's log session
*/
struct Back_end : Noncopyable
{
Log_session_client _client;
static Session_capability _cap(Parent &parent) {
return parent.session_cap(Parent::Env::log()); }
Back_end(Parent &parent)
: _client(reinterpret_cap_cast<Log_session>(_cap(parent))) { }
void write(char const *string) { (void)_client.write(string); }
};
}
static Back_end *back_end_ptr;
/**
* Singleton instance of the 'Log' interface
*/
static Log *log_ptr;
Log &Log::log()
{
if (log_ptr)
return *log_ptr;
raw("Error: Missing call of init_log");
sleep_forever();
}
static Trace_output *trace_ptr;
Trace_output &Trace_output::trace_output()
{
if (trace_ptr)
return *trace_ptr;
raw("Error: Missing call of init_log");
sleep_forever();
}
/**
* Hook for support the 'fork' implementation of the noux libc backend
*/
extern "C" void stdout_reconnect(Parent &parent)
{
/*
* We cannot use a 'Reconstructible' because we have to skip
* the object destruction inside a freshly forked process.
* Otherwise, the attempt to destruct the capability contained
* in the 'Log' object would result in an inconsistent ref counter
* of the respective capability-space element.
*/
construct_at<Back_end>(back_end_ptr, parent);
}
void Genode::init_log(Parent &parent)
{
/* ignore subsequent calls */
if (log_ptr)
return;
back_end_ptr = unmanaged_singleton<Back_end>(parent);
struct Write_fn { void operator () (char const *s) { back_end_ptr->write(s); } };
typedef Buffered_output<Log_session::MAX_STRING_LEN, Write_fn>
Buffered_log_output;
static Buffered_log_output *buffered_log_output =
unmanaged_singleton<Buffered_log_output>(Write_fn());
log_ptr = unmanaged_singleton<Log>(*buffered_log_output);
/* enable trace back end */
struct Write_trace_fn { void operator () (char const *s) { Thread::trace(s); } };
typedef Buffered_output<Log_session::MAX_STRING_LEN, Write_trace_fn>
Buffered_trace_output;
static Buffered_trace_output *buffered_trace_output =
unmanaged_singleton<Buffered_trace_output>(Write_trace_fn());
trace_ptr = unmanaged_singleton<Trace_output>(*buffered_trace_output);
}