From 6f8dc9054a1beea053ce49e16d04f59cce7431b4 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Tue, 13 Jun 2017 13:18:11 +0200 Subject: [PATCH] base: setup parent upgrade mechanism eagerly Fix #2447 --- .../src/include/base/internal/local_parent.h | 4 +- .../src/include/base/internal/platform_env.h | 18 +------ repos/base-linux/src/lib/base/platform_env.cc | 8 ++- repos/base/src/core/main.cc | 6 +++ .../base/internal/expanding_parent_client.h | 53 +++++++++++-------- .../base/src/include/base/internal/globals.h | 1 + .../src/include/base/internal/platform_env.h | 28 ++-------- repos/base/src/lib/base/entrypoint.cc | 6 +++ repos/base/src/lib/base/env_deprecated.cc | 49 +++-------------- repos/base/src/lib/base/env_reinit.cc | 2 +- 10 files changed, 59 insertions(+), 116 deletions(-) diff --git a/repos/base-linux/src/include/base/internal/local_parent.h b/repos/base-linux/src/include/base/internal/local_parent.h index 03104d7e6e..e62f7052a8 100644 --- a/repos/base-linux/src/include/base/internal/local_parent.h +++ b/repos/base-linux/src/include/base/internal/local_parent.h @@ -65,9 +65,7 @@ class Genode::Local_parent : public Expanding_parent_client * promote requests to non-local * services */ - Local_parent(Parent_capability parent_cap, - Emergency_ram_reserve &, - Allocator &); + Local_parent(Parent_capability parent_cap, Allocator &); }; #endif /* _INCLUDE__BASE__INTERNAL__LOCAL_PARENT_H_ */ diff --git a/repos/base-linux/src/include/base/internal/platform_env.h b/repos/base-linux/src/include/base/internal/platform_env.h index f7259dfb48..c0c146ba4c 100644 --- a/repos/base-linux/src/include/base/internal/platform_env.h +++ b/repos/base-linux/src/include/base/internal/platform_env.h @@ -101,8 +101,7 @@ class Genode::Platform_env_base : public Env_deprecated /** * 'Platform_env' used by all processes except for core */ -class Genode::Platform_env : public Platform_env_base, - public Expanding_parent_client::Emergency_ram_reserve +class Genode::Platform_env : public Platform_env_base { private: @@ -113,14 +112,6 @@ class Genode::Platform_env : public Platform_env_base, Heap _heap; - /* - * Emergency RAM reserve - * - * See the comment of '_fallback_sig_cap()' in 'env/env.cc'. - */ - constexpr static size_t _emergency_ram_size() { return 8*1024; } - Ram_dataspace_capability _emergency_ram_ds; - /** * Attach stack area to local address space (for non-hybrid components) */ @@ -139,13 +130,6 @@ class Genode::Platform_env : public Platform_env_base, ~Platform_env() { _parent().exit(0); } - /************************************* - ** Emergency_ram_reserve interface ** - *************************************/ - - void release() { ram_session()->free(_emergency_ram_ds); } - - /****************************** ** Env_deprecated interface ** ******************************/ diff --git a/repos/base-linux/src/lib/base/platform_env.cc b/repos/base-linux/src/lib/base/platform_env.cc index 9f43672f15..de523dd71a 100644 --- a/repos/base-linux/src/lib/base/platform_env.cc +++ b/repos/base-linux/src/lib/base/platform_env.cc @@ -101,10 +101,9 @@ Parent::Close_result Local_parent::close(Client::Id id) Local_parent::Local_parent(Parent_capability parent_cap, - Emergency_ram_reserve &reserve, Allocator &alloc) : - Expanding_parent_client(parent_cap, reserve), _alloc(alloc) + Expanding_parent_client(parent_cap), _alloc(alloc) { } @@ -148,7 +147,7 @@ static Parent_capability obtain_parent_cap() Local_parent &Platform_env::_parent() { - static Local_parent local_parent(obtain_parent_cap(), *this, _heap); + static Local_parent local_parent(obtain_parent_cap(), _heap); return local_parent; } @@ -157,8 +156,7 @@ Platform_env::Platform_env() : Platform_env_base(static_cap_cast(_parent().session_cap(Parent::Env::cpu())), static_cap_cast (_parent().session_cap(Parent::Env::pd()))), - _heap(Platform_env_base::ram_session(), Platform_env_base::rm_session()), - _emergency_ram_ds(ram_session()->alloc(_emergency_ram_size())) + _heap(Platform_env_base::ram_session(), Platform_env_base::rm_session()) { _attach_stack_area(); diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 52eb15d489..2a99aca8bd 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -92,6 +92,12 @@ Platform_generic *Genode::platform() { return platform_specific(); } Thread_capability Genode::main_thread_cap() { return Thread_capability(); } +/** + * Dummy implementation for core that has no parent to ask for resources + */ +void Genode::init_parent_resource_requests(Genode::Env & env) {}; + + /**************** ** Core child ** ****************/ diff --git a/repos/base/src/include/base/internal/expanding_parent_client.h b/repos/base/src/include/base/internal/expanding_parent_client.h index c408357a9c..54b7a607c7 100644 --- a/repos/base/src/include/base/internal/expanding_parent_client.h +++ b/repos/base/src/include/base/internal/expanding_parent_client.h @@ -28,13 +28,6 @@ namespace Genode { class Expanding_parent_client; } class Genode::Expanding_parent_client : public Parent_client { - public: - - struct Emergency_ram_reserve - { - virtual void release() = 0; - }; - private: /** @@ -58,29 +51,43 @@ class Genode::Expanding_parent_client : public Parent_client Lock _lock; /** - * Return signal context capability for the fallback signal handler + * Signal context for the fallback signal handler */ - Signal_context_capability _fallback_sig_cap(); + Signal_context _fallback_sig_ctx; + + /** + * Signal context capability for the fallback signal handler + */ + Signal_context_capability _fallback_sig_cap; + + /** + * Signal receiver for the fallback signal handler + */ + Constructible _fallback_sig_rcv; /** * Block for resource response arriving at the fallback signal handler */ - static void _wait_for_resource_response(); - - /** - * Emergency RAM reserve for constructing the fallback signal handler - * - * See the comment of '_fallback_sig_cap()' in 'env/env.cc'. - */ - Emergency_ram_reserve &_emergency_ram_reserve; + void _wait_for_resource_response() { + _fallback_sig_rcv->wait_for_signal(); } public: - Expanding_parent_client(Parent_capability cap, - Emergency_ram_reserve &emergency_ram_reserve) - : - Parent_client(cap), _emergency_ram_reserve(emergency_ram_reserve) - { } + Expanding_parent_client(Parent_capability cap) + : Parent_client(cap) { } + + + /** + * Downstreamed construction of the fallback signaling, used + * when the environment is ready to construct a signal receiver + */ + void init_fallback_signal_handling() + { + if (!_fallback_sig_cap.valid()) { + _fallback_sig_rcv.construct(); + _fallback_sig_cap = _fallback_sig_rcv->manage(&_fallback_sig_ctx); + } + } /********************** @@ -168,7 +175,7 @@ class Genode::Expanding_parent_client : public Parent_client * Install fallback signal handler not yet installed. */ if (_state == UNDEFINED) { - Parent_client::resource_avail_sigh(_fallback_sig_cap()); + Parent_client::resource_avail_sigh(_fallback_sig_cap); _state = BLOCKING_DEFAULT; } diff --git a/repos/base/src/include/base/internal/globals.h b/repos/base/src/include/base/internal/globals.h index 6e52045faf..f0d4f46b18 100644 --- a/repos/base/src/include/base/internal/globals.h +++ b/repos/base/src/include/base/internal/globals.h @@ -36,6 +36,7 @@ namespace Genode { void init_signal_thread(Env &); void init_root_proxy(Env &); void init_log(); + void init_parent_resource_requests(Env &); void exec_static_constructors(); void destroy_signal_thread(); diff --git a/repos/base/src/include/base/internal/platform_env.h b/repos/base/src/include/base/internal/platform_env.h index 68f238170c..a974fd205c 100644 --- a/repos/base/src/include/base/internal/platform_env.h +++ b/repos/base/src/include/base/internal/platform_env.h @@ -42,8 +42,7 @@ namespace Genode { } -class Genode::Platform_env : public Platform_env_base, - public Expanding_parent_client::Emergency_ram_reserve +class Genode::Platform_env : public Platform_env_base { private: @@ -81,14 +80,6 @@ class Genode::Platform_env : public Platform_env_base, */ Attached_stack_area _stack_area { _parent_client, _resources.pd }; - /* - * Emergency RAM reserve - * - * See the comment of '_fallback_sig_cap()' in 'env/env.cc'. - */ - constexpr static size_t _emergency_ram_size() { return 16*1024; } - Ram_dataspace_capability _emergency_ram_ds; - public: /** @@ -96,10 +87,9 @@ class Genode::Platform_env : public Platform_env_base, */ Platform_env() : - _parent_client(Genode::parent_cap(), *this), + _parent_client(Genode::parent_cap()), _resources(_parent_client), - _heap(&_resources.pd, &_resources.rm, Heap::UNLIMITED), - _emergency_ram_ds(_resources.pd.alloc(_emergency_ram_size())) + _heap(&_resources.pd, &_resources.rm, Heap::UNLIMITED) { env_stack_area_ram_allocator = &_resources.pd; env_stack_area_region_map = &_stack_area; @@ -112,18 +102,6 @@ class Genode::Platform_env : public Platform_env_base, void reinit_main_thread(Capability &) override; - /************************************* - ** Emergency_ram_reserve interface ** - *************************************/ - - void release() - { - log("used before freeing emergency=", _resources.pd.used_ram()); - _resources.pd.free(_emergency_ram_ds); - log("used after freeing emergency=", _resources.pd.used_ram()); - } - - /****************************** ** Env_deprecated interface ** ******************************/ diff --git a/repos/base/src/lib/base/entrypoint.cc b/repos/base/src/lib/base/entrypoint.cc index 5b9643a5f7..16381074a9 100644 --- a/repos/base/src/lib/base/entrypoint.cc +++ b/repos/base/src/lib/base/entrypoint.cc @@ -274,6 +274,12 @@ namespace { Genode::call_global_static_constructors(); Genode::init_signal_transmitter(env); + /* + * Now, as signaling is available, initialize the asynchronous + * parent resource mechanism + */ + init_parent_resource_requests(env); + Component::construct(env); } }; diff --git a/repos/base/src/lib/base/env_deprecated.cc b/repos/base/src/lib/base/env_deprecated.cc index 6c7ba94803..16f734b390 100644 --- a/repos/base/src/lib/base/env_deprecated.cc +++ b/repos/base/src/lib/base/env_deprecated.cc @@ -34,47 +34,12 @@ namespace Genode { } -static Genode::Signal_receiver *resource_sig_rec() +void Genode::init_parent_resource_requests(Genode::Env & env) { - static Genode::Signal_receiver sig_rec; - return &sig_rec; -} - - -Genode::Signal_context_capability -Genode::Expanding_parent_client::_fallback_sig_cap() -{ - static Signal_context _sig_ctx; - static Signal_context_capability _sig_cap; - - /* create signal-context capability only once */ - if (!_sig_cap.valid()) { - - /* - * Because the 'manage' function consumes meta data of the signal - * session, calling it may result in an 'Out_of_ram' or 'Out_of_caps' error. - * The 'manage' function handles this error by upgrading the session quota - * accordingly. However, this upgrade, in turn, may result in the - * depletion of the process' RAM quota. In this case, the process would - * issue a resource request to the parent. But in order to do so, the - * fallback signal handler has to be constructed. To solve this - * hen-and-egg problem, we allocate a so-called emergency RAM reserve - * immediately at the startup of the process as part of the - * 'Platform_env'. When initializing the fallback signal handler, these - * resources get released in order to ensure an eventual upgrade of the - * signal session to succeed. - * - * The corner case is tested by 'os/src/test/resource_request'. - */ - _emergency_ram_reserve.release(); - _sig_cap = resource_sig_rec()->manage(&_sig_ctx); - } - - return _sig_cap; -} - - -void Genode::Expanding_parent_client::_wait_for_resource_response() -{ - resource_sig_rec()->wait_for_signal(); + /** + * Catch up asynchronous resource request and notification + * mechanism construction of the expanding parent environment + */ + using Parent = Expanding_parent_client; + static_cast(&env.parent())->init_fallback_signal_handling(); } diff --git a/repos/base/src/lib/base/env_reinit.cc b/repos/base/src/lib/base/env_reinit.cc index c970de09ef..9f19789be1 100644 --- a/repos/base/src/lib/base/env_reinit.cc +++ b/repos/base/src/lib/base/env_reinit.cc @@ -59,7 +59,7 @@ void Genode::Platform_env::reinit(Native_capability::Raw raw) * Re-initialize 'Platform_env' members */ Expanding_parent_client * const p = &_parent_client; - construct_at(p, parent_cap(), *this); + construct_at(p, parent_cap()); construct_at(&_resources, _parent_client); /*