Adapt high-level components to new parent API

This patch adjusts the various users of the 'Child' API to the changes
on the account of the new non-blocking parent interface. It also removes
the use of the no-longer-available 'Connection::KEEP_OPEN' feature.

With the adjustment, we took the opportunity to redesign several
components to fit the non-blocking execution model much better, in
particular the demo applications.

Issue #2120
This commit is contained in:
Norman Feske
2016-11-23 17:07:49 +01:00
committed by Christian Helmuth
parent 8bafb9d41b
commit b44f0554bd
146 changed files with 3026 additions and 3484 deletions

View File

@ -32,18 +32,18 @@ class Kill_event_handler : public Scout::Event_handler
{
private:
Launchpad *_launchpad;
Launchpad_child *_launchpad_child;
Launchpad &_launchpad;
Launchpad_child &_launchpad_child;
public:
Kill_event_handler(Launchpad *launchpad, Launchpad_child *launchpad_child):
Kill_event_handler(Launchpad &launchpad, Launchpad_child &launchpad_child):
_launchpad(launchpad), _launchpad_child(launchpad_child) { }
/**
* Event handler interface
*/
void handle(Scout::Event &ev)
void handle_event(Scout::Event const &ev) override
{
static int key_cnt;
@ -53,7 +53,7 @@ class Kill_event_handler : public Scout::Event_handler
if (ev.type == Event::RELEASE) key_cnt--;
if (ev.type == Event::RELEASE && key_cnt == 0)
_launchpad->exit_child(_launchpad_child);
_launchpad.exit_child(_launchpad_child);
}
};
@ -73,7 +73,7 @@ class Child_entry : public Scout::Parent_element,
Scout::Block _block;
Kbyte_loadbar<PT> _loadbar;
char _name[_NAME_LEN];
Launchpad_child::Name const _name;
Scout::Fade_icon<PT, _IW, _IH> _kill_icon;
Scout::Fade_icon<PT, _IW, _IH> _fold_icon;
@ -85,14 +85,14 @@ class Child_entry : public Scout::Parent_element,
/**
* Constructor
*/
Child_entry(const char *name, int quota_kb, int max_quota_kb,
Launchpad *launchpad, Launchpad_child *launchpad_child)
Child_entry(Launchpad_child::Name const &name, int quota_kb, int max_quota_kb,
Launchpad &launchpad, Launchpad_child &launchpad_child)
:
_block(Scout::Block::RIGHT), _loadbar(0, &Scout::label_font),
_name(name),
_kill_event_handler(launchpad, launchpad_child)
{
Genode::strncpy(_name, name, sizeof(_name));
_block.append_plaintext(_name, &Scout::plain_style);
_block.append_plaintext(_name.string(), &Scout::plain_style);
_loadbar.max_value(max_quota_kb);
_loadbar.value(quota_kb);
@ -118,7 +118,7 @@ class Child_entry : public Scout::Parent_element,
/**
* Accessors
*/
const char *name() { return _name; }
Launchpad_child::Name name() { return _name; }
/******************************

View File

@ -22,6 +22,7 @@ class Launch_entry : public Scout::Parent_element, public Loadbar_listener
{
private:
Scout::Launcher::Name _prg_name;
Scout::Block _block;
Kbyte_loadbar<PT> _loadbar;
Scout::Launcher_config _config;
@ -37,15 +38,16 @@ class Launch_entry : public Scout::Parent_element, public Loadbar_listener
/**
* Constructor
*/
Launch_entry(const char *prg_name, unsigned long initial_quota,
Launch_entry(Scout::Launcher::Name const &prg_name, unsigned long initial_quota,
unsigned long max_quota, Launchpad *launchpad,
Genode::Dataspace_capability config_ds)
:
_prg_name(prg_name),
_block(Scout::Block::RIGHT), _loadbar(this, &Scout::label_font),
_config(config_ds),
_launcher(prg_name, launchpad, initial_quota * 1024UL, &_config)
{
_block.append_launchertext(prg_name, &Scout::link_style, &_launcher);
_block.append_launchertext(_prg_name.string(), &Scout::link_style, &_launcher);
_loadbar.max_value(max_quota);
_loadbar.value(initial_quota);

View File

@ -35,11 +35,12 @@ extern unsigned char TITLEBAR_RGBA[];
********************************/
template <typename PT>
Launchpad_window<PT>::Launchpad_window(Graphics_backend &gfx_backend,
Launchpad_window<PT>::Launchpad_window(Genode::Env &env,
Graphics_backend &gfx_backend,
Point position, Area size, Area max_size,
unsigned long initial_quota)
:
Launchpad(initial_quota),
Launchpad(env, initial_quota),
Window(gfx_backend, position, size, max_size, false),
_docview(0),
_spacer(1, _TH),

View File

@ -14,6 +14,9 @@
#ifndef _LAUNCHPAD_WINDOW_H_
#define _LAUNCHPAD_WINDOW_H_
#include <base/env.h>
#include <dataspace/capability.h>
#include <scout/platform.h>
#include <scout/window.h>
@ -73,7 +76,8 @@ class Launchpad_window : public Scout::Scrollbar_listener,
*
* \param initial_quota maximum value of quota displays
*/
Launchpad_window(Scout::Graphics_backend &gfx_backend,
Launchpad_window(Genode::Env &env,
Scout::Graphics_backend &gfx_backend,
Scout::Point position, Scout::Area size,
Scout::Area max_size, unsigned long inital_quota);
@ -123,39 +127,40 @@ class Launchpad_window : public Scout::Scrollbar_listener,
_status_entry.refresh();
}
void add_launcher(const char *filename,
void add_launcher(Launchpad_child::Name const &name,
unsigned long default_quota,
Genode::Dataspace_capability config_ds = Genode::Dataspace_capability())
Genode::Dataspace_capability config_ds = Genode::Dataspace_capability()) override
{
Launch_entry<PT> *le;
le = new Launch_entry<PT>(filename, default_quota / 1024,
le = new Launch_entry<PT>(name, default_quota / 1024,
initial_quota() / 1024,
this, config_ds);
_launch_section.append(le);
refresh();
}
void add_child(const char *unique_name,
void add_child(Launchpad_child::Name const &name,
unsigned long quota,
Launchpad_child *launchpad_child,
Genode::Allocator *alloc)
Launchpad_child &launchpad_child,
Genode::Allocator &alloc) override
{
Child_entry<PT> *ce;
ce = new (alloc) Child_entry<PT>(unique_name, quota / 1024,
ce = new (alloc) Child_entry<PT>(name, quota / 1024,
initial_quota() / 1024,
this, launchpad_child);
*this, launchpad_child);
_child_entry_list.insert(ce);
_kiddy_section.append(ce);
format(_size);
refresh();
}
void remove_child(const char *name, Genode::Allocator *alloc)
void remove_child(Launchpad_child::Name const &name,
Genode::Allocator &alloc) override
{
/* lookup child entry by its name */
Child_entry<PT> *ce = _child_entry_list.first();
for ( ; ce; ce = ce->Genode::List<Child_entry<PT> >::Element::next())
if (Genode::strcmp(ce->name(), name) == 0)
if (name == ce->name())
break;
if (!ce) {

View File

@ -53,7 +53,7 @@ class Loadbar_event_handler : public Scout::Event_handler
/**
* Event handler interface
*/
void handle(Scout::Event &ev)
void handle_event(Scout::Event const &ev) override
{
static int key_cnt;
using Scout::Event;

View File

@ -11,6 +11,8 @@
* under the terms of the GNU General Public License version 2.
*/
#include <base/component.h>
#include <scout/platform.h>
#include <scout/tick.h>
#include <scout/user_state.h>
@ -85,15 +87,52 @@ static long read_int_attr_from_config(const char *attr, long default_value)
}
/**
* Main program
*/
int main(int argc, char **argv)
struct Main : Scout::Event_handler
{
Scout::Platform &_pf;
Scout::Window &_launchpad;
Scout::User_state &_user_state;
unsigned long _old_time = _pf.timer_ticks();
Main(Scout::Platform &pf, Scout::Window &launchpad, Scout::User_state &user_state)
: _pf(pf), _launchpad(launchpad), _user_state(user_state) { }
void handle_event(Scout::Event const &event) override
{
using namespace Scout;
Event ev = event;
if (ev.type != Event::WHEEL)
ev.mouse_position = ev.mouse_position - _user_state.view_position();
_user_state.handle_event(ev);
if (ev.type == Event::TIMER)
Tick::handle(_pf.timer_ticks());
/* perform periodic redraw */
unsigned long const curr_time = _pf.timer_ticks();
if (!_pf.event_pending() && ((curr_time - _old_time > 20)
|| (curr_time < _old_time))) {
_old_time = curr_time;
_launchpad.process_redraw();
}
}
};
/***************
** Component **
***************/
void Component::construct(Genode::Env &env)
{
using namespace Scout;
static Nitpicker::Connection nitpicker;
static Platform pf(*nitpicker.input());
static Nitpicker::Connection nitpicker(env);
static Platform pf(env, *nitpicker.input());
long initial_x = read_int_attr_from_config("xpos", 550);
long initial_y = read_int_attr_from_config("ypos", 150);
@ -109,17 +148,13 @@ int main(int argc, char **argv)
/* create instance of launchpad window */
static Launchpad_window<Pixel_rgb565>
launchpad(
graphics_backend, initial_position, initial_size, max_size,
Genode::env()->ram_session()->avail()
);
launchpad(env, graphics_backend, initial_position, initial_size,
max_size, env.ram().avail());
/* request config file from ROM service */
try {
launchpad.process_config();
} catch (...) { }
try { launchpad.process_config(); } catch (...) { }
Avail_quota_update avail_quota_update(&launchpad);
static Avail_quota_update avail_quota_update(&launchpad);
/* create user state manager */
static User_state user_state(&launchpad, &launchpad,
@ -129,36 +164,6 @@ int main(int argc, char **argv)
launchpad.format(initial_size);
launchpad.ypos(0);
Genode::printf("--- entering main loop ---\n");
/* enter main loop */
unsigned long curr_time, old_time;
curr_time = old_time = pf.timer_ticks();
for (;;) {
Event ev = pf.get_event();
launchpad.gui_lock.lock();
if (ev.type != Event::WHEEL)
ev.mouse_position = ev.mouse_position - user_state.view_position();
user_state.handle_event(ev);
if (ev.type == Event::TIMER)
Tick::handle(pf.timer_ticks());
/* perform periodic redraw */
curr_time = pf.timer_ticks();
if (!pf.event_pending() && ((curr_time - old_time > 20) || (curr_time < old_time))) {
old_time = curr_time;
launchpad.process_redraw();
}
launchpad.gui_lock.unlock();
if (ev.type == Event::QUIT)
break;
}
return 0;
static Main main(pf, launchpad, user_state);
pf.event_handler(main);
}

View File

@ -136,7 +136,7 @@ class Iconbar_event_handler : public Scout::Event_handler
/**
* Event handler interface
*/
void handle(Event &ev)
void handle_event(Event const &ev) override
{
static int key_cnt;

View File

@ -426,7 +426,7 @@ void Verbatim::format_fixed_width(int w)
** Link_token **
****************/
void Link_token::handle(Event &e)
void Link_token::handle_event(Event const &e)
{
if (e.type != Event::PRESS) return;
@ -444,7 +444,7 @@ void Link_token::handle(Event &e)
** Launcher_link_token **
*************************/
void Launcher_link_token::handle(Event &e)
void Launcher_link_token::handle_event(Event const &e)
{
if (e.type != Event::PRESS) return;

View File

@ -200,7 +200,7 @@ class Scout::Link_token : public Token, public Link, public Event_handler,
/**
* Event handler interface
*/
void handle(Event &e);
void handle_event(Event const &) override;
/**
* Tick interface
@ -221,9 +221,13 @@ class Launchpad;
class Scout::Launcher : public Anchor
{
public:
typedef Genode::String<64> Name;
private:
const char *_prg_name; /* null-terminated name of the program */
Name _prg_name;
int _active;
int _exec_once;
Launchpad *_launchpad;
@ -232,22 +236,24 @@ class Scout::Launcher : public Anchor
public:
static void init(Genode::Env &);
/**
* Constructors
*/
Launcher(const char *prg_name, int exec_once = 0,
Launcher(Name const &prg_name, int exec_once = 0,
unsigned long quota = 0, Launcher_config *config = 0) :
_prg_name(prg_name), _active(1),
_exec_once(exec_once), _quota(quota), _config(config) { }
Launcher(const char *prg_name, Launchpad *launchpad,
Launcher(Name const &prg_name, Launchpad *launchpad,
unsigned long quota, Launcher_config *config = 0) :
_prg_name(prg_name), _launchpad(launchpad), _quota(quota),
_config(config) { }
int active() { return _active; }
const char *prg_name() { return _prg_name; }
Name prg_name() { return _prg_name; }
void quota(unsigned long quota) { _quota = quota; }
@ -280,7 +286,7 @@ class Scout::Launcher_link_token : public Link_token
/**
* Event handler interface
*/
void handle(Event &e);
void handle_event(Event const &) override;
};

View File

@ -18,9 +18,6 @@
#include <base/snprintf.h>
#include "elements.h"
static Launchpad launchpad(Genode::env()->ram_session()->quota());
using namespace Genode;
using namespace Scout;
@ -94,10 +91,32 @@ Dataspace_capability Config_registry::config(char const *name)
** Launcher interface **
************************/
static Launchpad *launchpad_ptr;
static Launchpad &launchpad()
{
if (!launchpad_ptr) {
class Missing_launchpad_init_call { };
throw Missing_launchpad_init_call();
}
return *launchpad_ptr;
}
void Launcher::init(Genode::Env &env)
{
static Launchpad launchpad(env, env.ram().avail());
launchpad_ptr = &launchpad;
}
void Launcher::launch()
{
static Config_registry config_registry;
launchpad.start_child(prg_name(), quota(),
config_registry.config(prg_name()));
launchpad().start_child(prg_name(), quota(),
config_registry.config(prg_name().string()));
}

View File

@ -11,6 +11,8 @@
* under the terms of the GNU General Public License version 2.
*/
#include <base/component.h>
#include <scout/platform.h>
#include <scout/tick.h>
#include <scout/user_state.h>
@ -45,20 +47,86 @@ extern unsigned char NAV_PREV_RGBA[];
static unsigned char *navicons_rgba[] = { NAV_NEXT_RGBA, NAV_PREV_RGBA };
static Scout::Generic_icon **navicons[] = { &Scout::Navbar::next_icon,
&Scout::Navbar::prev_icon };
&Scout::Navbar::prev_icon };
extern int native_startup(int, char **);
/**
* Main program
*/
int main(int argc, char **argv)
namespace Scout { struct Main; }
struct Scout::Main : Scout::Event_handler
{
Scout::Platform &_pf;
Scout::Window &_browser;
Scout::User_state &_user_state;
Scout::Element &_mcursor;
Scout::Point _mouse_position;
unsigned long _old_time = _pf.timer_ticks();
Main(Scout::Platform &pf, Scout::Window &browser,
Scout::User_state &user_state, Scout::Element &mcursor)
:
_pf(pf), _browser(browser), _user_state(user_state), _mcursor(mcursor)
{ }
void handle_event(Scout::Event const &event) override
{
using namespace Scout;
Event ev = event;
if (event.type != Event::WHEEL) {
ev.mouse_position = ev.mouse_position - _user_state.view_position();
/* update mouse cursor */
if (Config::mouse_cursor && (ev.mouse_position.x() != _mouse_position.x()
|| ev.mouse_position.y() != _mouse_position.y())) {
int x1 = min(ev.mouse_position.x(), _mouse_position.x());
int y1 = min(ev.mouse_position.y(), _mouse_position.y());
int x2 = max(ev.mouse_position.x() + _mcursor.size().w() - 1,
_mouse_position.x() + _mcursor.size().w() - 1);
int y2 = max(ev.mouse_position.y() + _mcursor.size().h() - 1,
_mouse_position.y() + _mcursor.size().h() - 1);
_mcursor.geometry(Rect(ev.mouse_position, _mcursor.size()));
_browser.redraw_area(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
_mouse_position = ev.mouse_position;
}
}
_user_state.handle_event(ev);
if (event.type == Event::TIMER)
Tick::handle(_pf.timer_ticks());
/* perform periodic redraw */
unsigned long curr_time = _pf.timer_ticks();
if (!_pf.event_pending() && ((curr_time - _old_time > 20)
|| (curr_time < _old_time))) {
_old_time = curr_time;
_browser.process_redraw();
}
}
};
/***************
** Component **
***************/
void Component::construct(Genode::Env &env)
{
using namespace Scout;
Launcher::init(env);
static Nitpicker::Connection nitpicker;
static Platform pf(*nitpicker.input());
static Platform pf(env, *nitpicker.input());
Area const max_size(530, 620);
Point const initial_position(256, 80);
@ -92,10 +160,9 @@ int main(int argc, char **argv)
);
/* initialize mouse cursor */
Point mouse_position;
static Icon<Pixel_rgb565, 32, 32> mcursor;
if (Config::mouse_cursor) {
mcursor.geometry(Rect(mouse_position, Area(32, 32)));
mcursor.geometry(Rect(Point(0, 0), Area(32, 32)));
mcursor.rgba(POINTER_RGBA);
mcursor.alpha(255);
mcursor.findable(0);
@ -107,47 +174,7 @@ int main(int argc, char **argv)
initial_position.x(), initial_position.y());
browser.ypos(0);
/* enter main loop */
unsigned long curr_time, old_time;
curr_time = old_time = pf.timer_ticks();
for (;;) {
Event ev = pf.get_event();
static Main main(pf, browser, user_state, mcursor);
pf.event_handler(main);
if (ev.type != Event::WHEEL) {
ev.mouse_position = ev.mouse_position - user_state.view_position();
/* update mouse cursor */
if (Config::mouse_cursor && (ev.mouse_position.x() != mouse_position.x()
|| ev.mouse_position.y() != mouse_position.y())) {
int x1 = min(ev.mouse_position.x(), mouse_position.x());
int y1 = min(ev.mouse_position.y(), mouse_position.y());
int x2 = max(ev.mouse_position.x() + mcursor.size().w() - 1,
mouse_position.x() + mcursor.size().w() - 1);
int y2 = max(ev.mouse_position.y() + mcursor.size().h() - 1,
mouse_position.y() + mcursor.size().h() - 1);
mcursor.geometry(Rect(ev.mouse_position, mcursor.size()));
browser.redraw_area(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
mouse_position = ev.mouse_position;
}
}
user_state.handle_event(ev);
if (ev.type == Event::TIMER)
Tick::handle(pf.timer_ticks());
/* perform periodic redraw */
curr_time = pf.timer_ticks();
if (!pf.event_pending() && ((curr_time - old_time > 20) || (curr_time < old_time))) {
old_time = curr_time;
browser.process_redraw();
}
if (ev.type == Event::QUIT)
break;
}
return 0;
}

View File

@ -58,7 +58,7 @@ class Linkicon_event_handler : public Event_handler
/**
* Event handler interface
*/
void handle(Event &ev)
void handle_event(Event const &ev) override
{
if (ev.type != Event::PRESS || !_navbar) return;

View File

@ -69,7 +69,7 @@ class Arrow_event_handler : public Event_handler, public Tick
/**
* Event handler interface
*/
void handle(Event &ev)
void handle_event(Event const &ev) override
{
static int key_cnt;
@ -166,7 +166,7 @@ class Slider_event_handler : public Event_handler
/**
* Event handler interface
*/
void handle(Event &ev)
void handle_event(Event const &ev) override
{
static int key_cnt;
static int curr_my, orig_my;

View File

@ -14,16 +14,10 @@
*/
#include <base/env.h>
#include <base/child.h>
#include <base/sleep.h>
#include <base/service.h>
#include <base/snprintf.h>
#include <base/blocking.h>
#include <rom_session/connection.h>
#include <ram_session/connection.h>
#include <cpu_session/connection.h>
#include <base/attached_dataspace.h>
#include <os/config.h>
#include <timer_session/connection.h>
#include <launchpad/launchpad.h>
using namespace Genode;
@ -33,10 +27,11 @@ using namespace Genode;
** Launchpad **
***************/
Launchpad::Launchpad(unsigned long initial_quota)
Launchpad::Launchpad(Env &env, unsigned long initial_quota)
:
_env(env),
_initial_quota(initial_quota),
_sliced_heap(env()->ram_session(), env()->rm_session())
_sliced_heap(_env.ram(), _env.rm())
{
/* names of services provided by the parent */
static const char *names[] = {
@ -45,25 +40,24 @@ Launchpad::Launchpad(unsigned long initial_quota)
"RAM", "RM", "PD", "CPU", "IO_MEM", "IO_PORT", "IRQ", "ROM", "LOG",
/* services expected to got started by init */
"Nitpicker", "Init", "Timer", "PCI", "Block", "Nic", "Rtc",
"Nitpicker", "Init", "Timer", "Block", "Nic", "Rtc",
0 /* null-termination */
};
for (unsigned i = 0; names[i]; i++)
_parent_services.insert(new (env()->heap())
Parent_service(names[i]));
new (_heap) Launchpad_child::Parent_service(_parent_services, names[i]);
}
/**
* Check if a program with the specified name already exists
*/
bool Launchpad::_child_name_exists(const char *name)
bool Launchpad::_child_name_exists(Launchpad_child::Name const &name)
{
Launchpad_child *c = _children.first();
for ( ; c; c = c->List<Launchpad_child>::Element::next())
if (strcmp(c->name(), name) == 0)
if (c->name() == name)
return true;
return false;
@ -73,30 +67,23 @@ bool Launchpad::_child_name_exists(const char *name)
/**
* Create a unique name based on the filename
*
* If a program with the filename as name already exists, we
* add a counting number as suffix.
* If a program with the filename as name already exists, we add a counting
* number as suffix.
*/
void Launchpad::_get_unique_child_name(const char *filename, char *dst, int dst_len)
Launchpad_child::Name
Launchpad::_get_unique_child_name(Launchpad_child::Name const &binary_name)
{
Lock::Guard lock_guard(_children_lock);
char buf[64];
char suffix[8];
suffix[0] = 0;
if (!_child_name_exists(binary_name))
return binary_name;
for (int cnt = 1; true; cnt++) {
/* build program name composed of filename and numeric suffix */
snprintf(buf, sizeof(buf), "%s%s", filename, suffix);
for (unsigned cnt = 1; ; cnt++) {
/* if such a program name does not exist yet, we are happy */
if (!_child_name_exists(buf)) {
strncpy(dst, buf, dst_len);
return;
}
/* increase number of suffix */
snprintf(suffix, sizeof(suffix), ".%d", cnt + 1);
Launchpad_child::Name const unique(binary_name, ".", cnt);
if (!_child_name_exists(unique))
return unique;
}
}
@ -114,370 +101,98 @@ void Launchpad::process_config()
* Iterate through all entries of the config file and create
* launchpad entries as specified.
*/
int launcher_cnt = 0;
for (unsigned i = 0; i < config_node.num_sub_nodes(); i++) {
Xml_node node = config_node.sub_node(i);
if (node.has_type("launcher"))
config_node.for_each_sub_node("launcher", [&] (Xml_node node) {
/* catch XML syntax errors within launcher node */
try {
/* read file name and default quote from launcher node */
Xml_node::Attribute filename_attr = node.attribute("name");
typedef Launchpad_child::Name Name;
Name *name = new (_heap) Name(node.attribute_value("name", Name()));
enum { MAX_NAME_LEN = 128 };
char *filename = (char *)env()->heap()->alloc(MAX_NAME_LEN);
if (!filename) {
Genode::error("out of memory while processing configuration");
return;
}
filename_attr.value(filename, MAX_NAME_LEN);
Xml_node::Attribute ram_quota_attr = node.attribute("ram_quota");
Number_of_bytes default_ram_quota = 0;
ram_quota_attr.value(&default_ram_quota);
Number_of_bytes default_ram_quota =
node.attribute_value("ram_quota", Number_of_bytes(0));
/*
* Obtain configuration for the child
*/
Dataspace_capability config_ds;
/*
* Obtain configuration for the child
*/
Dataspace_capability config_ds;
if (node.has_sub_node("configfile")
&& node.sub_node("configfile").has_attribute("name")) {
typedef String<128> Rom_name;
char name[128];
node.sub_node("configfile").attribute("name").value(name, sizeof(name));
if (node.has_sub_node("configfile")) {
Rom_connection config_rom(name);
config_rom.on_destruction(Rom_connection::KEEP_OPEN);
Rom_name const name =
node.sub_node("configfile").attribute_value("name", Rom_name());
config_ds = config_rom.dataspace();
}
Rom_connection &config_rom = *new (_heap) Rom_connection(name.string());
if (node.has_sub_node("config")) {
Xml_node config_node = node.sub_node("config");
/* allocate dataspace for config */
size_t const config_size = config_node.size();
config_ds = env()->ram_session()->alloc(config_size);
/* copy configuration into new dataspace */
char * const ptr = env()->rm_session()->attach(config_ds);
Genode::memcpy(ptr, config_node.addr(), config_size);
env()->rm_session()->detach(ptr);
}
/* add launchpad entry */
add_launcher(filename, default_ram_quota, config_ds);
launcher_cnt++;
} catch (...) {
Genode::warning("launcher entry ", launcher_cnt + 1, " is malformed");
}
else {
char buf[32];
node.type_name(buf, sizeof(buf));
Genode::warning("ignoring unsupported tag <", Genode::Cstring(buf), ">");
config_ds = config_rom.dataspace();
}
}
if (node.has_sub_node("config")) {
Xml_node config_node = node.sub_node("config");
/* allocate dataspace for config */
size_t const size = config_node.size();
config_ds = env()->ram_session()->alloc(size);
/* copy configuration into new dataspace */
Attached_dataspace attached(config_ds);
memcpy(attached.local_addr<char>(), config_node.addr(), size);
}
/* add launchpad entry */
add_launcher(*name, default_ram_quota, config_ds);
});
}
Launchpad_child *Launchpad::start_child(const char *filename,
Launchpad_child *Launchpad::start_child(Launchpad_child::Name const &binary_name,
unsigned long ram_quota,
Genode::Dataspace_capability config_ds)
Dataspace_capability config_ds)
{
Genode::log("starting ", filename, " with quota ", ram_quota);
log("starting ", binary_name, " with quota ", ram_quota);
/* find unique name for new child */
char unique_name[64];
_get_unique_child_name(filename, unique_name, sizeof(unique_name));
Genode::log("using unique child name \"", Cstring(unique_name), "\"");
Launchpad_child::Name const unique_name = _get_unique_child_name(binary_name);
log("using unique child name \"", unique_name, "\"");
if (ram_quota > env()->ram_session()->avail()) {
Genode::error("child's ram quota is higher than our available quota, using available quota");
error("child's ram quota is higher than our available quota, using available quota");
ram_quota = env()->ram_session()->avail() - 256*1000;
}
size_t metadata_size = 4096*16 + sizeof(Launchpad_child);
if (metadata_size > ram_quota) {
Genode::error("too low ram_quota to hold child metadata");
error("too low ram_quota to hold child metadata");
return 0;
}
ram_quota -= metadata_size;
/* lookup executable elf binary */
Dataspace_capability file_cap;
Rom_session_capability rom_cap;
try {
/*
* When creating a ROM connection for a non-existing file, the
* constructor of 'Rom_connection' throws a 'Parent::Service_denied'
* exception.
*/
Rom_connection rom(prefixed_label(Session_label(Cstring(unique_name)),
Session_label(filename)).string());
rom.on_destruction(Rom_connection::KEEP_OPEN);
rom_cap = rom.cap();
file_cap = rom.dataspace();
} catch (...) {
Genode::error("could not access ROM module \"", filename, "\"");
return 0;
}
/* create ram session for child with some of our own quota */
Ram_connection ram;
ram.on_destruction(Ram_connection::KEEP_OPEN);
ram.ref_account(env()->ram_session_cap());
env()->ram_session()->transfer_quota(ram.cap(), ram_quota);
/* create cpu session for child */
Cpu_connection cpu(unique_name);
cpu.on_destruction(Cpu_connection::KEEP_OPEN);
if (!ram.cap().valid() || !cpu.cap().valid()) {
if (ram.cap().valid()) {
Genode::warning("failed to create CPU session");
env()->parent()->close(ram.cap());
}
if (cpu.cap().valid()) {
Genode::warning("failed to create RAM session");
env()->parent()->close(cpu.cap());
}
env()->parent()->close(rom_cap);
Genode::log("our quota is ", env()->ram_session()->quota());
return 0;
}
Pd_connection pd;
pd.on_destruction(Pd_connection::KEEP_OPEN);
if (!pd.cap().valid()) {
Genode::warning("failed to create PD session");
env()->parent()->close(ram.cap());
env()->parent()->close(cpu.cap());
env()->parent()->close(rom_cap);
return 0;
}
try {
Launchpad_child *c = new (&_sliced_heap)
Launchpad_child(unique_name, file_cap, pd.cap(), ram.cap(),
cpu.cap(), rom_cap,
&_cap_session, &_parent_services, &_child_services,
config_ds, this);
Launchpad_child(_env, unique_name, binary_name, ram_quota,
_parent_services, _child_services, config_ds);
Lock::Guard lock_guard(_children_lock);
_children.insert(c);
add_child(unique_name, ram_quota, c, c->heap());
add_child(unique_name, ram_quota, *c, c->heap());
return c;
} catch (Cpu_session::Thread_creation_failed) {
Genode::warning("failed to create child - Cpu_session::Thread_creation_failed");
} catch (...) {
Genode::warning("failed to create child - unknown reason");
}
env()->parent()->close(ram.cap());
env()->parent()->close(cpu.cap());
env()->parent()->close(rom_cap);
} catch (...) {
warning("failed to create child - unknown reason"); }
return 0;
}
/**
* Watchdog-guarded child destruction mechanism
*
* During the destruction of a child, all sessions of the child are getting
* closed. A server, however, may refuse to answer a close call. We detect
* this case using a watchdog mechanism, unblock the 'close' call, and
* proceed with the closing the other remaining sessions.
*/
class Child_destructor_thread : Thread_deprecated<2*4096>
void Launchpad::exit_child(Launchpad_child &child)
{
private:
Launchpad_child *_curr_child; /* currently destructed child */
Allocator *_curr_alloc; /* child object'sallocator */
Lock _submit_lock; /* only one submission at a time */
Lock _activate_lock; /* submission protocol */
bool _ready; /* set if submission is completed */
int _watchdog_cnt; /* watchdog counter in milliseconds */
/**
* Thread entry function
*/
void entry() {
while (true) {
/* wait for next submission */
_activate_lock.lock();
/*
* Eventually long-taking operation that involves the
* closing of all session of the child. This procedure
* may need blocking cancellation to proceed in the
* case servers are unresponsive.
*/
try {
destroy(_curr_alloc, _curr_child);
} catch (Blocking_canceled) {
Genode::error("suspicious cancellation");
}
_ready = true;
}
}
public:
/*
* Watchdog timer granularity in milliseconds. This value defined
* after how many milliseconds the watchdog is activated.
*/
enum { WATCHDOG_GRANULARITY_MS = 10 };
/**
* Constructor
*/
Child_destructor_thread() :
Thread_deprecated("child_destructor"),
_curr_child(0), _curr_alloc(0),
_activate_lock(Lock::LOCKED),
_ready(true)
{
start();
}
/**
* Destruct child, coping with unresponsive servers
*
* \param alloc Child object's allocator
* \param child Child to destruct
* \param timeout_ms Maximum destruction time until the destructing
* thread gets waken up to give up the close call to
* an unreponsive server.
*/
void submit_for_destruction(Allocator *alloc, Launchpad_child *child,
Timer::Session *timer, int timeout_ms)
{
/* block until destructor thread is ready for new submission */
Lock::Guard _lock_guard(_submit_lock);
/* register submission values */
_curr_child = child;
_curr_alloc = alloc;
_ready = false;
_watchdog_cnt = 0;
/* wake up the destruction thread */
_activate_lock.unlock();
/*
* Now, the destruction thread attempts to close all the
* child's sessions. Check '_ready' flag periodically.
*/
while (!_ready) {
/* give the destruction thread some time to proceed */
timer->msleep(WATCHDOG_GRANULARITY_MS);
_watchdog_cnt += WATCHDOG_GRANULARITY_MS;
/* check if we reached the timeout */
if (_watchdog_cnt > timeout_ms) {
/*
* The destruction seems to got stuck, let's shake it a
* bit to proceed and reset the watchdog counter to give
* the next blocking operation a chance to execute.
*/
child->cancel_blocking();
_watchdog_cnt = 0;
}
}
}
};
/**
* Construct a timer session for the watchdog timer on demand
*/
static Timer::Session *timer_session()
{
static Timer::Connection timer;
return &timer;
}
Dataspace_capability Launchpad_child::_ldso_ds()
{
static bool first_attempt_failed = false;
if (!first_attempt_failed) {
try {
static Rom_connection rom("ld.lib.so");
static Dataspace_capability ds = rom.dataspace();
return ds;
} catch (...) { }
}
first_attempt_failed = true;
return Dataspace_capability();
}
/* construct child-destructor thread early - in case we run out of threads */
static Child_destructor_thread child_destructor;
/**
* Destruct Launchpad_child, cope with infinitely blocking server->close calls
*
* The arguments correspond to the 'Child_destructor_thread::submit_for_destruction'
* function.
*/
static void destruct_child(Allocator *alloc, Launchpad_child *child,
Timer::Session *timer, int timeout)
{
/* if no timer session was provided by our caller, we have create one */
if (!timer)
timer = timer_session();
child_destructor.submit_for_destruction(alloc, child, timer, timeout);
}
void Launchpad::exit_child(Launchpad_child *child,
Timer::Session *timer,
int session_close_timeout_ms)
{
remove_child(child->name(), child->heap());
remove_child(child.name(), child.heap());
Lock::Guard lock_guard(_children_lock);
_children.remove(child);
_children.remove(&child);
Ram_session_capability ram_session_cap = child->ram_session_cap();
Cpu_session_capability cpu_session_cap = child->cpu_session_cap();
Rom_session_capability rom_session_cap = child->rom_session_cap();
const Genode::Server *server = child->server();
destruct_child(&_sliced_heap, child, timer, session_close_timeout_ms);
env()->parent()->close(cpu_session_cap);
env()->parent()->close(rom_session_cap);
env()->parent()->close(ram_session_cap);
/*
* The killed child may have provided services to other children.
* Since the server is dead by now, we cannot close its sessions
* in the cooperative way. Instead, we need to instruct each
* other child to forget about session associated with the dead
* server. Note that the 'child' pointer points a a no-more
* existing object. It is only used to identify the corresponding
* session. It must never by de-referenced!
*/
Launchpad_child *c = _children.first();
for ( ; c; c = c->Genode::List<Launchpad_child>::Element::next())
c->revoke_server(server);
destroy(_sliced_heap, &child);
}

View File

@ -11,10 +11,9 @@
* under the terms of the GNU General Public License version 2.
*/
#include <base/component.h>
#include <base/rpc_server.h>
#include <base/signal.h>
#include <cap_session/connection.h>
#include <os/config.h>
#include <base/attached_rom_dataspace.h>
#include <scout/user_state.h>
#include <scout/nitpicker_graphics_backend.h>
@ -101,12 +100,10 @@ static bool config_decoration = true;
/**
* Parse configuration
*/
static void read_config()
static void read_config(Genode::Xml_node config_node)
{
using namespace Genode;
Xml_node config_node = config()->xml_node();
try {
char buf[16];
config_node.attribute("animate").value(buf, sizeof(buf));
@ -169,42 +166,71 @@ static void read_config()
struct Input_handler
{
GENODE_RPC(Rpc_handle_input, void, handle, Scout::Event&);
GENODE_RPC(Rpc_handle_input, void, handle_input, Scout::Event const &);
GENODE_RPC_INTERFACE(Rpc_handle_input);
};
class Input_handler_component : public Genode::Rpc_object<Input_handler,
Input_handler_component>
class Main : public Scout::Event_handler
{
private:
Scout::Platform &_pf;
Scout::User_state &_user_state;
Framebuffer_window<Genode::Pixel_rgb565> &_fb_win;
Genode::Signal_receiver &_sig_rec;
Genode::Attached_rom_dataspace &_config;
unsigned long _curr_time, _old_time;
void _handle_config()
{
_config.update();
/* keep the current values by default */
config_fb_x = _fb_win.view_x();
config_fb_y = _fb_win.view_y();
config_fb_width = _fb_win.view_w();
config_fb_height = _fb_win.view_h();
try { read_config(_config.xml()); } catch (...) { }
_fb_win.name(config_title);
_fb_win.config_alpha(config_alpha);
_fb_win.config_resize_handle(config_resize_handle);
_fb_win.config_decoration(config_decoration);
/* must get called after 'config_decoration()' */
_fb_win.content_geometry(config_fb_x, config_fb_y,
config_fb_width, config_fb_height);
_user_state.update_view_offset();
}
Genode::Signal_handler<Main> _config_handler;
public:
Input_handler_component(Scout::Platform &pf,
Scout::User_state &user_state,
Framebuffer_window<Genode::Pixel_rgb565> &fb_win,
Genode::Signal_receiver &sig_rec)
Main(Scout::Platform &pf,
Scout::User_state &user_state,
Framebuffer_window<Genode::Pixel_rgb565> &fb_win,
Genode::Entrypoint &ep,
Genode::Attached_rom_dataspace &config)
:
_pf(pf),
_user_state(user_state),
_fb_win(fb_win),
_sig_rec(sig_rec)
_config(config),
_config_handler(ep, *this, &Main::_handle_config)
{
_curr_time = _old_time = _pf.timer_ticks();
config.sigh(_config_handler);
}
void handle(Scout::Event &ev)
void handle_event(Scout::Event const &event) override
{
using Scout::Event;
Event ev = event;
if (ev.type != Event::WHEEL)
ev.mouse_position = ev.mouse_position - _user_state.view_position();
@ -217,30 +243,11 @@ class Input_handler_component : public Genode::Rpc_object<Input_handler,
if (ev.type == Event::TIMER) {
Scout::Tick::handle(_pf.timer_ticks());
/* check for configuration changes */
if (_sig_rec.pending()) {
_sig_rec.wait_for_signal();
Genode::config()->reload();
/* keep the current values by default */
config_fb_x = _fb_win.view_x();
config_fb_y = _fb_win.view_y();
config_fb_width = _fb_win.view_w();
config_fb_height = _fb_win.view_h();
try { read_config(); } catch (...) { }
_fb_win.name(config_title);
_fb_win.config_alpha(config_alpha);
_fb_win.config_resize_handle(config_resize_handle);
_fb_win.config_decoration(config_decoration);
/* must get called after 'config_decoration()' */
_fb_win.content_geometry(config_fb_x, config_fb_y,
config_fb_width, config_fb_height);
_user_state.update_view_offset();
}
}
/* perform periodic redraw */
_curr_time = _pf.timer_ticks();
if (!_pf.event_pending() && ((_curr_time - _old_time > 20) || (_curr_time < _old_time))) {
if ((_curr_time - _old_time > 20) || (_curr_time < _old_time)) {
_old_time = _curr_time;
_fb_win.process_redraw();
}
@ -248,29 +255,24 @@ class Input_handler_component : public Genode::Rpc_object<Input_handler,
};
/**
* Main program
*/
int main(int argc, char **argv)
/***************
** Component **
***************/
void Component::construct(Genode::Env &env)
{
using namespace Scout;
try { read_config(); } catch (...) { }
static Genode::Attached_rom_dataspace config(env, "config");
/*
* Register signal handler for config changes
*/
static Genode::Signal_receiver sig_rec;
static Genode::Signal_context sig_ctx;
try { Genode::config()->sigh(sig_rec.manage(&sig_ctx)); } catch (...) { }
try { read_config(config.xml()); } catch (...) { }
/* heuristic for allocating the double-buffer backing store */
enum { WINBORDER_WIDTH = 10, WINBORDER_HEIGHT = 40 };
/* init platform */
static Nitpicker::Connection nitpicker;
static Platform pf(*nitpicker.input());
static Nitpicker::Connection nitpicker(env);
static Platform pf(env, *nitpicker.input());
Area const max_size(config_fb_width + WINBORDER_WIDTH,
config_fb_height + WINBORDER_HEIGHT);
@ -301,27 +303,9 @@ int main(int argc, char **argv)
fb_win.content_geometry(config_fb_x, config_fb_y,
config_fb_width, config_fb_height);
/* initialize server entry point */
enum { STACK_SIZE = 2*1024*sizeof(Genode::addr_t) };
static Genode::Cap_connection cap;
static Genode::Rpc_entrypoint ep(&cap, STACK_SIZE, "liquid_fb_ep");
/* initialize public services */
init_services(ep);
init_services(env.ep().rpc_ep());
/* create local input handler service */
static Input_handler_component input_handler(pf, user_state, fb_win,
sig_rec);
Genode::Capability<Input_handler> input_handler_cap = ep.manage(&input_handler);
/* enter main loop */
for (;;) {
Event ev = pf.get_event();
input_handler_cap.call<Input_handler::Rpc_handle_input>(ev);
if (ev.type == Event::QUIT)
break;
}
return 0;
static Main main(pf, user_state, fb_win, env.ep(), config);
pf.event_handler(main);
}

View File

@ -58,7 +58,7 @@ class Window_content : public Scout::Element
:
_input_session(input_session),_element(element) { }
void handle(Scout::Event &ev)
void handle_event(Scout::Event const &ev) override
{
using namespace Scout;

View File

@ -401,7 +401,7 @@ int main(int argc, char **argv)
Framebuffer::Mode::RGB565), false);
/* initialize entry point that serves the root interface */
enum { STACK_SIZE = 4096 };
enum { STACK_SIZE = 4096*sizeof(long) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nitlog_ep");