base: new interface for textual output

Issue #1942
This commit is contained in:
Norman Feske 2016-05-03 16:31:17 +02:00
parent 3bceefc9cf
commit 1f395ae780
22 changed files with 693 additions and 95 deletions

View File

@ -9,6 +9,7 @@ SRC_CC += stack_area.cc \
cpu_session_component.cc \
cpu_session_support.cc \
dataspace_component.cc \
default_log.cc \
dump_alloc.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
@ -64,6 +65,7 @@ vpath io_mem_session_support.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 default_log.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
vpath pager_ep.cc $(GEN_CORE_DIR)

View File

@ -12,6 +12,7 @@ SRC_CC += stack_area.cc \
cpu_session_component.cc \
cpu_session_support.cc \
dataspace_component.cc \
default_log.cc \
dump_alloc.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
@ -52,6 +53,7 @@ vpath cpu_session_component.cc $(GEN_CORE_DIR)
vpath cpu_session_support.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath default_log.cc $(GEN_CORE_DIR)
vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath main.cc $(GEN_CORE_DIR)

View File

@ -22,6 +22,7 @@ SRC_CC += core_region_map.cc
SRC_CC += core_mem_alloc.cc
SRC_CC += core_rpc_cap_alloc.cc
SRC_CC += dataspace_component.cc
SRC_CC += default_log.cc
SRC_CC += dump_alloc.cc
SRC_CC += io_mem_session_component.cc
SRC_CC += io_mem_session_support.cc

View File

@ -26,6 +26,7 @@ SRC_CC = main.cc \
thread_linux.cc \
stack_area.cc \
core_printf.cc \
default_log.cc \
env_reinit.cc \
thread.cc thread_myself.cc
@ -49,6 +50,7 @@ vpath platform_services.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
vpath default_log.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/lib/base
vpath thread.cc $(BASE_DIR)/src/lib/base
vpath thread_myself.cc $(BASE_DIR)/src/lib/base

View File

@ -19,6 +19,7 @@
/* base-internal includes */
#include <base/internal/native_thread.h>
#include <base/internal/globals.h>
extern "C" int raw_write_str(const char *str);
@ -109,6 +110,7 @@ void Genode::call_global_static_constructors() { }
int main()
{
Genode::init_log();
Genode::bootstrap_component();
/* never reached */

View File

@ -12,6 +12,7 @@ SRC_CC = stack_area.cc \
cpu_session_extension.cc \
cpu_session_support.cc \
dataspace_component.cc \
default_log.cc \
dump_alloc.cc \
echo.cc \
io_mem_session_component.cc \
@ -61,6 +62,7 @@ vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
vpath default_log.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath platform_services.cc $(GEN_CORE_DIR)/spec/x86
vpath stack_area.cc $(GEN_CORE_DIR)

View File

@ -12,6 +12,7 @@ SRC_CC += stack_area.cc \
cpu_session_component.cc \
cpu_session_support.cc \
dataspace_component.cc \
default_log.cc \
dump_alloc.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
@ -60,6 +61,7 @@ vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath default_log.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
vpath pager_ep.cc $(GEN_CORE_DIR)
vpath %.cc $(REP_DIR)/src/core

View File

@ -11,6 +11,7 @@ SRC_CC = stack_area.cc \
cpu_session_component.cc \
cpu_session_platform.cc \
dataspace_component.cc \
default_log.cc \
dump_alloc.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
@ -59,6 +60,7 @@ 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 default_log.cc $(GEN_CORE_DIR)
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
vpath core_region_map.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)

View File

@ -1,5 +1,6 @@
SRC_CC = core_printf.cc
INC_DIR += $(REP_DIR)/src/include
SRC_CC = core_printf.cc default_log.cc
INC_DIR += $(REP_DIR)/src/include $(BASE_DIR)/src/include
LIBS += syscall
vpath core_printf.cc $(BASE_DIR)/src/lib/base
vpath default_log.cc $(BASE_DIR)/src/core

View File

