258 lines
6.3 KiB
C++
258 lines
6.3 KiB
C++
/*
|
|
* \brief Component bootstrap
|
|
* \author Norman Feske
|
|
* \author Christian Helmuth
|
|
* \date 2016-01-13
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2016-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <util/retry.h>
|
|
#include <base/component.h>
|
|
#include <base/connection.h>
|
|
#include <base/service.h>
|
|
#include <base/env.h>
|
|
#include <deprecated/env.h>
|
|
|
|
/* base-internal includes */
|
|
#include <base/internal/globals.h>
|
|
|
|
/*
|
|
* XXX remove this pointer once 'Env_deprecated' is removed
|
|
*/
|
|
static Genode::Env *env_ptr = nullptr;
|
|
|
|
/**
|
|
* Excecute pending static constructors
|
|
*
|
|
* The weak function is used for statically linked binaries. The dynamic linker
|
|
* provides the real implementation for dynamically linked components.
|
|
*/
|
|
void Genode::exec_static_constructors() __attribute__((weak));
|
|
void Genode::exec_static_constructors() { }
|
|
|
|
namespace {
|
|
|
|
using namespace Genode;
|
|
|
|
struct Env : Genode::Env
|
|
{
|
|
Genode::Entrypoint &_ep;
|
|
|
|
Genode::Parent &_parent = *env_deprecated()->parent();
|
|
|
|
/**
|
|
* Mutex for serializing 'session' and 'close'
|
|
*/
|
|
Genode::Mutex _mutex { };
|
|
|
|
/**
|
|
* Utility to used block for single signal
|
|
*/
|
|
struct Blockade
|
|
{
|
|
Parent &_parent;
|
|
Genode::Signal_receiver _sig_rec { };
|
|
Genode::Signal_context _sig_ctx { };
|
|
|
|
Blockade(Parent &parent) : _parent(parent)
|
|
{
|
|
_parent.session_sigh(_sig_rec.manage(&_sig_ctx));
|
|
}
|
|
|
|
void block() { _sig_rec.wait_for_signal(); }
|
|
};
|
|
|
|
Constructible<Blockade> _session_blockade { };
|
|
|
|
Env(Genode::Entrypoint &ep) : _ep(ep) { env_ptr = this; }
|
|
|
|
Genode::Parent &parent() override { return _parent; }
|
|
Genode::Cpu_session &cpu() override { return *Genode::env_deprecated()->cpu_session(); }
|
|
Genode::Region_map &rm() override { return *Genode::env_deprecated()->rm_session(); }
|
|
Genode::Pd_session &pd() override { return *Genode::env_deprecated()->pd_session(); }
|
|
Genode::Entrypoint &ep() override { return _ep; }
|
|
|
|
Genode::Cpu_session_capability cpu_session_cap() override
|
|
{
|
|
return Genode::env_deprecated()->cpu_session_cap();
|
|
}
|
|
|
|
Genode::Pd_session_capability pd_session_cap() override
|
|
{
|
|
return Genode::env_deprecated()->pd_session_cap();
|
|
}
|
|
|
|
Genode::Id_space<Parent::Client> &id_space() override
|
|
{
|
|
return Genode::env_session_id_space();
|
|
}
|
|
|
|
void reinit(Native_capability::Raw raw) override
|
|
{
|
|
Genode::env_deprecated()->reinit(raw);
|
|
}
|
|
|
|
void reinit_main_thread(Capability<Region_map> &stack_area_rm) override
|
|
{
|
|
Genode::env_deprecated()->reinit_main_thread(stack_area_rm);
|
|
}
|
|
|
|
void _block_for_session()
|
|
{
|
|
/*
|
|
* Construct blockade lazily be avoid it being used in core where
|
|
* all session requests are immediately answered.
|
|
*/
|
|
if (!_session_blockade.constructed())
|
|
_session_blockade.construct(_parent);
|
|
|
|
_session_blockade->block();
|
|
}
|
|
|
|
Session_capability session(Parent::Service_name const &name,
|
|
Parent::Client::Id id,
|
|
Parent::Session_args const &args,
|
|
Affinity const &affinity) override
|
|
{
|
|
Mutex::Guard guard(_mutex);
|
|
|
|
/*
|
|
* Since we account for the backing store for session meta data on
|
|
* the route between client and server, the session quota provided
|
|
* by the client may become successively diminished by intermediate
|
|
* components, prompting the server to deny the session request.
|
|
*/
|
|
|
|
/* extract session quota as specified by the 'Connection' */
|
|
char argbuf[Parent::Session_args::MAX_SIZE];
|
|
copy_cstring(argbuf, args.string(), sizeof(argbuf));
|
|
|
|
Ram_quota ram_quota = ram_quota_from_args(argbuf);
|
|
Cap_quota cap_quota = cap_quota_from_args(argbuf);
|
|
|
|
unsigned warn_after_attempts = 2;
|
|
|
|
for (unsigned cnt = 0;; cnt++) {
|
|
|
|
try {
|
|
|
|
Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota",
|
|
String<32>(ram_quota).string());
|
|
|
|
Arg_string::set_arg(argbuf, sizeof(argbuf), "cap_quota",
|
|
String<32>(cap_quota).string());
|
|
|
|
Session_capability cap =
|
|
_parent.session(id, name, Parent::Session_args(argbuf), affinity);
|
|
|
|
if (cap.valid())
|
|
return cap;
|
|
|
|
_block_for_session();
|
|
return _parent.session_cap(id);
|
|
}
|
|
|
|
catch (Insufficient_ram_quota) {
|
|
ram_quota = Ram_quota { ram_quota.value + 4096 }; }
|
|
|
|
catch (Insufficient_cap_quota) {
|
|
cap_quota = Cap_quota { cap_quota.value + 4 }; }
|
|
|
|
catch (Out_of_ram) {
|
|
if (ram_quota.value > pd().avail_ram().value) {
|
|
Parent::Resource_args args(String<64>("ram_quota=", ram_quota));
|
|
_parent.resource_request(args);
|
|
}
|
|
}
|
|
|
|
catch (Out_of_caps) {
|
|
if (cap_quota.value > pd().avail_caps().value) {
|
|
Parent::Resource_args args(String<64>("cap_quota=", cap_quota));
|
|
_parent.resource_request(args);
|
|
}
|
|
}
|
|
|
|
if (cnt == warn_after_attempts) {
|
|
warning("re-attempted ", name.string(), " session request ",
|
|
cnt, " times (args: ", Cstring(argbuf), ")");
|
|
warn_after_attempts *= 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void upgrade(Parent::Client::Id id, Parent::Upgrade_args const &args) override
|
|
{
|
|
Mutex::Guard guard(_mutex);
|
|
|
|
if (_parent.upgrade(id, args) == Parent::UPGRADE_PENDING)
|
|
_block_for_session();
|
|
}
|
|
|
|
void close(Parent::Client::Id id) override
|
|
{
|
|
Mutex::Guard guard(_mutex);
|
|
|
|
if (_parent.close(id) == Parent::CLOSE_PENDING)
|
|
_block_for_session();
|
|
}
|
|
|
|
void exec_static_constructors() override
|
|
{
|
|
Genode::exec_static_constructors();
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
namespace Genode {
|
|
|
|
struct Startup;
|
|
|
|
extern void bootstrap_component();
|
|
|
|
Env &internal_env()
|
|
{
|
|
class Env_ptr_not_initialized { };
|
|
if (!env_ptr)
|
|
throw Env_ptr_not_initialized();
|
|
|
|
return *env_ptr;
|
|
}
|
|
}
|
|
|
|
|
|
Genode::size_t Component::stack_size() __attribute__((weak));
|
|
Genode::size_t Component::stack_size() { return 64*1024; }
|
|
|
|
|
|
/*
|
|
* We need to execute the constructor of the main entrypoint from a
|
|
* class called 'Startup' as 'Startup' is a friend of 'Entrypoint'.
|
|
*/
|
|
struct Genode::Startup
|
|
{
|
|
::Env env { ep };
|
|
|
|
bool const exception_handling = (init_exception_handling(env), true);
|
|
|
|
/*
|
|
* The construction of the main entrypoint does never return.
|
|
*/
|
|
Entrypoint ep { env };
|
|
};
|
|
|
|
|
|
void Genode::bootstrap_component()
|
|
{
|
|
static Startup startup;
|
|
|
|
/* never reached */
|
|
}
|