diff --git a/run/log_tee.run b/run/log_tee.run new file mode 100644 index 0000000..17729e0 --- /dev/null +++ b/run/log_tee.run @@ -0,0 +1,33 @@ +build "core init server/log_tee test/printf" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init log_tee test-printf" + +append qemu_args "-nographic -m 64" + +run_genode_until {child "test-printf" exited with exit value 0} 10 diff --git a/src/server/log_tee/README b/src/server/log_tee/README new file mode 100644 index 0000000..41c4ad6 --- /dev/null +++ b/src/server/log_tee/README @@ -0,0 +1,41 @@ +Log_tee is a LOG shim server that writes client messages to +dedicated LOG sessions as well as a global component log. The +effect is that log messages are duplicated into two streams. + +This component pays for each client session from its own quota, +client quota donations are forwarded to the LOG backends. This +is to prevent naive client donations from being depleted before +reaching the final logging destination. + +Example: log messages should be written to the file-system, +the screen, and the kernel log. + + ⇊ + log_tee → terminal_log (on-screen) + ⇊ + log_tee → parent (kernel) + ⇊ + fs_log (file-system) + +! +! ... +! ... +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! \ No newline at end of file diff --git a/src/server/log_tee/component.cc b/src/server/log_tee/component.cc new file mode 100644 index 0000000..970bf09 --- /dev/null +++ b/src/server/log_tee/component.cc @@ -0,0 +1,109 @@ +/* + * \brief Server that duplicates log streams + * \author Emery Hemingway + * \date 2016-07-28 + */ + +/* + * 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 +#include +#include +#include +#include +#include + +namespace Log_tee { + + using namespace Genode; + class Session_component; + class Root_component; + +} + + +class Log_tee::Session_component : public Rpc_object +{ + private: + + /* craft our own connection to get a label in */ + struct Log_connection : Connection, Log_session_client + { + Log_connection(Env &env, char const *args) + : + Connection(env, session(env.parent(), args)), + Log_session_client(cap()) + { } + } _log; + + char _prefix[Session_label::capacity()+3]; + + public: + + Session_component(Env &env, Session_label const &label, char const *args) + : _log(env, args) + { snprintf(_prefix, sizeof(_prefix), "[%s] ", label.string()); } + + size_t write(Log_session::String const &msg) override + { + /* write to the dedicated client log session */ + size_t n = _log.write(msg); + + /* write to our own log session */ + log((char const *)_prefix, msg.string()); + + return n; + } +}; + + +class Log_tee::Root_component : + public Genode::Root_component +{ + private: + + Env &_env; + + protected: + + Log_tee::Session_component *_create_session(char const *args) override + { + Session_label const label = label_from_args(args); + + try { return new (md_alloc()) Session_component(_env, label, args); } + catch (Genode::Parent::Service_denied) { throw Root::Unavailable(); } + } + + public: + + Root_component(Env &env, Allocator &alloc) + : + Genode::Root_component(env.ep(), alloc), + _env(env) + { } +}; + + +Genode::size_t Component::stack_size() { return 2*1024*sizeof(Genode::addr_t); } + +void Component::construct(Genode::Env &env) +{ + /* + * Client sessions are not allocated on seperate dataspaces, + * they are allocated on a heap against the component's own + * RAM quota. The session RAM donation is passed verbatim to + * the backend session. + */ + + static Genode::Heap heap(env.ram(), env.rm()); + static Log_tee::Root_component root(env, heap); + + env.parent().announce(env.ep().manage(root)); +} \ No newline at end of file diff --git a/src/server/log_tee/target.mk b/src/server/log_tee/target.mk new file mode 100644 index 0000000..9b883bd --- /dev/null +++ b/src/server/log_tee/target.mk @@ -0,0 +1,3 @@ +TARGET := log_tee +SRC_CC := component.cc +LIBS := base \ No newline at end of file