@ -0,0 +1,109 @@
/*
* \brief LOG output functions
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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__LOG_H_
#define _INCLUDE__BASE__LOG_H_
#include <base/output.h>
#include <base/lock.h>
namespace Genode { class Log; }
/**
* Interface for writing output to the component's LOG session
*
* The LOG session is not used directly by the 'log', 'warning', and
* 'error' functions. They access the LOG indirectly via this interface
* instead, which ensures the proper synchronization of the output in the
* presence of multiple threads and to apply distinguishable colors to the
* different types of messages.
*/
class Genode::Log
{
public:
/**
* Type of message
*/
enum Type { LOG, WARNING, ERROR };
private:
Lock _lock;
void _acquire(Type);
void _release();
Output &_output;
/**
* Helper for the sequential output of a variable list of arguments
*/
template <typename HEAD, typename... TAIL>
void _output_args(Output &output, HEAD && head, TAIL &&... tail)
{
print(output, head);
_output_args(output, tail...);
}
template <typename LAST>
void _output_args(Output &output, LAST && last) { print(output, last); }
public:
Log(Output &output) : _output(output) { }
template <typename... ARGS>
void output(Type type, ARGS &&... args)
{
/*
* This function is being inlined. Hence, we try to keep it as
* small as possible. For this reason, the lock operations are
* performed by the '_acquire' and '_release' functions instead of
* using a lock guard.
*/
_acquire(type);
_output_args(_output, args...);
_release();
}
/**
* Return component-global singleton instance of the 'Log'
*/
static Log &log();
};
namespace Genode {
/**
* Write 'args' as a regular message to the log
*/
template <typename... ARGS>
void log(ARGS &&... args) { Log::log().output(Log::LOG, args...); }
/**
* Write 'args' as a warning message to the log
*/
template <typename... ARGS>
void warning(ARGS &&... args) { Log::log().output(Log::WARNING, args...); }
/**
* Write 'args' as an error message to the log
*/
template <typename... ARGS>
void error(ARGS &&... args) { Log::log().output(Log::ERROR, args...); }
}
#endif /* _INCLUDE__BASE__LOG_H_ */

View File

@ -0,0 +1,154 @@
/*
* \brief Interface for textual output
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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__OUTPUT_H_
#define _INCLUDE__BASE__OUTPUT_H_
#include <util/string.h>
#include <base/stdint.h>
namespace Genode { struct Output; }
struct Genode::Output
{
/**
* Output single character
*/
virtual void out_char(char) = 0;
/**
* Output string
*
* \param n maximum number of characters to output
*
* The output stops on the first occurrence of a null character in the
* string or after 'n' characters.
*
* The default implementation uses 'out_char'. This method may be
* overridden by the backend for improving efficiency.
*/
virtual void out_string(char const *str, size_t n = ~0UL);
};
namespace Genode {
/**
* Print null-terminated string
*/
void print(Output &output, char const *);
/**
* Print pointer value
*/
void print(Output &output, void const *);
/**
* Print arbitrary pointer types
*
* This function template takes precedence over the one that takes a
* constant object reference as argument.
*/
template <typename T>
static inline void print(Output &output, T *ptr)
{
print(output, (void const *)ptr);
}
/**
* Print unsigned long value
*/
void print(Output &output, unsigned long);
/**
* Print unsigned integer value
*/
static inline void print(Output &output, unsigned value)
{
print(output, (unsigned long)value);
}
/**
* Print signed long value
*/
void print(Output &output, long);
/**
* Print signed integer value
*/
static inline void print(Output &output, int value)
{
print(output, (long)value);
}
/**
* Print signed long long value
*/
void print(Output &output, long long);
/**
* Helper for the hexadecimal output of integer values
*
* To output an integer value as hexadecimal number, the value can be
* wrapped into an 'Hex' object, thereby selecting the corresponding
* overloaded 'print' function below.
*/
struct Hex
{
enum Prefix { PREFIX, OMIT_PREFIX };
enum Pad { PAD, NO_PAD };
unsigned long const value;
size_t const digits;
Prefix const prefix;
Pad const pad;
/**
* Constructor
*
* \param prefix by default, the value is prepended with the prefix
* '0x'. The prefix can be suppressed by specifying
* 'OMIT_PREFIX' as argument.
* \param pad by default, leading zeros are stripped from the
* output. If set to 'PAD', the leading zeros will be
* printed.
*/
template <typename T>
explicit Hex(T value, Prefix prefix = PREFIX, Pad pad = NO_PAD)
: value(value), digits(2*sizeof(T)), prefix(prefix), pad(pad) { }
};
/**
* Print hexadecimal number
*/
void print(Output &output, Hex const &);
/**
* Print information about object 'obj'
*
* The object type must provide a const 'print(Output &)' method that
* produces the textual representation of the object.
*
* In contrast to overloads of the 'Genode::print' function, the 'T::print'
* method is able to access object-internal state, which can thereby be
* incorporated into the textual output.
*/
template <typename T>
static inline void print(Output &output, T const &obj)
{
obj.print(output);
}
}
#endif /* _INCLUDE__BASE__OUTPUT_H_ */

