mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-01 08:48:20 +00:00
parent
3bceefc9cf
commit
1f395ae780
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
109
repos/base/include/base/log.h
Normal file
109
repos/base/include/base/log.h
Normal 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_ */
|
154
repos/base/include/base/output.h
Normal file
154
repos/base/include/base/output.h
Normal 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_ */
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
51
repos/base/src/core/default_log.cc
Normal file
51
repos/base/src/core/default_log.cc
Normal 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);
|
||||
}
|
||||
|
@ -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 ---");
|
||||
|
||||
|
@ -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_ */
|
||||
|
160
repos/base/src/include/base/internal/output.h
Normal file
160
repos/base/src/include/base/internal/output.h
Normal 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_ */
|
@ -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:
|
||||
|
51
repos/base/src/lib/base/default_log.cc
Normal file
51
repos/base/src/lib/base/default_log.cc
Normal 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);
|
||||
}
|
||||
|
44
repos/base/src/lib/base/log.cc
Normal file
44
repos/base/src/lib/base/log.cc
Normal 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();
|
||||
}
|
||||
|
83
repos/base/src/lib/base/output.cc
Normal file
83
repos/base/src/lib/base/output.cc
Normal 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); });
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user