base: add Child_policy::session_state_changed()

This method is a hook to enable a runtime to respond to state changes.
In particular, in init this hook is used to trigger the generation of a
new state report, if configured.

Furthermore, the patch introduces the 'generate_client_side_info' and
'generate_server_side_info' methods to the 'Session_state', which
generates an XML representation of the session states to appear in
reports produced by init.

Issue #2246
This commit is contained in:
Norman Feske 2017-02-17 15:25:52 +01:00 committed by Christian Helmuth
parent a74a0092b3
commit 9d683a56a0
5 changed files with 70 additions and 2 deletions

View File

@ -187,6 +187,11 @@ struct Genode::Child_policy
*/
virtual Id_space<Parent::Server> &server_id_space() { throw Nonexistent_id_space(); }
/**
* Notification hook invoked each time a session state is modified
*/
virtual void session_state_changed() { }
/**
* Return region map for the child's address space
*
@ -562,6 +567,12 @@ class Genode::Child : protected Rpc_object<Parent>,
2*Rom_connection::RAM_QUOTA;
}
template <typename FN>
void for_each_session(FN const &fn) const
{
_id_space.for_each<Session_state const>(fn);
}
/**
* Deduce session costs from usable ram quota
*/

View File

@ -167,7 +167,12 @@ class Genode::Session_state : public Parent::Client, public Parent::Server,
Affinity const &affinity() const { return _affinity; }
void generate_session_request(Xml_generator &xml) const;
void generate_session_request(Xml_generator &) const;
struct Detail { enum Args { NO_ARGS, ARGS } args; };
void generate_client_side_info(Xml_generator &, Detail detail) const;
void generate_server_side_info(Xml_generator &, Detail detail) const;
size_t donated_ram_quota() const { return _donated_ram_quota; }

View File

@ -312,6 +312,8 @@ _ZN6Genode8ipc_callENS_17Native_capabilityERNS_11Msgbuf_baseES2_m T
_ZN6Genode9ipc_replyENS_17Native_capabilityENS_18Rpc_exception_codeERNS_11Msgbuf_baseE T
_ZNK6Genode11Sliced_heap8overheadEm T
_ZNK6Genode13Session_state24generate_session_requestERNS_13Xml_generatorE T
_ZNK6Genode13Session_state25generate_client_side_infoERNS_13Xml_generatorENS0_6DetailE T
_ZNK6Genode13Session_state25generate_server_side_infoERNS_13Xml_generatorENS0_6DetailE T
_ZNK6Genode13Session_state5printERNS_6OutputE T
_ZNK6Genode13Shared_object7_lookupEPKc T
_ZNK6Genode13Shared_object8link_mapEv T

View File

@ -238,6 +238,8 @@ Session_capability Child::session(Parent::Client::Id id,
create_session(_policy.name(), service, route.label, *_session_factory,
_id_space, id, argbuf, filtered_affinity);
_policy.session_state_changed();
session.ready_callback = this;
session.closed_callback = this;
@ -322,6 +324,7 @@ Session_capability Child::session_cap(Client::Id id)
catch (Id_space<Parent::Client>::Unknown_id) {
warning(_policy.name(), " requested session cap for unknown ID"); }
_policy.session_state_changed();
return cap;
}
@ -369,11 +372,13 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const
if (session.phase == Session_state::CAP_HANDED_OUT) {
result = UPGRADE_DONE;
_policy.session_state_changed();
return;
}
session.service().wakeup();
});
_policy.session_state_changed();
return result;
}
@ -396,6 +401,7 @@ void Child::_revert_quota_and_destroy(Session_state &session)
warning(_policy.name(), ": could not revert session quota (", session, ")"); }
session.destroy();
_policy.session_state_changed();
}
@ -427,6 +433,8 @@ Child::Close_result Child::_close(Session_state &session)
return CLOSE_DONE;
}
_policy.session_state_changed();
session.discard_id_at_client();
session.service().wakeup();

View File

@ -18,12 +18,36 @@
using namespace Genode;
struct Formatted_phase
{
Session_state::Phase _phase;
Formatted_phase(Session_state::Phase phase) : _phase(phase) { }
void print(Output &output) const
{
using Genode::print;
typedef Genode::Session_state State;
switch (_phase) {
case State::CREATE_REQUESTED: print(output, "CREATE_REQUESTED"); break;
case State::INVALID_ARGS: print(output, "INVALID_ARGS"); break;
case State::AVAILABLE: print(output, "AVAILABLE"); break;
case State::CAP_HANDED_OUT: print(output, "CAP_HANDED_OUT"); break;
case State::UPGRADE_REQUESTED: print(output, "UPGRADE_REQUESTED"); break;
case State::CLOSE_REQUESTED: print(output, "CLOSE_REQUESTED"); break;
case State::CLOSED: print(output, "CLOSED"); break;
}
}
};
void Session_state::print(Output &out) const
{
using Genode::print;
print(out, "service=", _service.name(), " cid=", _id_at_client, " "
"args='", _args, "' state=", (int)phase, " "
"args='", _args, "' state=", Formatted_phase(phase), " "
"ram_quota=", _donated_ram_quota);
}
@ -70,6 +94,24 @@ void Session_state::generate_session_request(Xml_generator &xml) const
}
void Session_state::generate_client_side_info(Xml_generator &xml, Detail detail) const
{
xml.attribute("service", _service.name());
xml.attribute("label", _label);
xml.attribute("state", String<32>(Formatted_phase(phase)));
xml.attribute("ram", String<32>(Number_of_bytes(_donated_ram_quota)));
if (detail.args == Detail::ARGS)
xml.node("args", [&] () { xml.append_sanitized(_args.string()); });
}
void Session_state::generate_server_side_info(Xml_generator &xml, Detail detail) const
{
generate_client_side_info(xml, detail);
}
void Session_state::destroy()
{
/*