mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 10:01:57 +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
|
A simple ROM service that provides ROM modules that change in time according
|
||||||
to a configured timeline.
|
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:
|
Libraries:
|
||||||
|
|
||||||
:'libports/lib/mk/libc':
|
:'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