mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-26 13:59:57 +00:00
This commit restores the diag feature for selecting diagnostic output of services provided by core. This feature became unavailable with commit "base: remove dependency from deprecated APIs", which hard-wired the diag flag for core services to false. To control this feature, three possible policies can be expressed in a routing target of init's configuration: * Forcing silence by specifying 'diag="no"' * Enabling diagnostics by specifying 'diag="yes"' * Forwarding the preference of the client by omitting the 'diag' attribute Fixes #3962
185 lines
5.2 KiB
C++
185 lines
5.2 KiB
C++
/*
|
|
* \brief Connection to a local child
|
|
* \author Norman Feske
|
|
* \date 2016-11-10
|
|
*
|
|
* The 'Local_connection' can be used to locally establish a connection
|
|
* to a 'Local_service' or a 'Parent_service'.
|
|
*/
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__BASE__LOCAL_CONNECTION_H_
|
|
#define _INCLUDE__BASE__LOCAL_CONNECTION_H_
|
|
|
|
#include <util/arg_string.h>
|
|
#include <base/service.h>
|
|
|
|
namespace Genode {
|
|
|
|
class Local_connection_base;
|
|
template <typename> class Local_connection;
|
|
}
|
|
|
|
|
|
struct Genode::Local_connection_base : Noncopyable
|
|
{
|
|
public:
|
|
|
|
typedef Session_state::Args Args;
|
|
|
|
protected:
|
|
|
|
Constructible<Session_state> _session_state { };
|
|
|
|
private:
|
|
|
|
static Args _init_args(Args const &args, Session::Resources resources,
|
|
Session::Diag diag)
|
|
{
|
|
/* copy original arguments into modifiable buffer */
|
|
char buf[Args::capacity()];
|
|
copy_cstring(buf, args.string(), sizeof(buf));
|
|
|
|
Arg_string::set_arg(buf, sizeof(buf), "ram_quota",
|
|
String<64>(resources.ram_quota.value).string());
|
|
Arg_string::set_arg(buf, sizeof(buf), "cap_quota",
|
|
String<64>(resources.cap_quota.value).string());
|
|
Arg_string::set_arg(buf, sizeof(buf), "diag", diag.enabled);
|
|
|
|
/* return result as a copy */
|
|
return Args(Cstring(buf));
|
|
}
|
|
|
|
protected:
|
|
|
|
Local_connection_base(Service &service,
|
|
Id_space<Parent::Client> &id_space,
|
|
Parent::Client::Id id,
|
|
Args const &args, Affinity const &affinity,
|
|
Session::Label const &label,
|
|
Session::Diag diag,
|
|
Session::Resources resources)
|
|
{
|
|
enum { NUM_ATTEMPTS = 10 };
|
|
for (unsigned i = 0; i < NUM_ATTEMPTS; i++) {
|
|
_session_state.construct(service, id_space, id, label, diag,
|
|
_init_args(args, resources, diag),
|
|
affinity);
|
|
|
|
_session_state->service().initiate_request(*_session_state);
|
|
|
|
if (_session_state->alive())
|
|
break;
|
|
|
|
switch (_session_state->phase) {
|
|
|
|
case Session_state::INSUFFICIENT_RAM_QUOTA:
|
|
resources.ram_quota.value += 4096;
|
|
break;
|
|
|
|
case Session_state::INSUFFICIENT_CAP_QUOTA:
|
|
resources.cap_quota.value += 1;
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
if (_session_state->phase == Session_state::INSUFFICIENT_RAM_QUOTA
|
|
|| _session_state->phase == Session_state::INSUFFICIENT_CAP_QUOTA)
|
|
warning("giving up to increase session quota for ", service.name(), " session "
|
|
"after ", (int)NUM_ATTEMPTS, " attempts");
|
|
}
|
|
|
|
void close()
|
|
{
|
|
if (_session_state->alive()) {
|
|
_session_state->phase = Session_state::CLOSE_REQUESTED;
|
|
_session_state->service().initiate_request(*_session_state);
|
|
}
|
|
}
|
|
|
|
~Local_connection_base() { close(); }
|
|
};
|
|
|
|
|
|
template <typename CONNECTION>
|
|
class Genode::Local_connection : Local_connection_base
|
|
{
|
|
private:
|
|
|
|
typedef typename CONNECTION::Session_type SESSION;
|
|
|
|
Constructible <typename SESSION::Client> _client { };
|
|
|
|
public:
|
|
|
|
Capability<SESSION> cap() const
|
|
{
|
|
return reinterpret_cap_cast<SESSION>(_session_state->cap);
|
|
}
|
|
|
|
SESSION &session()
|
|
{
|
|
/*
|
|
* If session comes from a local service (e.g,. a virtualized
|
|
* RAM session, we return the reference to the corresponding
|
|
* component object, which can be called directly.
|
|
*/
|
|
if (_session_state->local_ptr)
|
|
return *static_cast<SESSION *>(_session_state->local_ptr);
|
|
|
|
/*
|
|
* The session is provided remotely. So return a client stub for
|
|
* interacting with the session. We construct the client object if
|
|
* we have a valid session capability.
|
|
*/
|
|
if (!_client.constructed() && _session_state->cap.valid())
|
|
_client.construct(cap());
|
|
|
|
if (_client.constructed())
|
|
return *_client;
|
|
|
|
/*
|
|
* This error is printed if the session could not be
|
|
* established or the session is provided by a child service.
|
|
*/
|
|
error(SESSION::service_name(), " session (", _session_state->args(), ") "
|
|
"unavailable");
|
|
throw Service_denied();
|
|
}
|
|
|
|
SESSION const &session() const
|
|
{
|
|
return const_cast<Local_connection *>(this)->session();
|
|
}
|
|
|
|
Local_connection(Service &service, Id_space<Parent::Client> &id_space,
|
|
Parent::Client::Id id, Args const &args,
|
|
Affinity const &affinity,
|
|
Session::Label const &label = Session_label(),
|
|
Session::Diag diag = { false })
|
|
:
|
|
Local_connection_base(service, id_space, id, args, affinity,
|
|
label.valid() ? label : label_from_args(args.string()),
|
|
diag,
|
|
Session::Resources { Ram_quota { CONNECTION::RAM_QUOTA },
|
|
Cap_quota { CONNECTION::CAP_QUOTA } })
|
|
{
|
|
service.wakeup();
|
|
}
|
|
|
|
bool alive() const { return _session_state->alive(); }
|
|
bool closed() const { return _session_state->closed(); }
|
|
|
|
using Local_connection_base::close;
|
|
};
|
|
|
|
#endif /* _INCLUDE__BASE__LOCAL_CONNECTION_H_ */
|