diff --git a/os/include/os/reporter.h b/os/include/os/reporter.h new file mode 100644 index 0000000000..3ea5d0081f --- /dev/null +++ b/os/include/os/reporter.h @@ -0,0 +1,94 @@ +/* + * \brief Utility for status reporting + * \author Norman Feske + * \date 2014-01-07 + */ + +/* + * Copyright (C) 2014 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__OS__REPORTER_H_ +#define _INCLUDE__OS__REPORTER_H_ + +#include +#include +#include +#include + + +namespace Genode { class Reporter; } + + +class Genode::Reporter : Noncopyable +{ + private: + + String<100> const _name; + + bool _enabled = false; + + struct Connection + { + Report::Connection report; + Attached_dataspace ds = { report.dataspace() }; + + Connection(char const *name) : report(name) { } + }; + + Lazy_volatile_object _conn; + + public: + + Reporter(char const *report_name) : _name(report_name) { } + + /** + * Enable or disable reporting + */ + void enabled(bool enabled) + { + if (enabled == _enabled) return; + + _enabled = enabled; + + if (_enabled) + _conn.construct(_name.string()); + else + _conn.destruct(); + } + + bool is_enabled() const { return _enabled; } + + /** + * Return size of report buffer + */ + size_t size() const { return _enabled ? _conn->ds.size() : 0; } + + /** + * Return pointer to report buffer + */ + char *base() { return _enabled ? _conn->ds.local_addr() : 0; } + + /** + * XML generator targeting a reporter + */ + struct Xml_generator : public Genode::Xml_generator + { + template + Xml_generator(Reporter &reporter, FUNC const &func) + : + Genode::Xml_generator(reporter.base(), + reporter.size(), + reporter._name.string(), + func) + { + reporter._conn->report.submit(used()); + } + }; +}; + + +#endif /* _INCLUDE__OS__REPORTER_H_ */ diff --git a/os/include/report_session/client.h b/os/include/report_session/client.h new file mode 100644 index 0000000000..bab0578fdc --- /dev/null +++ b/os/include/report_session/client.h @@ -0,0 +1,42 @@ +/* + * \brief Client-side Report session interface + * \author Norman Feske + * \date 2014-01-10 + */ + +/* + * Copyright (C) 2014 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__REPORT_SESSION__CLIENT_H_ +#define _INCLUDE__REPORT_SESSION__CLIENT_H_ + +/* Genode includes */ +#include +#include + +namespace Report { struct Session_client; } + + +struct Report::Session_client : Genode::Rpc_client +{ + Session_client(Genode::Capability cap) + : Genode::Rpc_client(cap) { } + + Dataspace_capability dataspace() override { + return call(); } + + void submit(size_t length) override { + call(length); } + + void response_sigh(Signal_context_capability cap) override { + call(cap); } + + size_t obtain_response() override { + return call(); } +}; + +#endif /* _INCLUDE__REPORT_SESSION__CLIENT_H_ */ diff --git a/os/include/report_session/connection.h b/os/include/report_session/connection.h new file mode 100644 index 0000000000..f1a382e93b --- /dev/null +++ b/os/include/report_session/connection.h @@ -0,0 +1,34 @@ +/* + * \brief Connection to Report service + * \author Norman Feske + * \date 2014-01-10 + */ + +/* + * Copyright (C) 2014 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__REPORT_SESSION__CONNECTION_H_ +#define _INCLUDE__REPORT_SESSION__CONNECTION_H_ + +#include +#include + +namespace Report { struct Connection; } + + +struct Report::Connection : Genode::Connection, Session_client +{ + Connection(char const *label, size_t buffer_size = 4096) + : + Genode::Connection( + session("label=\"%s\", ram_quota=%zd, buffer_size=%zd", + label, 2*4096 + buffer_size, buffer_size)), + Session_client(cap()) + { } +}; + +#endif /* _INCLUDE__REPORT_SESSION__CONNECTION_H_ */ diff --git a/os/include/report_session/report_session.h b/os/include/report_session/report_session.h new file mode 100644 index 0000000000..f70bdf3fd1 --- /dev/null +++ b/os/include/report_session/report_session.h @@ -0,0 +1,97 @@ +/* + * \brief Report session interface + * \author Norman Feske + * \date 2014-01-10 + * + * A report session allows a client to report status information about itself + * to the outer world, in particular to its parent process. + * + * The communication between client and server is based on the combination + * of shared memory with synchronous RPC. A dataspace shared between both + * processes is used to carry the data. RPC calls are used to synchronize the + * access to the buffer. When the client performs an RPC, it hands over the + * responsibility to access the buffer to the server. While an RPC is in + * progress and the client blocks for the reply, the server may read and write + * the buffer. At all other times, the server is not expected to access the + * buffer. + * + * This hand over of the buffer between both parties is a mere convention. It + * is not enforced by the system. For this reason, neither of both proceess + * must keep its internal state stored in the buffer. Data should always be + * copied in/out and never processed directly in the buffer. + */ + +/* + * Copyright (C) 2014 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__REPORT_SESSION__REPORT_SESSION_H_ +#define _INCLUDE__REPORT_SESSION__REPORT_SESSION_H_ + +/* Genode includes */ +#include +#include +#include +#include + +namespace Report { + + using Genode::Dataspace_capability; + using Genode::Signal_context_capability; + using Genode::size_t; + + struct Session; +} + + +struct Report::Session : Genode::Session +{ + static const char *service_name() { return "Report"; } + + /** + * Request the dataspace used to carry reports and responses + */ + virtual Dataspace_capability dataspace() = 0; + + /** + * Submit data that is currently contained in the dataspace as report + * + * \param length length of report in bytes + * + * While this function is called, the information in the dataspace + * must not be modified by the client. + */ + virtual void submit(size_t length) = 0; + + /** + * Install signal handler for response notifications + */ + virtual void response_sigh(Signal_context_capability) = 0; + + /** + * Request a response from the recipient of reports + * + * By calling this function, the client expects that the server will + * replace the content of the dataspace with new information. + * + * \return length of response in bytes + */ + virtual size_t obtain_response() = 0; + + + /******************* + ** RPC interface ** + *******************/ + + GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace); + GENODE_RPC(Rpc_submit, void, submit, size_t); + GENODE_RPC(Rpc_response_sigh, void, response_sigh, Signal_context_capability); + GENODE_RPC(Rpc_obtain_response, size_t, obtain_response); + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_submit, Rpc_response_sigh, + Rpc_obtain_response); +}; + +#endif /* _INCLUDE__REPORT_SESSION__REPORT_SESSION_H_ */ diff --git a/os/src/server/log_report/main.cc b/os/src/server/log_report/main.cc new file mode 100644 index 0000000000..83379d8bb6 --- /dev/null +++ b/os/src/server/log_report/main.cc @@ -0,0 +1,128 @@ +/* + * \brief Report server that dumps reports to the LOG + * \author Norman Feske + * \date 2014-01-10 + */ + +/* + * Copyright (C) 2014 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +namespace Report { + using Server::Entrypoint; + using Genode::env; + + class Session_component; + class Root; + struct Main; +} + + +class Report::Session_component : public Genode::Rpc_object +{ + public: + + typedef Genode::String<200> Label; + + private: + + Label _label; + + Genode::Attached_ram_dataspace _ds; + + public: + + Session_component(Label const &label, size_t buffer_size) + : + _label(label), _ds(env()->ram_session(), buffer_size) + { } + + Dataspace_capability dataspace() override { return _ds.cap(); } + + void submit(size_t const length) override + { + using namespace Genode; + + printf("\nreport: %s\n", _label.string()); + + char buf[1024]; + for (size_t consumed = 0; consumed < length; consumed += strlen(buf)) { + strncpy(buf, _ds.local_addr() + consumed, sizeof(buf)); + printf("%s", buf); + } + printf("\nend of report\n"); + } + + void response_sigh(Genode::Signal_context_capability) override { } + + size_t obtain_response() override { return 0; } +}; + + +class Report::Root : public Genode::Root_component +{ + protected: + + Session_component *_create_session(const char *args) override + { + using namespace Genode; + + /* read label from session arguments */ + char label[200]; + Arg_string::find_arg(args, "label").string(label, sizeof(label), ""); + + /* read report buffer size from session arguments */ + size_t const buffer_size = + Arg_string::find_arg(args, "buffer_size").long_value(0); + + return new (md_alloc()) + Session_component(Session_component::Label(label), buffer_size); + } + + public: + + Root(Entrypoint &ep, Genode::Allocator &md_alloc) + : + Genode::Root_component(&ep.rpc_ep(), &md_alloc) + { } +}; + + +struct Report::Main +{ + Entrypoint &ep; + + Genode::Sliced_heap sliced_heap = { env()->ram_session(), + env()->rm_session() }; + Root root = { ep, sliced_heap }; + + Main(Entrypoint &ep) : ep(ep) + { + env()->parent()->announce(ep.manage(root)); + } +}; + + +namespace Server { + + char const *name() { return "log_report_ep"; } + + size_t stack_size() { return 4*1024*sizeof(long); } + + void construct(Entrypoint &ep) + { + static Report::Main main(ep); + } +} diff --git a/os/src/server/log_report/target.mk b/os/src/server/log_report/target.mk new file mode 100644 index 0000000000..35ad859ff0 --- /dev/null +++ b/os/src/server/log_report/target.mk @@ -0,0 +1,3 @@ +TARGET = log_report +SRC_CC = main.cc +LIBS = base server