mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
parent
7c23d6cd81
commit
a60966150e
@ -384,6 +384,10 @@ Separate components:
|
||||
A simple ROM service that provides ROM modules that change in time according
|
||||
to a configured timeline.
|
||||
|
||||
:'os/src/server/report_rom':
|
||||
A service that implements both the report session interface and the ROM
|
||||
session interface. It reflects incoming reports as ROM modules.
|
||||
|
||||
Libraries:
|
||||
|
||||
:'libports/lib/mk/libc':
|
||||
|
70
os/run/report_rom.run
Normal file
70
os/run/report_rom.run
Normal file
@ -0,0 +1,70 @@
|
||||
build "core init server/report_rom test/report_rom drivers/timer"
|
||||
|
||||
create_boot_directory
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="RM"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="SIGNAL"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="report_rom">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="ROM" />
|
||||
<service name="Report" /> </provides>
|
||||
</start>
|
||||
<start name="test-report_rom">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
<service name="ROM">
|
||||
<if-arg key="label" value="test-report_rom/brightness" />
|
||||
<child name="report_rom" />
|
||||
</service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image "core init timer report_rom test-report_rom"
|
||||
|
||||
append qemu_args "-nographic -m 128"
|
||||
|
||||
run_genode_until {child exited with exit value 0.*\n} 30
|
||||
|
||||
grep_output {^\[init -> test-report_rom}
|
||||
|
||||
compare_output_to {
|
||||
[init -> test-report_rom] --- test-report_rom started ---
|
||||
[init -> test-report_rom] Reporter: open session
|
||||
[init -> test-report_rom] Reporter: brightness 10
|
||||
[init -> test-report_rom] ROM client: request brightness report
|
||||
[init -> test-report_rom] -> <brightness brightness="10"/>
|
||||
[init -> test-report_rom] Reporter: updated brightness to 77
|
||||
[init -> test-report_rom] ROM client: wait for update notification
|
||||
[init -> test-report_rom] ROM client: got signal
|
||||
[init -> test-report_rom] ROM client: request updated brightness report
|
||||
[init -> test-report_rom] -> <brightness brightness="77"/>
|
||||
[init -> test-report_rom] Reporter: close report session
|
||||
[init -> test-report_rom] ROM client: wait for update notification
|
||||
[init -> test-report_rom] ROM client: detected vanished report
|
||||
[init -> test-report_rom] Reporter: start reporting (while the ROM client still listens)
|
||||
[init -> test-report_rom] ROM client: wait for update notification
|
||||
[init -> test-report_rom] --- test-report_rom finished ---
|
||||
}
|
24
os/src/server/report_rom/README
Normal file
24
os/src/server/report_rom/README
Normal file
@ -0,0 +1,24 @@
|
||||
The "report_rom" component is both a report service and a ROM service. It makes
|
||||
incoming reports available as ROM modules. The ROM modules are named after the
|
||||
label of the corresponding report session.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The report-ROM server hands out ROM modules only if explicitly permitted by a
|
||||
configured policy. For example:
|
||||
|
||||
! <config>
|
||||
! <rom>
|
||||
! <policy label="decorator -> pointer" report="nitpicker -> pointer"/>
|
||||
! <policy ... />
|
||||
! ...
|
||||
! </rom>
|
||||
! </config>
|
||||
|
||||
The label of an incoming ROM session is matched against the 'label' attribute
|
||||
of all '<policy>' nodes. If the session label matches a policy label, the
|
||||
client obtains the data from the report client with the label specified in the
|
||||
'report' attribute. In the example above, the nitpicker GUI server sends
|
||||
reports about the pointer position to the report-ROM service. Those reports
|
||||
are handed out to a window decorator (labeled "decorator") as ROM module.
|
74
os/src/server/report_rom/main.cc
Normal file
74
os/src/server/report_rom/main.cc
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* \brief Server that aggregates reports and exposes them as ROM modules
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/heap.h>
|
||||
#include <base/env.h>
|
||||
#include <os/server.h>
|
||||
#include <os/config.h>
|
||||
|
||||
/* local includes */
|
||||
#include <rom_service.h>
|
||||
#include <report_service.h>
|
||||
|
||||
|
||||
namespace Server {
|
||||
using Genode::env;
|
||||
using Genode::Xml_node;
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
struct Server::Main
|
||||
{
|
||||
Entrypoint &ep;
|
||||
|
||||
Genode::Sliced_heap sliced_heap = { env()->ram_session(),
|
||||
env()->rm_session() };
|
||||
|
||||
Rom::Registry rom_registry = { sliced_heap };
|
||||
|
||||
Xml_node _rom_config_node()
|
||||
{
|
||||
try {
|
||||
return Genode::config()->xml_node().sub_node("rom"); }
|
||||
catch (Xml_node::Nonexistent_sub_node) {
|
||||
PWRN("missing <rom> configuration");
|
||||
return Xml_node("<rom>");
|
||||
}
|
||||
}
|
||||
|
||||
Xml_node rom_config = _rom_config_node();
|
||||
|
||||
Report::Root report_root = { ep, sliced_heap, rom_registry };
|
||||
Rom ::Root rom_root = { ep, sliced_heap, rom_registry, rom_config};
|
||||
|
||||
Main(Entrypoint &ep) : ep(ep)
|
||||
{
|
||||
env()->parent()->announce(ep.manage(report_root));
|
||||
env()->parent()->announce(ep.manage(rom_root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Server {
|
||||
|
||||
char const *name() { return "report_rom_ep"; }
|
||||
|
||||
size_t stack_size() { return 4*1024*sizeof(long); }
|
||||
|
||||
void construct(Entrypoint &ep)
|
||||
{
|
||||
static Main main(ep);
|
||||
}
|
||||
}
|
113
os/src/server/report_rom/report_service.h
Normal file
113
os/src/server/report_rom/report_service.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* \brief Server that aggregates reports and exposes them as ROM modules
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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 _REPORT_SERVICE_H_
|
||||
#define _REPORT_SERVICE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <report_session/report_session.h>
|
||||
#include <root/component.h>
|
||||
|
||||
/* local includes */
|
||||
#include <rom_registry.h>
|
||||
|
||||
|
||||
namespace Report {
|
||||
struct Session_component;
|
||||
struct Root;
|
||||
}
|
||||
|
||||
|
||||
struct Report::Session_component : Genode::Rpc_object<Session>, Rom::Writer
|
||||
{
|
||||
private:
|
||||
|
||||
Rom::Registry_for_writer &_registry;
|
||||
|
||||
Genode::Attached_ram_dataspace _ds;
|
||||
|
||||
Rom::Module &_module;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Rom::Module::Name const &name, size_t buffer_size,
|
||||
Rom::Registry_for_writer ®istry)
|
||||
:
|
||||
_registry(registry),
|
||||
_ds(Genode::env()->ram_session(), buffer_size),
|
||||
_module(_registry.lookup(*this, name))
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* Clear report when the report session gets closes.
|
||||
*/
|
||||
~Session_component()
|
||||
{
|
||||
_module.write_content(0, 0);
|
||||
_registry.release(*this, _module);
|
||||
}
|
||||
|
||||
Dataspace_capability dataspace() override { return _ds.cap(); }
|
||||
|
||||
void submit(size_t const length) override
|
||||
{
|
||||
_module.write_content(_ds.local_addr<char>(),
|
||||
Genode::min(length, _ds.size()));
|
||||
}
|
||||
|
||||
void response_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
size_t obtain_response() override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
struct Report::Root : Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Rom::Registry_for_writer &_rom_registry;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* read label from session arguments */
|
||||
char label[200];
|
||||
Arg_string::find_arg(args, "label").string(label, sizeof(label), "");
|
||||
|
||||
/* read report buffer size from session arguments */
|
||||
size_t const buffer_size =
|
||||
Arg_string::find_arg(args, "buffer_size").long_value(0);
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(Rom::Module::Name(label), buffer_size,
|
||||
_rom_registry);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Server::Entrypoint &ep,
|
||||
Genode::Allocator &md_alloc,
|
||||
Rom::Registry_for_writer &rom_registry)
|
||||
:
|
||||
Genode::Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
||||
_rom_registry(rom_registry)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* _REPORT_SERVICE_H_ */
|
197
os/src/server/report_rom/rom_module.h
Normal file
197
os/src/server/report_rom/rom_module.h
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* \brief ROM module written by report service, read by ROM service
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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 _ROM_MODULE_
|
||||
#define _ROM_MODULE_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/volatile_object.h>
|
||||
#include <os/attached_ram_dataspace.h>
|
||||
|
||||
namespace Rom {
|
||||
using Genode::size_t;
|
||||
using Genode::Lazy_volatile_object;
|
||||
using Genode::Attached_ram_dataspace;
|
||||
|
||||
class Module;
|
||||
class Registry;
|
||||
class Writer;
|
||||
class Reader;
|
||||
class Buffer;
|
||||
|
||||
typedef Genode::List<Module> Module_list;
|
||||
typedef Genode::List<Reader> Reader_list;
|
||||
}
|
||||
|
||||
|
||||
struct Rom::Writer { };
|
||||
|
||||
|
||||
struct Rom::Reader : Reader_list::Element
|
||||
{
|
||||
virtual void notify_module_changed() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A Rom::Module gets created as soon as either a ROM client or a Report client
|
||||
* refers to it.
|
||||
*
|
||||
* XXX We never know which of both types of client is actually connected. How
|
||||
* should pay for it? There are two choices: The backing store could be payed
|
||||
* by the server, thereby exposing the server to possibe resource exhaustion
|
||||
* triggered by a malicious client. Alternatively, we could make all clients of
|
||||
* either kind of service pay that refer to the Rom::Module. In the worst case,
|
||||
* however, if there are many client for a single report, the paid-for RAM
|
||||
* quota will never be used. For now, we simply allocate the backing store from
|
||||
* the server's quota.
|
||||
*
|
||||
* The Rom::Module gets destroyed no client refers to it anymore.
|
||||
*/
|
||||
struct Rom::Module : Module_list::Element
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Genode::String<200> Name;
|
||||
|
||||
private:
|
||||
|
||||
Name _name;
|
||||
|
||||
/**
|
||||
* The ROM module may be read by any number of ROM clients
|
||||
*/
|
||||
Reader_list mutable _readers;
|
||||
|
||||
/**
|
||||
* There must be only one or no writer
|
||||
*/
|
||||
Writer const mutable * _writer = 0;
|
||||
|
||||
/**
|
||||
* Dataspace used as backing store
|
||||
*
|
||||
* The buffer for the content is not allocated from the heap to
|
||||
* allow for the immediate release of the underlying backing store when
|
||||
* the module gets destructed.
|
||||
*/
|
||||
Lazy_volatile_object<Attached_ram_dataspace> _ds;
|
||||
|
||||
/**
|
||||
* Content size, which may less than the capacilty of '_ds'.
|
||||
*/
|
||||
size_t _size = 0;
|
||||
|
||||
void _notify_readers() const
|
||||
{
|
||||
for (Reader const *r = _readers.first(); r; r = r->next())
|
||||
r->notify_module_changed();
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
** Interface used by registry **
|
||||
********************************/
|
||||
|
||||
friend class Registry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Module(Name const &name) : _name(name) { }
|
||||
|
||||
bool _reader_is_registered(Reader const &reader) const
|
||||
{
|
||||
for (Reader const *r = _readers.first(); r; r = r->next())
|
||||
if (r == &reader)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void _register(Reader const &reader) const { _readers.insert(&reader); }
|
||||
|
||||
void _unregister(Reader const &reader) const { _readers.remove(&reader); }
|
||||
|
||||
void _register(Writer const &writer) const
|
||||
{
|
||||
class Unexpected_multiple_writers { };
|
||||
if (_writer)
|
||||
throw Unexpected_multiple_writers();
|
||||
|
||||
_writer = &writer;
|
||||
}
|
||||
|
||||
void _unregister(Writer const &writer) const
|
||||
{
|
||||
class Unexpected_unknown_writer { };
|
||||
if (_writer != &writer)
|
||||
throw Unexpected_unknown_writer();
|
||||
|
||||
_writer = 0;
|
||||
}
|
||||
|
||||
bool _has_name(Name const &name) const { return name == _name; }
|
||||
|
||||
bool _is_in_use() const { return _readers.first() || _writer; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Assign new content to the ROM module
|
||||
*
|
||||
* Called by report service when a new report comes in.
|
||||
*/
|
||||
void write_content(char const * const src, size_t const src_len)
|
||||
{
|
||||
_size = 0;
|
||||
|
||||
/* realloc backing store if needed */
|
||||
if (!_ds.is_constructed() || _ds->size() < src_len)
|
||||
_ds.construct(Genode::env()->ram_session(), src_len);
|
||||
|
||||
/* copy content into backing store */
|
||||
_size = src_len;
|
||||
Genode::memcpy(_ds->local_addr<char>(), src, _size);
|
||||
|
||||
/* notify ROM clients that access the module */
|
||||
for (Reader const *r = _readers.first(); r; r = r->next())
|
||||
r->notify_module_changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Buffer_too_small { };
|
||||
|
||||
/**
|
||||
* Read content of ROM module
|
||||
*
|
||||
* Called by ROM service when a dataspace is obtained by the client.
|
||||
*/
|
||||
size_t read_content(char *dst, size_t dst_len) const
|
||||
{
|
||||
if (!_ds.is_constructed())
|
||||
return 0;
|
||||
|
||||
if (dst_len < _size)
|
||||
throw Buffer_too_small();
|
||||
|
||||
Genode::memcpy(dst, _ds->local_addr<char>(), _size);
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_t size() const { return _size; }
|
||||
};
|
||||
|
||||
#endif /* _ROM_MODULE_ */
|
115
os/src/server/report_rom/rom_registry.h
Normal file
115
os/src/server/report_rom/rom_registry.h
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* \brief Registry of ROM modules
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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 _ROM_REGISTRY_H_
|
||||
#define _ROM_REGISTRY_H_
|
||||
|
||||
/* local includes */
|
||||
#include <rom_module.h>
|
||||
|
||||
namespace Rom {
|
||||
struct Registry_for_reader;
|
||||
struct Registry_for_writer;
|
||||
}
|
||||
|
||||
|
||||
struct Rom::Registry_for_reader
|
||||
{
|
||||
virtual Module const &lookup(Reader const &reader, Module::Name const &name) = 0;
|
||||
|
||||
virtual void release(Reader const &reader, Module const &module) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct Rom::Registry_for_writer
|
||||
{
|
||||
virtual Module &lookup(Writer const &writer, Module::Name const &name) = 0;
|
||||
|
||||
virtual void release(Writer const &writer, Module const &module) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct Rom::Registry : Registry_for_reader, Registry_for_writer, Genode::Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Allocator &_md_alloc;
|
||||
|
||||
Module_list _modules;
|
||||
|
||||
Module &_lookup(Module::Name const name)
|
||||
{
|
||||
for (Module *m = _modules.first(); m; m = m->next())
|
||||
if (m->_has_name(name))
|
||||
return *m;
|
||||
|
||||
/* module does not exist yet, create one */
|
||||
|
||||
/* XXX proper accounting for the used memory is missing */
|
||||
/* XXX if we run out of memory, the server will abort */
|
||||
Module * const module = new (&_md_alloc) Module(name);
|
||||
_modules.insert(module);
|
||||
return *module;
|
||||
|
||||
}
|
||||
|
||||
void _try_to_destroy(Module const &module)
|
||||
{
|
||||
if (module._is_in_use())
|
||||
return;
|
||||
|
||||
_modules.remove(&module);
|
||||
Genode::destroy(&_md_alloc, const_cast<Module *>(&module));
|
||||
}
|
||||
|
||||
template <typename USER>
|
||||
Module &_lookup(USER const &user, Module::Name const &name)
|
||||
{
|
||||
Module &module = _lookup(name);
|
||||
module._register(user);
|
||||
return module;
|
||||
}
|
||||
|
||||
template <typename USER>
|
||||
void _release(USER const &user, Module const &module)
|
||||
{
|
||||
module._unregister(user);
|
||||
_try_to_destroy(module);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Registry(Genode::Allocator &md_alloc) : _md_alloc(md_alloc) { }
|
||||
|
||||
Module &lookup(Writer const &writer, Module::Name const &name) override
|
||||
{
|
||||
return _lookup(writer, name);
|
||||
}
|
||||
|
||||
void release(Writer const &writer, Module const &module) override
|
||||
{
|
||||
return _release(writer, module);
|
||||
}
|
||||
|
||||
Module const &lookup(Reader const &reader, Module::Name const &name) override
|
||||
{
|
||||
return _lookup(reader, name);
|
||||
}
|
||||
|
||||
void release(Reader const &reader, Module const &module) override
|
||||
{
|
||||
return _release(reader, module);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _ROM_REGISTRY_H_ */
|
152
os/src/server/report_rom/rom_service.h
Normal file
152
os/src/server/report_rom/rom_service.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* \brief ROM service
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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 _ROM_SERVICE_H_
|
||||
#define _ROM_SERVICE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <rom_session/rom_session.h>
|
||||
#include <root/component.h>
|
||||
|
||||
/* local includes */
|
||||
#include <rom_registry.h>
|
||||
|
||||
namespace Rom {
|
||||
class Session_component;
|
||||
class Root;
|
||||
|
||||
using Genode::Xml_node;
|
||||
}
|
||||
|
||||
|
||||
class Rom::Session_component : public Genode::Rpc_object<Genode::Rom_session>,
|
||||
public Reader
|
||||
{
|
||||
private:
|
||||
|
||||
Registry_for_reader &_registry;
|
||||
Module const &_module;
|
||||
|
||||
Lazy_volatile_object<Genode::Attached_ram_dataspace> _ds;
|
||||
|
||||
Genode::Signal_context_capability _sigh;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Registry_for_reader ®istry,
|
||||
Rom::Module::Name const &name)
|
||||
:
|
||||
_registry(registry), _module(_registry.lookup(*this, name))
|
||||
{ }
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
_registry.release(*this, _module);
|
||||
}
|
||||
|
||||
Genode::Rom_dataspace_capability dataspace() override
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* replace dataspace by new one */
|
||||
/* XXX we could keep the old dataspace if the size fits */
|
||||
_ds.construct(env()->ram_session(), _module.size());
|
||||
|
||||
/* fill dataspace content with report contained in module */
|
||||
_module.read_content(_ds->local_addr<char>(), _ds->size());
|
||||
|
||||
/* cast RAM into ROM dataspace capability */
|
||||
Dataspace_capability ds_cap = static_cap_cast<Dataspace>(_ds->cap());
|
||||
|
||||
return static_cap_cast<Rom_dataspace>(ds_cap);
|
||||
}
|
||||
|
||||
void sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
_sigh = sigh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of 'Reader' interface
|
||||
*/
|
||||
void notify_module_changed() const override
|
||||
{
|
||||
if (_sigh.valid())
|
||||
Genode::Signal_transmitter(_sigh).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Rom::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Registry_for_reader &_registry;
|
||||
Xml_node const &_config;
|
||||
|
||||
typedef Rom::Module::Name Label;
|
||||
|
||||
/**
|
||||
* Determine module name for label according to the configured policy
|
||||
*/
|
||||
Rom::Module::Name _module_name(Label const &label) const
|
||||
{
|
||||
try {
|
||||
for (Xml_node node = _config.sub_node("policy");
|
||||
true; node = node.next("policy")) {
|
||||
|
||||
if (!node.has_attribute("label")
|
||||
|| !node.has_attribute("report")
|
||||
|| !node.attribute("label").has_value(label.string()))
|
||||
continue;
|
||||
|
||||
char report[Rom::Module::Name::capacity()];
|
||||
node.attribute("report").value(report, sizeof(report));
|
||||
return Rom::Module::Name(report);
|
||||
}
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
PWRN("no valid policy for label \"%s\"", label.string());
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* read label of ROM module from args */
|
||||
char label[Label::capacity()];
|
||||
Arg_string::find_arg(args, "label").string(label, sizeof(label), "");
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_registry, _module_name(Label(label)));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Server::Entrypoint &ep,
|
||||
Genode::Allocator &md_alloc,
|
||||
Registry_for_reader ®istry,
|
||||
Xml_node const &config)
|
||||
:
|
||||
Genode::Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
||||
_registry(registry),
|
||||
_config(config)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* _ROM_SERVICE_H_ */
|
4
os/src/server/report_rom/target.mk
Normal file
4
os/src/server/report_rom/target.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = report_rom
|
||||
SRC_CC = main.cc
|
||||
LIBS = base server config
|
||||
INC_DIR += $(PRG_DIR)
|
90
os/src/test/report_rom/main.cc
Normal file
90
os/src/test/report_rom/main.cc
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* \brief Test for report-ROM service
|
||||
* \author Norman Feske
|
||||
* \date 2013-01-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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 <base/printf.h>
|
||||
#include <os/reporter.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
|
||||
|
||||
#define ASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
PERR("assertion %s failed", #cond); \
|
||||
return -2; }
|
||||
|
||||
|
||||
static void report_brightness(Genode::Reporter &reporter, int value)
|
||||
{
|
||||
Genode::Reporter::Xml_generator xml(reporter, [&] () {
|
||||
xml.attribute("brightness", value); });
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Signal_receiver sig_rec;
|
||||
Signal_context sig_ctx;
|
||||
Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx);
|
||||
|
||||
printf("--- test-report_rom started ---\n");
|
||||
|
||||
printf("Reporter: open session\n");
|
||||
Reporter brightness_reporter("brightness");
|
||||
brightness_reporter.enabled(true);
|
||||
|
||||
printf("Reporter: brightness 10\n");
|
||||
report_brightness(brightness_reporter, 10);
|
||||
|
||||
printf("ROM client: request brightness report\n");
|
||||
Attached_rom_dataspace brightness_rom("test-report_rom/brightness");
|
||||
|
||||
ASSERT(brightness_rom.is_valid());
|
||||
|
||||
brightness_rom.sigh(sig_cap);
|
||||
printf(" -> %s\n", brightness_rom.local_addr<char>());
|
||||
|
||||
printf("Reporter: updated brightness to 77\n");
|
||||
report_brightness(brightness_reporter, 77);
|
||||
|
||||
printf("ROM client: wait for update notification\n");
|
||||
sig_rec.wait_for_signal();
|
||||
printf("ROM client: got signal\n");
|
||||
|
||||
printf("ROM client: request updated brightness report\n");
|
||||
brightness_rom.update();
|
||||
printf(" -> %s\n", brightness_rom.local_addr<char>());
|
||||
|
||||
printf("Reporter: close report session\n");
|
||||
brightness_reporter.enabled(false);
|
||||
|
||||
printf("ROM client: wait for update notification\n");
|
||||
sig_rec.wait_for_signal();
|
||||
|
||||
brightness_rom.update();
|
||||
ASSERT(!brightness_rom.is_valid());
|
||||
printf("ROM client: detected vanished report\n");
|
||||
|
||||
printf("Reporter: start reporting (while the ROM client still listens)\n");
|
||||
brightness_reporter.enabled(true);
|
||||
report_brightness(brightness_reporter, 99);
|
||||
|
||||
printf("ROM client: wait for update notification\n");
|
||||
sig_rec.wait_for_signal();
|
||||
|
||||
printf("--- test-report_rom finished ---\n");
|
||||
|
||||
sig_rec.dissolve(&sig_ctx);
|
||||
|
||||
return 0;
|
||||
}
|
4
os/src/test/report_rom/target.mk
Normal file
4
os/src/test/report_rom/target.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = test-report_rom
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
|
Loading…
x
Reference in New Issue
Block a user