diff --git a/repos/base-fiasco/src/core/target.inc b/repos/base-fiasco/src/core/target.inc index 155aed53b..cbdd6ed24 100644 --- a/repos/base-fiasco/src/core/target.inc +++ b/repos/base-fiasco/src/core/target.inc @@ -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) diff --git a/repos/base-foc/src/core/target.inc b/repos/base-foc/src/core/target.inc index 4e2949eb3..edcfca630 100644 --- a/repos/base-foc/src/core/target.inc +++ b/repos/base-foc/src/core/target.inc @@ -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) diff --git a/repos/base-hw/lib/mk/core.inc b/repos/base-hw/lib/mk/core.inc index 75420f562..d15cd9c9c 100644 --- a/repos/base-hw/lib/mk/core.inc +++ b/repos/base-hw/lib/mk/core.inc @@ -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 diff --git a/repos/base-linux/src/core/target.mk b/repos/base-linux/src/core/target.mk index a4a8905a4..914dbf50e 100644 --- a/repos/base-linux/src/core/target.mk +++ b/repos/base-linux/src/core/target.mk @@ -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 diff --git a/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc b/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc index b0ff9364d..05a26f759 100644 --- a/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc +++ b/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc @@ -19,6 +19,7 @@ /* base-internal includes */ #include +#include 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 */ diff --git a/repos/base-nova/src/core/target.inc b/repos/base-nova/src/core/target.inc index 8104d9efa..c5604c06f 100644 --- a/repos/base-nova/src/core/target.inc +++ b/repos/base-nova/src/core/target.inc @@ -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) diff --git a/repos/base-okl4/src/core/target.inc b/repos/base-okl4/src/core/target.inc index 4c2714873..31c10b166 100644 --- a/repos/base-okl4/src/core/target.inc +++ b/repos/base-okl4/src/core/target.inc @@ -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 diff --git a/repos/base-pistachio/src/core/target.inc b/repos/base-pistachio/src/core/target.inc index ca4be55b6..d4bb70adf 100644 --- a/repos/base-pistachio/src/core/target.inc +++ b/repos/base-pistachio/src/core/target.inc @@ -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) diff --git a/repos/base-sel4/lib/mk/core_printf.mk b/repos/base-sel4/lib/mk/core_printf.mk index 73575bc93..c34a6f380 100644 --- a/repos/base-sel4/lib/mk/core_printf.mk +++ b/repos/base-sel4/lib/mk/core_printf.mk @@ -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 diff --git a/repos/base/include/base/log.h b/repos/base/include/base/log.h new file mode 100644 index 000000000..eb96fb3b5 --- /dev/null +++ b/repos/base/include/base/log.h @@ -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 +#include + +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 + void _output_args(Output &output, HEAD && head, TAIL &&... tail) + { + print(output, head); + _output_args(output, tail...); + } + + template + void _output_args(Output &output, LAST && last) { print(output, last); } + + public: + + Log(Output &output) : _output(output) { } + + template + 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 + void log(ARGS &&... args) { Log::log().output(Log::LOG, args...); } + + + /** + * Write 'args' as a warning message to the log + */ + template + void warning(ARGS &&... args) { Log::log().output(Log::WARNING, args...); } + + + /** + * Write 'args' as an error message to the log + */ + template + void error(ARGS &&... args) { Log::log().output(Log::ERROR, args...); } +} + +#endif /* _INCLUDE__BASE__LOG_H_ */ diff --git a/repos/base/include/base/output.h b/repos/base/include/base/output.h new file mode 100644 index 000000000..9628c32eb --- /dev/null +++ b/repos/base/include/base/output.h @@ -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 +#include + +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 + 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 + 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 + static inline void print(Output &output, T const &obj) + { + obj.print(output); + } +} + +#endif /* _INCLUDE__BASE__OUTPUT_H_ */ diff --git a/repos/base/lib/mk/base-common.inc b/repos/base/lib/mk/base-common.inc index 83e2ed042..d692e0dbe 100644 --- a/repos/base/lib/mk/base-common.inc +++ b/repos/base/lib/mk/base-common.inc @@ -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 diff --git a/repos/base/lib/mk/base.inc b/repos/base/lib/mk/base.inc index 5db96c6ff..3764f77f2 100644 --- a/repos/base/lib/mk/base.inc +++ b/repos/base/lib/mk/base.inc @@ -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 diff --git a/repos/base/src/core/default_log.cc b/repos/base/src/core/default_log.cc new file mode 100644 index 000000000..26f5ad22a --- /dev/null +++ b/repos/base/src/core/default_log.cc @@ -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 +#include + +/* base-internal includes */ +#include +#include +#include + +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(Write_fn()); + + log_ptr = unmanaged_singleton(*buffered_log_output); +} + diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 5eb01c268..998322c8f 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -225,7 +226,7 @@ int main() */ inhibit_tracing = true; - PINF("Genode %s", Genode::version_string); + log("Genode ", Genode::version_string); PDBG("--- create local services ---"); diff --git a/repos/base/src/include/base/internal/globals.h b/repos/base/src/include/base/internal/globals.h index 13f9f1ff5..7b6df12ca 100644 --- a/repos/base/src/include/base/internal/globals.h +++ b/repos/base/src/include/base/internal/globals.h @@ -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_ */ diff --git a/repos/base/src/include/base/internal/output.h b/repos/base/src/include/base/internal/output.h new file mode 100644 index 000000000..479d1306c --- /dev/null +++ b/repos/base/src/include/base/internal/output.h @@ -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 + +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 +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 +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 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 +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_ */ diff --git a/repos/base/src/lib/base/console.cc b/repos/base/src/lib/base/console.cc index 5e56277aa..3b83897dc 100644 --- a/repos/base/src/lib/base/console.cc +++ b/repos/base/src/lib/base/console.cc @@ -17,9 +17,13 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ #include #include +/* base-internal includes */ +#include + 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 -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 -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(numeric_arg, cmd.base); + out_signed(numeric_arg, cmd.base, + [&] (char c) { _out_char(c); }); else - _out_signed(numeric_arg, cmd.base); + out_signed(numeric_arg, cmd.base, + [&] (char c) { _out_char(c); }); break; case Format_command::UINT: if (cmd.length == Format_command::LONG_LONG) { - _out_unsigned(numeric_arg, cmd.base, cmd.padding); + out_unsigned(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(numeric_arg, cmd.base, cmd.padding); + out_unsigned(numeric_arg, cmd.base, cmd.padding, + [&] (char c) { _out_char(c); }); break; case Format_command::CHAR: diff --git a/repos/base/src/lib/base/default_log.cc b/repos/base/src/lib/base/default_log.cc new file mode 100644 index 000000000..9f681c123 --- /dev/null +++ b/repos/base/src/lib/base/default_log.cc @@ -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 +#include + +/* base-internal includes */ +#include +#include +#include + +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 + Buffered_log_output; + + static Buffered_log_output *buffered_log_output = + unmanaged_singleton(Write_fn()); + + log_ptr = unmanaged_singleton(*buffered_log_output); +} + diff --git a/repos/base/src/lib/base/log.cc b/repos/base/src/lib/base/log.cc new file mode 100644 index 000000000..6a61882a9 --- /dev/null +++ b/repos/base/src/lib/base/log.cc @@ -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 + +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(); +} + diff --git a/repos/base/src/lib/base/output.cc b/repos/base/src/lib/base/output.cc new file mode 100644 index 000000000..66648f24f --- /dev/null +++ b/repos/base/src/lib/base/output.cc @@ -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-internal includes */ +#include + +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(""); + else + while (*str) output.out_char(*str++); +} + + +void Genode::print(Output &output, void const *ptr) +{ + print(output, Hex(reinterpret_cast(ptr))); +} + + +void Genode::print(Output &output, unsigned long value) +{ + out_unsigned(value, 10, 0, [&] (char c) { output.out_char(c); }); +} + + +void Genode::print(Output &output, long value) +{ + out_signed(value, 10, [&] (char c) { output.out_char(c); }); +} + + +void Genode::print(Output &output, long long value) +{ + out_signed(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(value.value, 16, pad_len, + [&] (char c) { output.out_char(c); }); +} + diff --git a/repos/base/src/lib/startup/init_main_thread.cc b/repos/base/src/lib/startup/init_main_thread.cc index b08329832..5cccb3159 100644 --- a/repos/base/src/lib/startup/init_main_thread.cc +++ b/repos/base/src/lib/startup/init_main_thread.cc @@ -19,8 +19,12 @@ #include #include +/* base-internal includes */ +#include + 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();