diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index 4f8be206a..c23683c5c 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -187,6 +187,11 @@ struct Genode::Child_policy */ virtual Id_space &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, 2*Rom_connection::RAM_QUOTA; } + template + void for_each_session(FN const &fn) const + { + _id_space.for_each(fn); + } + /** * Deduce session costs from usable ram quota */ diff --git a/repos/base/include/base/session_state.h b/repos/base/include/base/session_state.h index b4d55b526..6ef8b6666 100644 --- a/repos/base/include/base/session_state.h +++ b/repos/base/include/base/session_state.h @@ -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; } diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 048ab5ee5..420cd8443 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -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 diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 606f15c95..4dc2052ea 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -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::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(); diff --git a/repos/base/src/lib/base/session_state.cc b/repos/base/src/lib/base/session_state.cc index 52f993732..330335285 100644 --- a/repos/base/src/lib/base/session_state.cc +++ b/repos/base/src/lib/base/session_state.cc @@ -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() { /*