/* * \brief Component bootstrap * \author Norman Feske * \author Christian Helmuth * \date 2016-01-13 */ /* * Copyright (C) 2016-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ /* Genode includes */ #include #include #include #include #include /* base-internal includes */ #include /* * XXX remove this pointer once 'Env_deprecated' is removed */ static Genode::Env *env_ptr = nullptr; /** * Excecute pending static constructors * * The weak function is used for statically linked binaries. The dynamic linker * provides the real implementation for dynamically linked components. */ void Genode::exec_static_constructors() __attribute__((weak)); void Genode::exec_static_constructors() { } namespace { using namespace Genode; struct Env : Genode::Env { Genode::Entrypoint &_ep; Genode::Parent &_parent = *env_deprecated()->parent(); /** * Lock for serializing 'session' and 'close' */ Genode::Lock _lock; /** * Utility to used block for single signal */ struct Blockade { Parent &_parent; Genode::Signal_receiver _sig_rec; Genode::Signal_context _sig_ctx; Blockade(Parent &parent) : _parent(parent) { _parent.session_sigh(_sig_rec.manage(&_sig_ctx)); } void block() { _sig_rec.wait_for_signal(); } }; Constructible _session_blockade; Env(Genode::Entrypoint &ep) : _ep(ep) { env_ptr = this; } Genode::Parent &parent() override { return _parent; } Genode::Ram_session &ram() override { return *Genode::env_deprecated()->ram_session(); } Genode::Cpu_session &cpu() override { return *Genode::env_deprecated()->cpu_session(); } Genode::Region_map &rm() override { return *Genode::env_deprecated()->rm_session(); } Genode::Pd_session &pd() override { return *Genode::env_deprecated()->pd_session(); } Genode::Entrypoint &ep() override { return _ep; } Genode::Ram_session_capability ram_session_cap() override { return Genode::env_deprecated()->ram_session_cap(); } Genode::Cpu_session_capability cpu_session_cap() override { return Genode::env_deprecated()->cpu_session_cap(); } Genode::Pd_session_capability pd_session_cap() override { return Genode::env_deprecated()->pd_session_cap(); } Genode::Id_space &id_space() override { return Genode::env_session_id_space(); } void reinit(Native_capability::Raw raw) override { Genode::env_deprecated()->reinit(raw); } void reinit_main_thread(Capability &stack_area_rm) override { Genode::env_deprecated()->reinit_main_thread(stack_area_rm); } void _block_for_session() { /* * Construct blockade lazily be avoid it being used in core where * all session requests are immediately answered. */ if (!_session_blockade.constructed()) _session_blockade.construct(_parent); _session_blockade->block(); } Session_capability session(Parent::Service_name const &name, Parent::Client::Id id, Parent::Session_args const &args, Affinity const &affinity) override { Lock::Guard guard(_lock); /* * Since we account for the backing store for session meta data on * the route between client and server, the session quota provided * by the client may become successively diminished by intermediate * components, prompting the server to deny the session request. */ /* extract session quota as specified by the 'Connection' */ char argbuf[Parent::Session_args::MAX_SIZE]; strncpy(argbuf, args.string(), sizeof(argbuf)); Ram_quota ram_quota = ram_quota_from_args(argbuf); Cap_quota cap_quota = cap_quota_from_args(argbuf); unsigned warn_after_attempts = 2; for (unsigned cnt = 0;; cnt++) { try { Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", String<32>(ram_quota).string()); Arg_string::set_arg(argbuf, sizeof(argbuf), "cap_quota", String<32>(cap_quota).string()); Session_capability cap = _parent.session(id, name, Parent::Session_args(argbuf), affinity); if (cap.valid()) return cap; _block_for_session(); return _parent.session_cap(id); } catch (Insufficient_ram_quota) { ram_quota = Ram_quota { ram_quota.value + 4096 }; } catch (Insufficient_cap_quota) { cap_quota = Cap_quota { cap_quota.value + 4 }; } catch (Out_of_ram) { if (ram_quota.value > ram().avail_ram().value) { Parent::Resource_args args(String<64>("ram_quota=", ram_quota)); _parent.resource_request(args); } } catch (Out_of_caps) { if (cap_quota.value > pd().avail_caps().value) { Parent::Resource_args args(String<64>("cap_quota=", cap_quota)); _parent.resource_request(args); } } if (cnt == warn_after_attempts) { warning("re-attempted ", name.string(), " session request ", cnt, " times (args: ", Cstring(argbuf), ")"); warn_after_attempts *= 2; } } } void upgrade(Parent::Client::Id id, Parent::Upgrade_args const &args) override { Lock::Guard guard(_lock); if (_parent.upgrade(id, args) == Parent::UPGRADE_PENDING) _block_for_session(); } void close(Parent::Client::Id id) override { Lock::Guard guard(_lock); if (_parent.close(id) == Parent::CLOSE_PENDING) _block_for_session(); } void exec_static_constructors() override { Genode::exec_static_constructors(); } }; } namespace Genode { struct Startup; extern void bootstrap_component(); Env &internal_env() { class Env_ptr_not_initialized { }; if (!env_ptr) throw Env_ptr_not_initialized(); return *env_ptr; } } Genode::size_t Component::stack_size() __attribute__((weak)); Genode::size_t Component::stack_size() { return 64*1024; } /* * We need to execute the constructor of the main entrypoint from a * class called 'Startup' as 'Startup' is a friend of 'Entrypoint'. */ struct Genode::Startup { ::Env env { ep }; bool const exception_handling = (init_exception_handling(env), true); /* * The construction of the main entrypoint does never return. */ Entrypoint ep { env }; }; void Genode::bootstrap_component() { static Startup startup; /* never reached */ }