/* * \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; } static void wait_and_dispatch_one_signal(bool entrypoint) { /* * 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_rpc_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) return; if (entrypoint) dispatcher->dispatch_at_entrypoint(num); else dispatcher->dispatch(num); } 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() { ::wait_and_dispatch_one_signal(true); } 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 (;;) { /* * It might happen that we try to forward a signal to the entrypoint, * while the context of that signal is already destroyed. In that case * we will get an ipc error exception as result, which has to be caught. */ try { wait_and_dispatch_one_signal(false); } catch(Genode::Ipc_error) { } } }