View File

@ -11,11 +11,13 @@ SRC_CC += slab.cc
SRC_CC += allocator_avl.cc
SRC_CC += heap.cc sliced_heap.cc
SRC_CC += console.cc
SRC_CC += output.cc
SRC_CC += child.cc
SRC_CC += child_process.cc
SRC_CC += elf_binary.cc
SRC_CC += ipc.cc
SRC_CC += lock.cc
SRC_CC += log.cc
SRC_CC += rpc_entrypoint.cc
SRC_CC += signal.cc signal_common.cc
SRC_CC += sleep.cc

View File

@ -1,4 +1,4 @@
SRC_CC += log_console.cc
SRC_CC += log_console.cc default_log.cc
SRC_CC += env_deprecated.cc stack_area.cc env_reinit.cc
SRC_CC += rpc_cap_alloc.cc

View File

@ -0,0 +1,51 @@
/*
* \brief Access to the core's log facility
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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/log.h>
#include <base/printf.h>
/* base-internal includes */
#include <base/internal/globals.h>
#include <base/internal/output.h>
#include <base/internal/unmanaged_singleton.h>
using namespace Genode;
static Log *log_ptr;
Log &Log::log() { return *log_ptr; }
void Genode::init_log()
{
/* ignore subsequent calls */
if (log_ptr)
return;
/*
* Currently, we still rely on the old format-string support and
* produce output via 'core_printf.cc'.
*/
struct Write_fn { void operator () (char const *s) { printf("%s", s); } };
typedef Buffered_output<512, 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);
}

View File

@ -16,6 +16,7 @@
#include <base/sleep.h>
#include <base/service.h>
#include <base/child.h>
#include <base/log.h>
#include <rm_session/connection.h>
#include <pd_session/connection.h>
#include <rom_session/connection.h>
@ -225,7 +226,7 @@ int main()
*/
inhibit_tracing = true;
PINF("Genode %s", Genode::version_string);
log("Genode ", Genode::version_string);
PDBG("--- create local services ---");

View File

@ -26,6 +26,7 @@ namespace Genode {
extern Ram_session *env_stack_area_ram_session;
void init_signal_thread();
void init_log();
}
#endif /* _INCLUDE__BASE__INTERNAL__GLOBALS_H_ */

View File

