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 * promote requests to non-local
* services * services
*/ */
Local_parent(Parent_capability parent_cap, Local_parent(Parent_capability parent_cap, Allocator &);
Emergency_ram_reserve &,
Allocator &);
}; };
#endif /* _INCLUDE__BASE__INTERNAL__LOCAL_PARENT_H_ */ #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 * 'Platform_env' used by all processes except for core
*/ */
class Genode::Platform_env : public Platform_env_base, class Genode::Platform_env : public Platform_env_base
public Expanding_parent_client::Emergency_ram_reserve
{ {
private: private:
@ -113,14 +112,6 @@ class Genode::Platform_env : public Platform_env_base,
Heap _heap; 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) * 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); } ~Platform_env() { _parent().exit(0); }
/*************************************
** Emergency_ram_reserve interface **
*************************************/
void release() { ram_session()->free(_emergency_ram_ds); }
/****************************** /******************************
** Env_deprecated interface ** ** 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, Local_parent::Local_parent(Parent_capability parent_cap,
Emergency_ram_reserve &reserve,
Allocator &alloc) 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() 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; 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())), 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()))), static_cap_cast<Pd_session> (_parent().session_cap(Parent::Env::pd()))),
_heap(Platform_env_base::ram_session(), Platform_env_base::rm_session()), _heap(Platform_env_base::ram_session(), Platform_env_base::rm_session())
_emergency_ram_ds(ram_session()->alloc(_emergency_ram_size()))
{ {
_attach_stack_area(); _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(); } 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 ** ** Core child **
****************/ ****************/

View File

@ -28,13 +28,6 @@ namespace Genode { class Expanding_parent_client; }
class Genode::Expanding_parent_client : public Parent_client class Genode::Expanding_parent_client : public Parent_client
{ {
public:
struct Emergency_ram_reserve
{
virtual void release() = 0;
};
private: private:
/** /**
@ -58,29 +51,43 @@ class Genode::Expanding_parent_client : public Parent_client
Lock _lock; 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 * Block for resource response arriving at the fallback signal handler
*/ */
static void _wait_for_resource_response(); void _wait_for_resource_response() {
_fallback_sig_rcv->wait_for_signal(); }
/**
* 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;
public: public:
Expanding_parent_client(Parent_capability cap, Expanding_parent_client(Parent_capability cap)
Emergency_ram_reserve &emergency_ram_reserve) : Parent_client(cap) { }
:
Parent_client(cap), _emergency_ram_reserve(emergency_ram_reserve)
{ } /**
* 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. * Install fallback signal handler not yet installed.
*/ */
if (_state == UNDEFINED) { if (_state == UNDEFINED) {
Parent_client::resource_avail_sigh(_fallback_sig_cap()); Parent_client::resource_avail_sigh(_fallback_sig_cap);
_state = BLOCKING_DEFAULT; _state = BLOCKING_DEFAULT;
} }

View File

@ -36,6 +36,7 @@ namespace Genode {
void init_signal_thread(Env &); void init_signal_thread(Env &);
void init_root_proxy(Env &); void init_root_proxy(Env &);
void init_log(); void init_log();
void init_parent_resource_requests(Env &);
void exec_static_constructors(); void exec_static_constructors();
void destroy_signal_thread(); void destroy_signal_thread();

View File

@ -42,8 +42,7 @@ namespace Genode {
} }
class Genode::Platform_env : public Platform_env_base, class Genode::Platform_env : public Platform_env_base
public Expanding_parent_client::Emergency_ram_reserve
{ {
private: private:
@ -81,14 +80,6 @@ class Genode::Platform_env : public Platform_env_base,
*/ */
Attached_stack_area _stack_area { _parent_client, _resources.pd }; 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: public:
/** /**
@ -96,10 +87,9 @@ class Genode::Platform_env : public Platform_env_base,
*/ */
Platform_env() Platform_env()
: :
_parent_client(Genode::parent_cap(), *this), _parent_client(Genode::parent_cap()),
_resources(_parent_client), _resources(_parent_client),
_heap(&_resources.pd, &_resources.rm, Heap::UNLIMITED), _heap(&_resources.pd, &_resources.rm, Heap::UNLIMITED)
_emergency_ram_ds(_resources.pd.alloc(_emergency_ram_size()))
{ {
env_stack_area_ram_allocator = &_resources.pd; env_stack_area_ram_allocator = &_resources.pd;
env_stack_area_region_map = &_stack_area; 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; 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 ** ** Env_deprecated interface **
******************************/ ******************************/

View File

@ -274,6 +274,12 @@ namespace {
Genode::call_global_static_constructors(); Genode::call_global_static_constructors();
Genode::init_signal_transmitter(env); Genode::init_signal_transmitter(env);
/*
* Now, as signaling is available, initialize the asynchronous
* parent resource mechanism
*/
init_parent_resource_requests(env);
Component::construct(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; * Catch up asynchronous resource request and notification
} * mechanism construction of the expanding parent environment
*/
using Parent = Expanding_parent_client;
Genode::Signal_context_capability static_cast<Parent*>(&env.parent())->init_fallback_signal_handling();
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();
} }

View File

@ -59,7 +59,7 @@ void Genode::Platform_env::reinit(Native_capability::Raw raw)
* Re-initialize 'Platform_env' members * Re-initialize 'Platform_env' members
*/ */
Expanding_parent_client * const p = &_parent_client; 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); construct_at<Resources>(&_resources, _parent_client);
/* /*