base: setup parent upgrade mechanism eagerly

Fix #2447
This commit is contained in:
Stefan Kalkowski 2017-06-13 13:18:11 +02:00 committed by Christian Helmuth
parent 06b25a9082
commit 6f8dc9054a
10 changed files with 59 additions and 116 deletions

View File

@ -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_ */

View File

@ -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 **
******************************/

View File

@ -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<Cpu_session>(_parent().session_cap(Parent::Env::cpu())),
static_cap_cast<Pd_session> (_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();

View File

@ -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 **
****************/

View File

@ -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<Signal_receiver> _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;
}

View File

@ -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();

View File

@ -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<Region_map> &) 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 **
******************************/

View File

@ -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);
}
};

View File

@ -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<Parent*>(&env.parent())->init_fallback_signal_handling();
}

View File

@ -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<Expanding_parent_client>(p, parent_cap(), *this);
construct_at<Expanding_parent_client>(p, parent_cap());
construct_at<Resources>(&_resources, _parent_client);
/*