@ -0,0 +1,160 @@
/*
* \brief Internal utilities used for implementing the 'Output' funtions
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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__INTERNAL__OUTPUT_H_
#define _INCLUDE__BASE__INTERNAL__OUTPUT_H_
#include <base/output.h>
using namespace Genode;
/**
* Convert digit to ASCII value
*/
static inline char ascii(int digit, int uppercase = 0)
{
if (digit > 9)
return digit + (uppercase ? 'A' : 'a') - 10;
return digit + '0';
}
/**
* Output signed value with the specified base
*/
template <typename T, typename OUT_CHAR_FN>
static inline void out_signed(T value, unsigned base, OUT_CHAR_FN const &out_char)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
/* set flag if value is negative */
int neg = value < 0 ? 1 : 0;
/* get absolute value */
value = value < 0 ? -value : value;
int i = 0;
/* handle zero as special case */
if (value == 0)
buf[i++] = ascii(0);
/* fill buffer starting with the least significant digits */
else
for (; value > 0; value /= base)
buf[i++] = ascii(value % base);
/* add sign to buffer for negative values */
if (neg)
out_char('-');
/* output buffer in reverse order */
for (; i--; )
out_char(buf[i]);
}
/**
* Output unsigned value with the specified base and padding
*/
template <typename T, typename OUT_CHAR_FN>
static inline void out_unsigned(T value, unsigned base, int pad,
OUT_CHAR_FN const &out_char)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
int i = 0;
/* handle zero as special case */
if (value == 0) {
buf[i++] = ascii(0);
pad--;
}
/* fill buffer starting with the least significant digits */
for (; value > 0; value /= base, pad--)
buf[i++] = ascii(value % base);
/* add padding zeros */
for (; pad-- > 0; )
out_char(ascii(0));
/* output buffer in reverse order */
for (; i--; )
out_char(buf[i]);
}
namespace Genode { template <size_t, typename> class Buffered_output; }
/**
* Implementation of the output interface that buffers characters
*
* \param BUF_SIZE maximum number of characters to buffer before writing
* \param WRITE_FN functor called to writing the buffered characters to a
* backend.
*
* The 'WRITE_FN' functor is called with a null-terminated 'char const *'
* as argument.
*/
template <size_t BUF_SIZE, typename BACKEND_WRITE_FN>
class Genode::Buffered_output : public Output
{
private:
BACKEND_WRITE_FN _write_fn;
char _buf[BUF_SIZE];
unsigned _num_chars = 0;
void _flush()
{
/* null-terminate string */
_buf[_num_chars] = 0;
_write_fn(_buf);
/* restart with empty buffer */
_num_chars = 0;
}
public:
Buffered_output(BACKEND_WRITE_FN const &write_fn) : _write_fn(write_fn) { }
void out_char(char c) override
{
/* ensure enough buffer space for complete escape sequence */
if ((c == 27) && (_num_chars + 8 > BUF_SIZE)) _flush();
_buf[_num_chars++] = c;
/* flush immediately on line break */
if (c == '\n' || _num_chars >= sizeof(_buf) - 1)
_flush();
}
};
#endif /* _INCLUDE__BASE__INTERNAL__OUTPUT_H_ */

View File

