genode/repos/demo/include/launchpad/launchpad.h

268 lines
7.9 KiB
C
Raw Normal View History

2011-12-22 15:19:25 +00:00
/*
* \brief Launchpad interface
* \author Norman Feske
* \date 2006-09-01
*
* This class is a convenience-wrapper for starting and killing
* child processes. To support the Launchpad application, is
* also provides an interface to glues the child handling and
* the GUI together.
*/
/*
2013-01-10 20:44:47 +00:00
* Copyright (C) 2006-2013 Genode Labs GmbH
2011-12-22 15:19:25 +00:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__LAUNCHPAD__LAUNCHPAD_H_
#define _INCLUDE__LAUNCHPAD__LAUNCHPAD_H_
#include <base/allocator.h>
#include <base/service.h>
#include <base/lock.h>
#include <timer_session/timer_session.h>
#include <pd_session/client.h>
2011-12-22 15:19:25 +00:00
#include <init/child.h>
class Launchpad;
class Launchpad_child : public Genode::Child_policy,
public Genode::List<Launchpad_child>::Element,
public Genode::Child_service::Wakeup
2011-12-22 15:19:25 +00:00
{
public:
typedef Genode::Child_policy::Name Name;
typedef Genode::Registered<Genode::Child_service> Child_service;
typedef Genode::Registered<Genode::Parent_service> Parent_service;
typedef Genode::Registry<Child_service> Child_services;
typedef Genode::Registry<Parent_service> Parent_services;
private:
Name const _name;
Binary_name const _elf_name;
Genode::Env &_env;
Genode::Ram_session_capability _ref_ram_cap;
Genode::Ram_session_client _ref_ram { _ref_ram_cap };
Genode::size_t const _ram_quota;
Parent_services &_parent_services;
Child_services &_child_services;
Genode::Dataspace_capability _config_ds;
Genode::Session_requester _session_requester;
Init::Child_policy_provide_rom_file _config_policy;
Genode::Child _child;
/**
* Child_service::Wakeup callback
*/
void wakeup_child_service() override
{
_session_requester.trigger_update();
}
template <typename T>
static Genode::Service *_find_service(Genode::Registry<T> &services,
Genode::Service::Name const &name)
{
Genode::Service *service = nullptr;
services.for_each([&] (T &s) {
if (!service && (s.name() == name))
service = &s; });
return service;
}
2011-12-22 15:19:25 +00:00
public:
Launchpad_child(Genode::Env &env,
Genode::Session_label const &label,
Binary_name const &elf_name,
Genode::size_t ram_quota,
Parent_services &parent_services,
Child_services &child_services,
Genode::Dataspace_capability config_ds)
2011-12-22 15:19:25 +00:00
:
_name(label), _elf_name(elf_name),
_env(env), _ref_ram_cap(env.ram_session_cap()), _ram_quota(ram_quota),
_parent_services(parent_services),
_child_services(child_services),
_session_requester(env.ep().rpc_ep(), _env.ram(), _env.rm()),
_config_policy("config", config_ds, &_env.ep().rpc_ep()),
_child(_env.rm(), _env.ep().rpc_ep(), *this)
2011-12-22 15:19:25 +00:00
{ }
~Launchpad_child()
{
using namespace Genode;
/* unregister services */
_child_services.for_each(
[&] (Child_service &service) {
if (service.has_id_space(_session_requester.id_space()))
Genode::destroy(_child.heap(), &service); });
}
/****************************
** Child_policy interface **
****************************/
Name name() const override { return _name; }
Binary_name binary_name() const override { return _elf_name; }
Genode::Ram_session &ref_ram() override { return _ref_ram; }
Genode::Ram_session_capability ref_ram_cap() const override { return _ref_ram_cap; }
void init(Genode::Ram_session &session,
Genode::Ram_session_capability cap) override
{
session.ref_account(_ref_ram_cap);
_ref_ram.transfer_quota(cap, _ram_quota);
}
Genode::Id_space<Genode::Parent::Server> &server_id_space() override {
return _session_requester.id_space(); }
Genode::Service &resolve_session_request(Genode::Service::Name const &service_name,
Genode::Session_state::Args const &args) override
2011-12-22 15:19:25 +00:00
{
Genode::Service *service = nullptr;
2011-12-22 15:19:25 +00:00
/* check for config file request */
if ((service = _config_policy
.resolve_session_request(service_name.string(), args.string())))
return *service;
2011-12-22 15:19:25 +00:00
/* check for "session_requests" ROM request */
Genode::Session_label const label(Genode::label_from_args(args.string()));
if (service_name == Genode::Rom_session::service_name()
&& label.last_element() == Genode::Session_requester::rom_name())
return _session_requester.service();
2011-12-22 15:19:25 +00:00
/* if service is provided by one of our children, use it */
if ((service = _find_service(_child_services, service_name)))
return *service;
2011-12-22 15:19:25 +00:00
/*
* Handle special case of the demo scenario when the user uses
* a nested Launchad for starting another Nitpicker instance
* before starting Liquid_fb. In this case, we do not want to
* delegate Nitpicker's session requests to the parent. The
* parent may be a launchpad again trying to apply the same
* policy. This instance will recognise that the session is not
* available at init (because the actual input and framebuffer
* drivers are singletons, and would therefore block for
* Framebuffer or Input to become available at one of its own
* children. The launchpad with which the user originally
* interacted, however, would block at the parent interface
* until this condition gets satisfied.
*/
if (service_name != "Input"
&& service_name != "Framebuffer"
&& ((service = _find_service(_parent_services, service_name))))
return *service;
Genode::warning(name(), ": service ", service_name, " not available");
throw Genode::Parent::Service_denied();
2011-12-22 15:19:25 +00:00
}
void announce_service(Genode::Service::Name const &service_name) override
{
if (_find_service(_child_services, service_name)) {
Genode::warning(name(), ": service ", service_name, " is already registered");
return;
}
new (_child.heap())
Child_service(_child_services, _session_requester.id_space(),
_child.session_factory(), service_name,
_child.ram_session_cap(), *this);
}
2011-12-22 15:19:25 +00:00
};
class Launchpad
2011-12-22 15:19:25 +00:00
{
private:
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
2011-12-22 15:19:25 +00:00
unsigned long _initial_quota;
Launchpad_child::Parent_services _parent_services;
Launchpad_child::Child_services _child_services;
2011-12-22 15:19:25 +00:00
Genode::Lock _children_lock;
Genode::List<Launchpad_child> _children;
bool _child_name_exists(Launchpad_child::Name const &);
2011-12-22 15:19:25 +00:00
Launchpad_child::Name _get_unique_child_name(Launchpad_child::Name const &);
2011-12-22 15:19:25 +00:00
Genode::Sliced_heap _sliced_heap;
2011-12-22 15:19:25 +00:00
protected:
int _ypos;
public:
Launchpad(Genode::Env &env, unsigned long initial_quota);
2011-12-22 15:19:25 +00:00
unsigned long initial_quota() { return _initial_quota; }
virtual ~Launchpad() { }
/**
* Process launchpad XML configuration
*/
2016-11-25 15:54:49 +00:00
void process_config(Genode::Xml_node);
2011-12-22 15:19:25 +00:00
2011-12-22 15:19:25 +00:00
/*************************
** Configuring the GUI **
*************************/
virtual void quota(unsigned long quota) { }
virtual void add_launcher(Launchpad_child::Name const &binary_name,
2011-12-22 15:19:25 +00:00
unsigned long default_quota,
Genode::Dataspace_capability config_ds) { }
virtual void add_child(Launchpad_child::Name const &,
2011-12-22 15:19:25 +00:00
unsigned long quota,
Launchpad_child &,
Genode::Allocator &) { }
2011-12-22 15:19:25 +00:00
virtual void remove_child(Launchpad_child::Name const &,
Genode::Allocator &) { }
2011-12-22 15:19:25 +00:00
Launchpad_child *start_child(Launchpad_child::Name const &binary_name,
unsigned long quota,
2011-12-22 15:19:25 +00:00
Genode::Dataspace_capability config_ds);
/**
* Exit child and close all its sessions
*/
void exit_child(Launchpad_child &child);
2011-12-22 15:19:25 +00:00
};
#endif /* _INCLUDE__LAUNCHPAD__LAUNCHPAD_H_ */