genode/repos/os/src/test/dynamic_config/server/main.cc

117 lines
3.0 KiB
C++

/*
* \brief Test for changing configuration at runtime (server-side)
* \author Norman Feske
* \author Martin Stein
* \date 2012-04-04
*
* This program provides a generated config file as ROM service. After
* opening a ROM session, the data gets repeatedly updated.
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/attached_ram_dataspace.h>
#include <os/static_root.h>
#include <timer_session/connection.h>
#include <rom_session/rom_session.h>
#include <base/component.h>
using namespace Genode;
/*
* The implementation of this class follows the lines of
* 'os/include/os/child_policy_dynamic_rom.h'.
*/
class Rom_session_component : public Rpc_object<Rom_session>
{
private:
Env &_env;
Attached_ram_dataspace _fg { _env.ram(), _env.rm(), 0 };
Attached_ram_dataspace _bg { _env.ram(), _env.rm(), 0 };
bool _bg_pending_data { false };
Signal_context_capability _sigh { };
public:
Rom_session_component(Env &env) : _env(env) { }
/**
* Update the config file
*/
void configure(char const *data)
{
size_t const data_len = strlen(data) + 1;
/* let background buffer grow if needed */
if (_bg.size() < data_len)
_bg.realloc(&_env.ram(), data_len);
copy_cstring(_bg.local_addr<char>(), data, data_len);
_bg_pending_data = true;
/* inform client about the changed data */
if (_sigh.valid())
Signal_transmitter(_sigh).submit();
}
/***************************
** ROM session interface **
***************************/
Rom_dataspace_capability dataspace() override
{
if (!_fg.size() && !_bg_pending_data) {
error("no data loaded");
return Rom_dataspace_capability();
}
/*
* Keep foreground if no background exists. Otherwise, use old
* background as new foreground.
*/
if (_bg_pending_data) {
_fg.swap(_bg);
_bg_pending_data = false;
}
Dataspace_capability ds_cap = _fg.cap();
return static_cap_cast<Rom_dataspace>(ds_cap);
}
void sigh(Signal_context_capability sigh_cap) override { _sigh = sigh_cap; }
};
struct Main
{
enum { STACK_SIZE = 2 * 1024 * sizeof(addr_t) };
Env &env;
Rom_session_component rom_session { env };
Static_root<Rom_session> rom_root { env.ep().manage(rom_session) };
int counter { -1 };
Timer::Connection timer { env };
Signal_handler<Main> timer_handler { env.ep(), *this, &Main::handle_timer };
void handle_timer()
{
String<100> config("<config><counter>", counter++, "</counter></config>");
rom_session.configure(config.string());
timer.trigger_once(250 * 1000);
}
Main(Env &env) : env(env)
{
timer.sigh(timer_handler);
handle_timer();
env.parent().announce(env.ep().manage(rom_root));
}
};
void Component::construct(Env &env) { static Main main(env); }