@ -17,9 +17,13 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/console.h>
#include <base/stdint.h>
/* base-internal includes */
#include <base/internal/output.h>
using namespace Genode;
@ -138,93 +142,6 @@ class Format_command
};
/**
* Convert digit to ASCII value
*/
static char ascii(int digit, int uppercase = 0)
{
if (digit > 9)
return digit + (uppercase ? 'A' : 'a') - 10;
return digit + '0';
}
/**
* Output signed value with the specified base
*/
template <typename T>
void Console::_out_signed(T value, unsigned base)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
/* set flag if value is negative */
int neg = value < 0 ? 1 : 0;
/* get absolute value */
value = value < 0 ? -value : value;
int i = 0;
/* handle zero as special case */
if (value == 0)
buf[i++] = ascii(0);
/* fill buffer starting with the least significant digits */
else
for (; value > 0; value /= base)
buf[i++] = ascii(value % base);
/* add sign to buffer for negative values */
if (neg)
_out_char('-');
/* output buffer in reverse order */
for (; i--; )
_out_char(buf[i]);
}
/**
* Output unsigned value with the specified base and padding
*/
template <typename T>
void Console::_out_unsigned(T value, unsigned base, int pad)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
int i = 0;
/* handle zero as special case */
if (value == 0) {
buf[i++] = ascii(0);
pad--;
}
/* fill buffer starting with the least significant digits */
for (; value > 0; value /= base, pad--)
buf[i++] = ascii(value % base);
/* add padding zeros */
for (; pad-- > 0; )
_out_char(ascii(0));
/* output buffer in reverse order */
for (; i--; )
_out_char(buf[i]);
}
void Console::_out_string(const char *str)
{
if (!str)
@ -292,15 +209,18 @@ void Console::vprintf(const char *format, va_list list)
case Format_command::INT:
if (cmd.length == Format_command::LONG_LONG)
_out_signed<long long>(numeric_arg, cmd.base);
out_signed<long long>(numeric_arg, cmd.base,
[&] (char c) { _out_char(c); });
else
_out_signed<long>(numeric_arg, cmd.base);
out_signed<long>(numeric_arg, cmd.base,
[&] (char c) { _out_char(c); });
break;
case Format_command::UINT:
if (cmd.length == Format_command::LONG_LONG) {
_out_unsigned<unsigned long long>(numeric_arg, cmd.base, cmd.padding);
out_unsigned<unsigned long long>(numeric_arg, cmd.base, cmd.padding,
[&] (char c) { _out_char(c); });
break;
}
@ -308,7 +228,8 @@ void Console::vprintf(const char *format, va_list list)
case Format_command::PTR:
_out_unsigned<unsigned long>(numeric_arg, cmd.base, cmd.padding);
out_unsigned<unsigned long>(numeric_arg, cmd.base, cmd.padding,
[&] (char c) { _out_char(c); });
break;
case Format_command::CHAR:

View File

@ -0,0 +1,51 @@
/*
* \brief Access to the component's LOG session
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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/log.h>
#include <log_session/log_session.h>
/* base-internal includes */
#include <base/internal/globals.h>
#include <base/internal/output.h>
#include <base/internal/unmanaged_singleton.h>
using namespace Genode;
static Log *log_ptr;
Log &Log::log() { return *log_ptr; }
extern "C" int stdout_write(const char *s);
void Genode::init_log()
{
/* ignore subsequent calls */
if (log_ptr)
return;
struct Write_fn { void operator () (char const *s) { stdout_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);
}

View File

@ -0,0 +1,44 @@
/*
* \brief Access to the component's LOG session
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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/log.h>
using namespace Genode;
void Log::_acquire(Type type)
{
_lock.lock();
/*
* Mark warnings and errors via distinct colors.
*/
switch (type) {
case LOG: break;
case WARNING: _output.out_string("\033[34mWarning: "); break;
case ERROR: _output.out_string("\033[31mError: "); break;
};
}
void Log::_release()
{
/*
* Reset color and add newline
*/
_output.out_string("\033[0m\n");
_lock.unlock();
}

View File

@ -0,0 +1,83 @@
/*
* \brief Textual output functions
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 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/output.h>
/* base-internal includes */
#include <base/internal/output.h>
using namespace Genode;
/************
** Output **
************/
void Output::out_string(char const *str, size_t n)
{
if (!str)
return;
while (*str && n--) out_char(*str++);
}
/******************************
** Print function overloads **
******************************/
void Genode::print(Output &output, char const *str)
{
if (!str)
output.out_string("<null-string>");
else
while (*str) output.out_char(*str++);
}
void Genode::print(Output &output, void const *ptr)
{
print(output, Hex(reinterpret_cast<addr_t>(ptr)));
}
void Genode::print(Output &output, unsigned long value)
{
out_unsigned<unsigned long>(value, 10, 0, [&] (char c) { output.out_char(c); });
}
void Genode::print(Output &output, long value)
{
out_signed<long>(value, 10, [&] (char c) { output.out_char(c); });
}
void Genode::print(Output &output, long long value)
{
out_signed<long long>(value, 10, [&] (char c) { output.out_char(c); });
}
void Genode::print(Output &output, Hex const &value)
{
if (value.prefix == Hex::PREFIX)
output.out_string("0x");
size_t const pad_len = value.pad ? value.digits : 0;
out_unsigned<unsigned long>(value.value, 16, pad_len,
[&] (char c) { output.out_char(c); });
}

View File

@ -19,8 +19,12 @@
#include <base/printf.h>
#include <base/thread.h>
/* base-internal includes */
#include <base/internal/globals.h>
using namespace Genode;
addr_t init_main_thread_result;
extern void init_exception_handling();
@ -89,6 +93,7 @@ extern "C" void init_main_thread()
* destructor won't be registered for the atexit routine.
*/
(void*)env();
init_log();
/* initialize exception handling */
init_exception_handling();