diff --git a/os/include/os/slave.h b/os/include/os/slave.h new file mode 100644 index 0000000000..0616230dca --- /dev/null +++ b/os/include/os/slave.h @@ -0,0 +1,180 @@ +/* + * \brief Convenience helper for running a service as child process + * \author Norman Feske + * \author Christian Helmuth + * \date 2012-01-25 + */ + +/* + * Copyright (C) 2012 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 _INCLUDE__OS__SLAVE_H_ +#define _INCLUDE__OS__SLAVE_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include + +namespace Genode { + + /** + * Slave-policy class + * + * This class provides a convenience policy for single-service slaves using a + * white list of parent services. + */ + class Slave_policy : public Genode::Child_policy + { + protected: + + /** + * Return white list of services the slave is permitted to use + * + * The list is terminated via a NULL pointer. + */ + virtual char const **_permitted_services() const = 0; + + private: + + char const *_label; + Genode::Service_registry _parent_services; + + Genode::Rpc_entrypoint &_entrypoint; + Genode::Rom_connection _binary_rom; + Init::Child_policy_enforce_labeling _labeling_policy; + Init::Child_policy_provide_rom_file _binary_policy; + Init::Child_policy_provide_rom_file _config_policy; + + bool _service_permitted(const char *service_name) + { + for (const char **s = _permitted_services(); *s; ++s) + if (!Genode::strcmp(service_name, *s)) + return true; + + return false; + } + + public: + + /** + * Slave-policy constructor + * + * \param label name of the program to start + * \param entrypoint entrypoint used to provide local services + * such as the config ROM service + * \param config dataspace containing the child config + */ + Slave_policy(const char *label, + Genode::Rpc_entrypoint &entrypoint, + Genode::Dataspace_capability config = Genode::Dataspace_capability()) + : + _label(label), + _entrypoint(entrypoint), + _binary_rom(_label, _label), + _labeling_policy(_label), + _binary_policy("binary", _binary_rom.dataspace(), &_entrypoint), + _config_policy("config", config, &_entrypoint) + { } + + Genode::Dataspace_capability binary() { return _binary_rom.dataspace(); } + + + /**************************** + ** Child_policy interface ** + ****************************/ + + const char *name() const { return _label; } + + Genode::Service *resolve_session_request(const char *service_name, + const char *args) + { + Genode::Service *service = 0; + + /* check for binary file request */ + if ((service = _binary_policy.resolve_session_request(service_name, args))) + return service; + + /* check for config file request */ + if ((service = _config_policy.resolve_session_request(service_name, args))) + return service; + + if (!_service_permitted(service_name)) { + PERR("%s: illegal session request of service \"%s\"", + name(), service_name); + return 0; + } + + /* fill parent service registry on demand */ + if (!(service = _parent_services.find(service_name))) { + service = new (Genode::env()->heap()) + Genode::Parent_service(service_name); + _parent_services.insert(service); + } + + /* return parent service */ + return service; + } + + void filter_session_args(const char *service, + char *args, Genode::size_t args_len) + { + _labeling_policy.filter_session_args(service, args, args_len); + } + }; + + + class Slave + { + private: + + struct Resources + { + Genode::Ram_connection ram; + Genode::Cpu_connection cpu; + Genode::Rm_connection rm; + + class Quota_exceeded : public Genode::Exception { }; + + Resources(const char *label, Genode::size_t ram_quota) + : ram(label), cpu(label) + { + /* + * XXX derive donated quota from information to be provided by + * the used 'Connection' interfaces + */ + enum { DONATED_RAM_QUOTA = 128*1024 }; + if (ram_quota > DONATED_RAM_QUOTA) + ram_quota -= DONATED_RAM_QUOTA; + else + throw Quota_exceeded(); + ram.ref_account(Genode::env()->ram_session_cap()); + Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota); + } + }; + + Resources _resources; + Genode::Child _child; + + public: + + Slave(Genode::Rpc_entrypoint &entrypoint, + Slave_policy &slave_policy, + Genode::size_t ram_quota) + : + _resources(slave_policy.name(), ram_quota), + _child(slave_policy.binary(), + _resources.ram.cap(), _resources.cpu.cap(), + _resources.rm.cap(), &entrypoint, &slave_policy) + { } + }; +} + +#endif /* _INCLUDE__OS__SLAVE_H_ */