From ae40cb545c32d28bcb79cac0cd8df413a37783ab Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 25 Sep 2013 15:36:23 +0200 Subject: [PATCH] base: Unify 'Platform_env' across platforms --- base-linux/lib/mk/base-common.mk | 2 +- base-linux/lib/mk/base.inc | 2 +- base-linux/src/base/env/platform_env.h | 102 +++----- base-linux/src/core/target.mk | 1 + base/src/base/env/platform_env.h | 319 +++++++++--------------- base/src/base/env/platform_env_common.h | 85 +++++++ 6 files changed, 242 insertions(+), 269 deletions(-) create mode 100644 base/src/base/env/platform_env_common.h diff --git a/base-linux/lib/mk/base-common.mk b/base-linux/lib/mk/base-common.mk index 8bd39b991..b96cf8726 100644 --- a/base-linux/lib/mk/base-common.mk +++ b/base-linux/lib/mk/base-common.mk @@ -24,7 +24,7 @@ SRC_CC += thread/trace.cc INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock INC_DIR += $(REP_DIR)/src/base/ipc -INC_DIR += $(REP_DIR)/src/base/env +INC_DIR += $(REP_DIR)/src/base/env $(BASE_DIR)/src/base/env INC_DIR += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform INC_DIR += $(BASE_DIR)/src/base/thread diff --git a/base-linux/lib/mk/base.inc b/base-linux/lib/mk/base.inc index 3cc6e6861..425110501 100644 --- a/base-linux/lib/mk/base.inc +++ b/base-linux/lib/mk/base.inc @@ -12,7 +12,7 @@ LIBS += base-common syscall SRC_CC += console/log_console.cc SRC_CC += env/env.cc env/platform_env.cc env/context_area.cc -INC_DIR += $(REP_DIR)/src/base/env +INC_DIR += $(REP_DIR)/src/base/env $(BASE_DIR)/src/base/env vpath %.cc $(REP_DIR)/src/base vpath %.cc $(BASE_DIR)/src/base diff --git a/base-linux/src/base/env/platform_env.h b/base-linux/src/base/env/platform_env.h index bc58ade66..a7d923323 100644 --- a/base-linux/src/base/env/platform_env.h +++ b/base-linux/src/base/env/platform_env.h @@ -12,22 +12,45 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _INCLUDE__BASE__PLATFORM_ENV_H_ -#define _INCLUDE__BASE__PLATFORM_ENV_H_ +#ifndef _PLATFORM_ENV_H_ +#define _PLATFORM_ENV_H_ +/* Linux includes */ #include #include #include #include -#include -#include +/* Genode includes */ #include #include -#include -#include #include -#include + +/* local includes (from 'base/src/base/env/') */ +#include + + +namespace Genode { + struct Expanding_cpu_session_client; + class Platform_env; +} + + +struct Genode::Expanding_cpu_session_client +: + Upgradeable_client +{ + Expanding_cpu_session_client(Genode::Capability cap) + : Upgradeable_client(cap) { } + + Thread_capability create_thread(Name const &name, addr_t utcb) + { + return retry( + [&] () { return Linux_cpu_session_client::create_thread(name, utcb); }, + [&] () { upgrade_ram(8*1024); }); + } +}; + namespace Genode { @@ -292,69 +315,6 @@ namespace Genode { private: - class Expanding_ram_session_client : public Ram_session_client - { - Ram_session_capability _cap; - - public: - - Expanding_ram_session_client(Ram_session_capability cap) - : Ram_session_client(cap), _cap(cap) { } - - Ram_dataspace_capability alloc(size_t size, bool cached) - { - bool try_again; - do { - try_again = false; - try { - return Ram_session_client::alloc(size, cached); - - } catch (Ram_session::Out_of_metadata) { - - /* give up if the error occurred a second time */ - if (try_again) - break; - - PINF("upgrading quota donation for Env::RAM session"); - env()->parent()->upgrade(_cap, "ram_quota=8K"); - try_again = true; - } - } while (try_again); - - return Ram_dataspace_capability(); - } - }; - - class Expanding_cpu_session_client : public Linux_cpu_session_client - { - Cpu_session_capability _cap; - - public: - - Expanding_cpu_session_client(Cpu_session_capability cap) - : Linux_cpu_session_client(static_cap_cast(cap)), _cap(cap) { } - - Thread_capability create_thread(Name const &name, addr_t utcb = 0) { - bool try_again; - do { - try_again = false; - try { - return Linux_cpu_session_client::create_thread(name, utcb); - } - catch (Cpu_session::Out_of_metadata) { - if (try_again) - break; - PINF("upgrade quota donation for Env::CPU session"); - env()->parent()->upgrade(_cap, "ram_quota=8K"); - try_again = true; - } - } while (try_again); - - return Thread_capability(); - } - }; - - /******************************* ** Platform-specific members ** *******************************/ @@ -481,4 +441,4 @@ namespace Genode { }; } -#endif /* _INCLUDE__BASE__PLATFORM_ENV_H_ */ +#endif /* _PLATFORM_ENV_H_ */ diff --git a/base-linux/src/core/target.mk b/base-linux/src/core/target.mk index d9fc4a30e..2c32c381f 100644 --- a/base-linux/src/core/target.mk +++ b/base-linux/src/core/target.mk @@ -29,6 +29,7 @@ INC_DIR += $(REP_DIR)/src/core/include \ $(REP_DIR)/src/platform \ $(REP_DIR)/src/base/ipc \ $(REP_DIR)/src/base/env \ + $(BASE_DIR)/src/base/env \ $(REP_DIR)/src/base/console \ $(BASE_DIR)/src/base/thread \ diff --git a/base/src/base/env/platform_env.h b/base/src/base/env/platform_env.h index e2c07c4bb..05b2fb23c 100644 --- a/base/src/base/env/platform_env.h +++ b/base/src/base/env/platform_env.h @@ -17,207 +17,134 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _INCLUDE__BASE__PLATFORM_ENV_H_ -#define _INCLUDE__BASE__PLATFORM_ENV_H_ +#ifndef _PLATFORM_ENV_H_ +#define _PLATFORM_ENV_H_ +/* Genode includes */ +#include #include - #include -#include -#include -#include -#include -#include + +/* local includes */ +#include namespace Genode { - - class Platform_env : public Env - { - class Expanding_rm_session_client : public Rm_session_client - { - Rm_session_capability _cap; - - public: - - Expanding_rm_session_client(Rm_session_capability cap) - : Rm_session_client(cap), _cap(cap) { } - - Local_addr attach(Dataspace_capability ds, - size_t size = 0, off_t offset = 0, - bool use_local_addr = false, - Local_addr local_addr = (addr_t)0, - bool executable = false) { - - bool try_again = false; - do { - try { - return Rm_session_client::attach(ds, size, offset, - use_local_addr, - local_addr, - executable); - - } catch (Rm_session::Out_of_metadata) { - - /* give up if the error occurred a second time */ - if (try_again) - break; - - PINF("upgrading quota donation for Env::RM session"); - env()->parent()->upgrade(_cap, "ram_quota=8K"); - try_again = true; - } - } while (try_again); - - return (addr_t)0; - } - - Pager_capability add_client(Thread_capability thread) - { - bool try_again = false; - do { - try { - return Rm_session_client::add_client(thread); - } catch (Rm_session::Out_of_metadata) { - - /* give up if the error occurred a second time */ - if (try_again) - break; - - PINF("upgrading quota donation for Env::RM session"); - env()->parent()->upgrade(_cap, "ram_quota=8K"); - try_again = true; - } - } while (try_again); - - return Pager_capability(); - } - - void remove_client(Pager_capability pager) - { - Rm_session_client::remove_client(pager); - } - }; - - class Expanding_ram_session_client : public Ram_session_client - { - Ram_session_capability _cap; - - public: - - Expanding_ram_session_client(Ram_session_capability cap) - : Ram_session_client(cap), _cap(cap) { } - - Ram_dataspace_capability alloc(size_t size, bool cached) { - bool try_again = false; - do { - try { - return Ram_session_client::alloc(size, cached); - - } catch (Ram_session::Out_of_metadata) { - - /* give up if the error occurred a second time */ - if (try_again) - break; - - PINF("upgrading quota donation for Env::RAM session"); - env()->parent()->upgrade(_cap, "ram_quota=8K"); - try_again = true; - } - } while (try_again); - - return Ram_dataspace_capability(); - } - }; - - class Expanding_cpu_session_client : public Cpu_session_client - { - Cpu_session_capability _cap; - - public: - - Expanding_cpu_session_client(Cpu_session_capability cap) - : Cpu_session_client(cap), _cap(cap) { } - - Thread_capability create_thread(Name const &name, addr_t utcb) { - bool try_again = false; - do { - try { - return Cpu_session_client::create_thread(name, utcb); - } catch (Cpu_session::Out_of_metadata) { - - /* give up if the error occurred a second time */ - if (try_again) - break; - - PINF("upgrading quota donation for Env::CPU session"); - env()->parent()->upgrade(_cap, "ram_quota=8K"); - try_again = true; - } - } while (try_again); - - return Thread_capability(); - } - }; - - private: - - Parent_client _parent_client; - - struct Resources - { - Ram_session_capability ram_cap; - Expanding_ram_session_client ram; - Cpu_session_capability cpu_cap; - Expanding_cpu_session_client cpu; - Expanding_rm_session_client rm; - Pd_session_client pd; - - Resources(Parent &parent) - : - ram_cap(static_cap_cast(parent.session("Env::ram_session", ""))), - ram(ram_cap), - cpu_cap(static_cap_cast(parent.session("Env::cpu_session", ""))), - cpu(cpu_cap), - rm(static_cap_cast(parent.session("Env::rm_session", ""))), - pd(static_cap_cast(parent.session("Env::pd_session", ""))) - { } - }; - - Resources _resources; - Heap _heap; - - char _initial_junk[sizeof(addr_t) * 4096]; - - public: - - /** - * Standard constructor - */ - Platform_env() - : - _parent_client(Genode::parent_cap()), - _resources(_parent_client), - _heap(&_resources.ram, &_resources.rm, Heap::UNLIMITED, - _initial_junk, sizeof(_initial_junk)) - { } - - void reload_parent_cap(Native_capability::Dst, long); - - - /******************* - ** Env interface ** - *******************/ - - Parent *parent() { return &_parent_client; } - Ram_session *ram_session() { return &_resources.ram; } - Ram_session_capability ram_session_cap() { return _resources.ram_cap; } - Cpu_session *cpu_session() { return &_resources.cpu; } - Cpu_session_capability cpu_session_cap() { return _resources.cpu_cap; } - Rm_session *rm_session() { return &_resources.rm; } - Pd_session *pd_session() { return &_resources.pd; } - Allocator *heap() { return &_heap; } - }; + struct Expanding_rm_session_client; + struct Expanding_cpu_session_client; + class Platform_env; } -#endif /* _INCLUDE__BASE__PLATFORM_ENV_H_ */ + +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(Name const &name, addr_t utcb) + { + return retry( + [&] () { return Cpu_session_client::create_thread(name, utcb); }, + [&] () { upgrade_ram(8*1024); }); + } +}; + + +class Genode::Platform_env : public Genode::Env +{ + private: + + Parent_client _parent_client; + + struct Resources + { + template + Capability request(Parent &parent, char const *service) { + return static_cap_cast(parent.session(service, "")); } + + Ram_session_capability ram_cap; + Expanding_ram_session_client ram = { ram_cap }; + Cpu_session_capability cpu_cap; + Expanding_cpu_session_client cpu = { cpu_cap }; + Expanding_rm_session_client rm; + Pd_session_client pd; + + Resources(Parent &parent) : + ram_cap(request(parent, "Env::ram_session")), + cpu_cap(request(parent, "Env::cpu_session")), + rm (request (parent, "Env::rm_session")), + pd (request (parent, "Env::pd_session")) + { } + }; + + Resources _resources; + Heap _heap; + + char _initial_junk[sizeof(addr_t) * 4096]; + + public: + + /** + * Standard constructor + */ + Platform_env() + : + _parent_client(Genode::parent_cap()), + _resources(_parent_client), + _heap(&_resources.ram, &_resources.rm, Heap::UNLIMITED, + _initial_junk, sizeof(_initial_junk)) + { } + + void reload_parent_cap(Native_capability::Dst, long); + + + /******************* + ** Env interface ** + *******************/ + + Parent *parent() { return &_parent_client; } + Ram_session *ram_session() { return &_resources.ram; } + Ram_session_capability ram_session_cap() { return _resources.ram_cap; } + Cpu_session *cpu_session() { return &_resources.cpu; } + Cpu_session_capability cpu_session_cap() { return _resources.cpu_cap; } + Rm_session *rm_session() { return &_resources.rm; } + Pd_session *pd_session() { return &_resources.pd; } + Allocator *heap() { return &_heap; } +}; + +#endif /* _PLATFORM_ENV_H_ */ diff --git a/base/src/base/env/platform_env_common.h b/base/src/base/env/platform_env_common.h new file mode 100644 index 000000000..7afd7e13e --- /dev/null +++ b/base/src/base/env/platform_env_common.h @@ -0,0 +1,85 @@ +/* + * \brief Platform environment of Genode process + * \author Norman Feske + * \date 2013-09-25 + * + * Parts of 'Platform_env' shared accross all base platforms. + */ + +/* + * 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_COMMON_H_ +#define _PLATFORM_ENV_COMMON_H_ + +#include +#include +#include +#include +#include +#include + +namespace Genode { + class Expanding_rm_session_client; + class Expanding_ram_session_client; + class Expanding_cpu_session_client; +} + + +/** + * Repeatedly try to execute a function 'func' + * + * If the function 'func' throws an exception of type 'EXC', the 'handler' + * is called and the function call is retried. + */ +template +auto retry(FUNC func, HANDLER handler) -> decltype(func()) +{ + for (;;) + try { return func(); } + catch (EXC) { handler(); } +} + + +/** + * Client object for a session that may get its session quota upgraded + */ +template +struct Upgradeable_client : CLIENT +{ + typedef Genode::Capability Capability; + + Capability _cap; + + Upgradeable_client(Capability cap) : CLIENT(cap), _cap(cap) { } + + void upgrade_ram(Genode::size_t quota) + { + PINF("upgrading quota donation for Env::%s (%zd bytes)", + CLIENT::Rpc_interface::service_name(), quota); + + char buf[128]; + Genode::snprintf(buf, sizeof(buf), "ram_quota=%zd", quota); + Genode::env()->parent()->upgrade(_cap, buf); + } +}; + + +struct Genode::Expanding_ram_session_client : Upgradeable_client +{ + Expanding_ram_session_client(Ram_session_capability cap) + : Upgradeable_client(cap) { } + + Ram_dataspace_capability alloc(size_t size, bool cached) + { + return retry( + [&] () { return Ram_session_client::alloc(size, cached); }, + [&] () { upgrade_ram(8*1024); }); + } +}; + +#endif /* _PLATFORM_ENV_COMMON_H_ */