From 7e353883367927b653b0243a1b3737d9f498a122 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sun, 8 Sep 2013 16:19:38 +0200 Subject: [PATCH] os: Skeleton for server implementations --- os/include/os/server.h | 82 +++++++++++++++++++++++ os/lib/mk/server.mk | 3 + os/src/lib/server/server.cc | 125 ++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 os/include/os/server.h create mode 100644 os/lib/mk/server.mk create mode 100644 os/src/lib/server/server.cc diff --git a/os/include/os/server.h b/os/include/os/server.h new file mode 100644 index 000000000..fe26bc2a9 --- /dev/null +++ b/os/include/os/server.h @@ -0,0 +1,82 @@ +/* + * \brief Skeleton for implementing servers + * \author Norman Feske + * \date 2013-09-07 + */ + +/* + * Copyright (C) 2013 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__SERVER_H_ +#define _INCLUDE__OS__SERVER_H_ + +#include + +namespace Server { + + using namespace Genode; + + class Entrypoint + { + private: + + Rpc_entrypoint &_rpc_ep; + + public: + + Entrypoint(); + + /** + * Associate RPC object with the entry point + */ + template + Capability + manage(Rpc_object &obj) + { + return _rpc_ep.manage(&obj); + } + + /** + * Dissolve RPC object from entry point + */ + template + void dissolve(Rpc_object &obj) + { + _rpc_ep.dissolve(&obj); + } + + /** + * Associate signal dispatcher with entry point + */ + Signal_context_capability manage(Signal_rpc_dispatcher_base &); + + /** + * Disassociate signal dispatcher from entry point + */ + void dissolve(Signal_rpc_dispatcher_base &); + + /** + * Return RPC entrypoint + */ + Rpc_entrypoint &rpc_ep() { return _rpc_ep; } + }; + + void wait_and_dispatch_one_signal(); + + + /*********************************************************** + ** Functions to be provided by the server implementation ** + ***********************************************************/ + + size_t stack_size(); + + char const *name(); + + void construct(Entrypoint &); +}; + +#endif /* _INCLUDE__OS__SERVER_H_ */ diff --git a/os/lib/mk/server.mk b/os/lib/mk/server.mk new file mode 100644 index 000000000..89472ab84 --- /dev/null +++ b/os/lib/mk/server.mk @@ -0,0 +1,3 @@ +SRC_CC = server.cc + +vpath server.cc $(REP_DIR)/src/lib/server diff --git a/os/src/lib/server/server.cc b/os/src/lib/server/server.cc new file mode 100644 index 000000000..87a5d9478 --- /dev/null +++ b/os/src/lib/server/server.cc @@ -0,0 +1,125 @@ +/* + * \brief Skeleton for implementing servers + * \author Norman Feske + * \date 2013-09-07 + */ + +/* + * Copyright (C) 2013 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 + +using namespace Server; + + +static Cap_session &global_cap_session() +{ + static Cap_connection inst; + return inst; +} + + +static Rpc_entrypoint &global_rpc_ep() +{ + static Rpc_entrypoint inst(&global_cap_session(), + stack_size(), + name()); + return inst; +} + + +static Entrypoint &global_ep() +{ + static Server::Entrypoint inst; + return inst; +} + + +static Genode::Signal_receiver &global_sig_rec() +{ + static Genode::Signal_receiver inst; + return inst; +} + + +Signal_context_capability Entrypoint::manage(Signal_rpc_dispatcher_base &dispatcher) +{ + return dispatcher.manage(global_sig_rec(), global_rpc_ep()); +} + + +void Server::Entrypoint::dissolve(Signal_rpc_dispatcher_base &dispatcher) +{ + dispatcher.dissolve(global_sig_rec(), global_rpc_ep()); +} + + +Server::Entrypoint::Entrypoint() : _rpc_ep(global_rpc_ep()) { } + + +void Server::wait_and_dispatch_one_signal() +{ + /* + * We call the signal dispatcher outside of the scope of 'Signal' + * object because we block the RPC interface in the input handler + * when the kill mode gets actived. While kill mode is active, we + * do not serve incoming RPC requests but we need to stay responsive + * to user input. Hence, we wait for signals in the input dispatcher + * in this case. An already existing 'Signal' object would lock the + * signal receiver and thereby prevent this nested way of signal + * handling. + */ + Signal_dispatcher_base *dispatcher = 0; + unsigned num = 0; + + { + Signal sig = global_sig_rec().wait_for_signal(); + dispatcher = dynamic_cast(sig.context()); + num = sig.num(); + } + + if (dispatcher) + dispatcher->dispatch(num); +} + + +namespace Server { + struct Constructor; + struct Constructor_component; +} + + +struct Server::Constructor +{ + GENODE_RPC(Rpc_construct, void, construct); + GENODE_RPC_INTERFACE(Rpc_construct); +}; + + +struct Server::Constructor_component : Rpc_object +{ + void construct() { Server::construct(global_ep()); } +}; + + +int main(int argc, char **argv) +{ + static Server::Constructor_component constructor; + + static Server::Entrypoint ep; + + /* call Server::construct in the context of the entrypoint */ + Capability constructor_cap = ep.manage(constructor); + + constructor_cap.call(); + + /* process incoming signals */ + for (;;) + Server::wait_and_dispatch_one_signal(); +}