os: Skeleton for server implementations

This commit is contained in:
Norman Feske 2013-09-08 16:19:38 +02:00
parent 94bcd3f1bf
commit 7e35388336
3 changed files with 210 additions and 0 deletions

82
os/include/os/server.h Normal file
View File

@ -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 <os/signal_rpc_dispatcher.h>
namespace Server {
using namespace Genode;
class Entrypoint
{
private:
Rpc_entrypoint &_rpc_ep;
public:
Entrypoint();
/**
* Associate RPC object with the entry point
*/
template <typename RPC_INTERFACE, typename RPC_SERVER>
Capability<RPC_INTERFACE>
manage(Rpc_object<RPC_INTERFACE, RPC_SERVER> &obj)
{
return _rpc_ep.manage(&obj);
}
/**
* Dissolve RPC object from entry point
*/
template <typename RPC_INTERFACE, typename RPC_SERVER>
void dissolve(Rpc_object<RPC_INTERFACE, RPC_SERVER> &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_ */

3
os/lib/mk/server.mk Normal file
View File

@ -0,0 +1,3 @@
SRC_CC = server.cc
vpath server.cc $(REP_DIR)/src/lib/server

125
os/src/lib/server/server.cc Normal file
View File

@ -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 <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;
}
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<Signal_dispatcher_base *>(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<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 (;;)
Server::wait_and_dispatch_one_signal();
}