ca971bbfd8
This patch changes the top-level directory layout as a preparatory step for improving the tools for managing 3rd-party source codes. The rationale is described in the issue referenced below. Issue #1082
143 lines
3.2 KiB
C++
143 lines
3.2 KiB
C++
/*
|
|
* \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 <os/server.h>
|
|
#include <cap_session/connection.h>
|
|
|
|
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<Signal_rpc_dispatcher_base *>(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<Server::Constructor,
|
|
Server::Constructor_component>
|
|
{
|
|
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<Server::Constructor> constructor_cap = ep.manage(constructor);
|
|
|
|
constructor_cap.call<Server::Constructor::Rpc_construct>();
|
|
|
|
/* 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) { }
|
|
}
|
|
}
|