/* * \brief Platform environment of Genode process * \author Norman Feske * \author Christian Helmuth * \date 2006-07-28 * * This file is a generic variant of the platform environment, which is * suitable for platforms such as L4ka::Pistachio and L4/Fiasco. On other * platforms, it may be replaced by a platform-specific version residing * in the corresponding 'base-' repository. */ /* * Copyright (C) 2006-2013 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 _PLATFORM_ENV_H_ #define _PLATFORM_ENV_H_ /* Genode includes */ #include #include #include /* local includes */ #include namespace Genode { struct Expanding_rm_session_client; struct Expanding_cpu_session_client; class Platform_env; } struct Genode::Expanding_rm_session_client : Upgradeable_client { Expanding_rm_session_client(Rm_session_capability cap) : Upgradeable_client(cap) { } Local_addr attach(Dataspace_capability ds, size_t size, off_t offset, bool use_local_addr, Local_addr local_addr, bool executable) { return retry( [&] () { return Rm_session_client::attach(ds, size, offset, use_local_addr, local_addr, executable); }, [&] () { upgrade_ram(8*1024); }); } Pager_capability add_client(Thread_capability thread) { return retry( [&] () { return Rm_session_client::add_client(thread); }, [&] () { upgrade_ram(8*1024); }); } }; struct Genode::Expanding_cpu_session_client : Upgradeable_client { Expanding_cpu_session_client(Genode::Cpu_session_capability cap) : /* * We need to upcast the capability because on some platforms (i.e., * NOVA), 'Cpu_session_client' refers to a platform-specific session * interface ('Nova_cpu_session'). */ Upgradeable_client (static_cap_cast(cap)) { } Thread_capability create_thread(size_t quota, Name const &name, addr_t utcb) { return retry( [&] () { return Cpu_session_client::create_thread(quota, name, utcb); }, [&] () { upgrade_ram(8*1024); }); } }; class Genode::Platform_env : public Genode::Env, public Emergency_ram_reserve { private: Expanding_parent_client _parent_client; struct Resources { template Capability request(Parent &parent, char const *service) { return static_cap_cast(parent.session(service, "")); } Expanding_ram_session_client ram; Expanding_cpu_session_client cpu; Expanding_rm_session_client rm; Pd_session_client pd; Resources(Parent &parent) : ram(request(parent, "Env::ram_session")), cpu(request(parent, "Env::cpu_session")), rm (request (parent, "Env::rm_session")), pd (request (parent, "Env::pd_session")) { } }; Resources _resources; Heap _heap; char _initial_heap_chunk[sizeof(addr_t) * 4096]; /* * Emergency RAM reserve * * See the comment of '_fallback_sig_cap()' in 'env/env.cc'. */ constexpr static size_t _emergency_ram_size() { return 4*1024; } Ram_dataspace_capability _emergency_ram_ds; public: /** * Standard constructor */ Platform_env() : _parent_client(Genode::parent_cap(), *this), _resources(_parent_client), _heap(&_resources.ram, &_resources.rm, Heap::UNLIMITED, _initial_heap_chunk, sizeof(_initial_heap_chunk)), _emergency_ram_ds(_resources.ram.alloc(_emergency_ram_size())) { } /** * Reload parent capability and reinitialize environment resources * * This function is solely used for implementing fork semantics. * After forking a process, the new child process is executed * within a copy of the address space of the forking process. * Thereby, the new process inherits the original 'env' object of * the forking process, which is meaningless in the context of the * new process. By calling this function, the new process is able * to reinitialize its 'env' with meaningful capabilities obtained * via its updated parent capability. */ void reinit(Native_capability::Dst, long); /** * Reinitialize main-thread object * * \param context_area_rm new RM session of the context area * * This function is solely used for implementing fork semantics * as provided by the Noux environment. */ void reinit_main_thread(Rm_session_capability &); /************************************* ** Emergency_ram_reserve interface ** *************************************/ void release() { PDBG("used before freeing emergency=%zu", _resources.ram.used()); _resources.ram.free(_emergency_ram_ds); PDBG("used after freeing emergency=%zu", _resources.ram.used()); } /******************* ** Env interface ** *******************/ Parent *parent() { return &_parent_client; } Ram_session *ram_session() { return &_resources.ram; } Ram_session_capability ram_session_cap() { return _resources.ram; } Cpu_session *cpu_session() { return &_resources.cpu; } Cpu_session_capability cpu_session_cap() { return _resources.cpu; } Rm_session *rm_session() { return &_resources.rm; } Pd_session *pd_session() { return &_resources.pd; } Allocator *heap() { return &_heap; } }; #endif /* _PLATFORM_ENV_H_ */