diff --git a/repos/gems/recipes/pkg/sculpt/archives b/repos/gems/recipes/pkg/sculpt/archives
index b0b25774c8..984ed896e4 100644
--- a/repos/gems/recipes/pkg/sculpt/archives
+++ b/repos/gems/recipes/pkg/sculpt/archives
@@ -4,6 +4,8 @@ _/pkg/backdrop
_/src/report_rom
_/src/clipboard
_/src/init
+_/src/monitor
+_/src/terminal_crosslink
_/src/fs_rom
_/src/cached_fs_rom
_/src/fs_report
diff --git a/repos/gems/run/sculpt.run b/repos/gems/run/sculpt.run
index 3acf1267d4..00162758fa 100644
--- a/repos/gems/run/sculpt.run
+++ b/repos/gems/run/sculpt.run
@@ -598,8 +598,16 @@ install_config {
+
+
+
+
+
+
+
+
-
+
@@ -655,6 +663,7 @@ install_config {
+
diff --git a/repos/gems/src/app/depot_deploy/child.h b/repos/gems/src/app/depot_deploy/child.h
index 5cc46f2e29..26bacfd4e3 100644
--- a/repos/gems/src/app/depot_deploy/child.h
+++ b/repos/gems/src/app/depot_deploy/child.h
@@ -353,6 +353,8 @@ class Depot_deploy::Child : public List_model::Element
Depot_rom_server const &cached_depot_rom,
Depot_rom_server const &uncached_depot_rom) const;
+ inline void gen_monitor_policy_node(Xml_generator&) const;
+
template
void with_missing_pkg_path(FN const &fn) const
{
@@ -562,11 +564,49 @@ void Depot_deploy::Child::gen_start_node(Xml_generator &xml,
}
xml.node("route", [&] () {
- _gen_routes(xml, common, cached_depot_rom, uncached_depot_rom); });
+
+ if (start_xml.has_sub_node("monitor")) {
+ xml.node("service", [&] () {
+ xml.attribute("name", "PD");
+ xml.node("local");
+ });
+ xml.node("service", [&] () {
+ xml.attribute("name", "CPU");
+ xml.node("local");
+ });
+ }
+
+ _gen_routes(xml, common, cached_depot_rom, uncached_depot_rom);
+ });
});
}
+void Depot_deploy::Child::gen_monitor_policy_node(Xml_generator &xml) const
+{
+ if (!_configured() || _condition == UNSATISFIED)
+ return;
+
+ if (_defined_by_launcher() && !_launcher_xml.constructed())
+ return;
+
+ if (!_pkg_xml->xml().has_sub_node("runtime")) {
+ return;
+ }
+
+ Xml_node const start_xml = _start_xml->xml();
+
+ if (start_xml.has_sub_node("monitor")) {
+ Xml_node const monitor = start_xml.sub_node("monitor");
+ xml.node("policy", [&] () {
+ xml.attribute("label", _name);
+ xml.attribute("wait", monitor.attribute_value("wait", false));
+ xml.attribute("wx", monitor.attribute_value("wx", false));
+ });
+ }
+}
+
+
void Depot_deploy::Child::_gen_routes(Xml_generator &xml, Xml_node common,
Depot_rom_server const &cached_depot_rom,
Depot_rom_server const &uncached_depot_rom) const
diff --git a/repos/gems/src/app/depot_deploy/children.h b/repos/gems/src/app/depot_deploy/children.h
index b22c582995..6f64593247 100644
--- a/repos/gems/src/app/depot_deploy/children.h
+++ b/repos/gems/src/app/depot_deploy/children.h
@@ -159,6 +159,12 @@ class Depot_deploy::Children
cached_depot_rom, uncached_depot_rom); });
}
+ void gen_monitor_policy_nodes(Xml_generator &xml) const
+ {
+ _children.for_each([&] (Child const &child) {
+ child.gen_monitor_policy_node(xml); });
+ }
+
void gen_queries(Xml_generator &xml) const
{
_children.for_each([&] (Child const &child) {
diff --git a/repos/gems/src/app/sculpt_manager/deploy.cc b/repos/gems/src/app/sculpt_manager/deploy.cc
index d520983cd0..6b3a2836b7 100644
--- a/repos/gems/src/app/sculpt_manager/deploy.cc
+++ b/repos/gems/src/app/sculpt_manager/deploy.cc
@@ -194,8 +194,11 @@ void Sculpt::Deploy::gen_runtime_start_nodes(Xml_generator &xml,
}
/* generate start nodes for deployed packages */
- if (managed_deploy.has_sub_node("common_routes"))
+ if (managed_deploy.has_sub_node("common_routes")) {
_children.gen_start_nodes(xml, managed_deploy.sub_node("common_routes"),
prio_levels, affinity_space,
"depot_rom", "dynamic_depot_rom");
+ xml.node("monitor", [&] () {
+ _children.gen_monitor_policy_nodes(xml);});
+ }
}
diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc
index a0ad5c1336..90c299b49d 100644
--- a/repos/gems/src/app/sculpt_manager/main.cc
+++ b/repos/gems/src/app/sculpt_manager/main.cc
@@ -2086,6 +2086,7 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const
gen_parent_service(xml);
gen_parent_service(xml);
gen_parent_service(xml);
+ gen_parent_service(xml);
});
xml.node("affinity-space", [&] () {
diff --git a/repos/gems/src/app/sculpt_manager/model/component.h b/repos/gems/src/app/sculpt_manager/model/component.h
index 53e7b1bcb8..401d171553 100644
--- a/repos/gems/src/app/sculpt_manager/model/component.h
+++ b/repos/gems/src/app/sculpt_manager/model/component.h
@@ -48,6 +48,10 @@ struct Sculpt::Component : Noncopyable
affinity_space.height() };
Priority priority = Priority::DEFAULT;
+ bool monitor { false };
+ bool wait { false };
+ bool wx { false };
+
struct Blueprint_info
{
bool known;
@@ -188,6 +192,15 @@ struct Sculpt::Component : Noncopyable
});
}
+ void gen_monitor(Xml_generator &xml) const
+ {
+ if (monitor)
+ xml.node("monitor", [&] () {
+ xml.attribute("wait", wait ? "yes" : "no");
+ xml.attribute("wx", wx ? "yes" : "no");
+ });
+ }
+
void gen_pd_cpu_route(Xml_generator &xml) const
{
/* by default pd route goes to parent if nothing is specified */
diff --git a/repos/gems/src/app/sculpt_manager/model/runtime_config.h b/repos/gems/src/app/sculpt_manager/model/runtime_config.h
index f1d517927e..29e5998b1a 100644
--- a/repos/gems/src/app/sculpt_manager/model/runtime_config.h
+++ b/repos/gems/src/app/sculpt_manager/model/runtime_config.h
@@ -320,7 +320,8 @@ class Sculpt::Runtime_config
_pin_ctrl { _r, Type::PIN_CONTROL, "GPIO pin control" },
_trace { _r, Type::TRACE, "system-global tracing" },
_vm { _r, Type::VM, "virtualization hardware" },
- _pd { _r, Type::PD, "system PD service" };
+ _pd { _r, Type::PD, "system PD service" },
+ _monitor { _r, Type::TERMINAL, "debug monitor" };
template
void for_each(FN const &fn) const { _r.for_each(fn); }
diff --git a/repos/gems/src/app/sculpt_manager/model/runtime_state.h b/repos/gems/src/app/sculpt_manager/model/runtime_state.h
index 7392d69e54..c10254bf2f 100644
--- a/repos/gems/src/app/sculpt_manager/model/runtime_state.h
+++ b/repos/gems/src/app/sculpt_manager/model/runtime_state.h
@@ -185,6 +185,8 @@ class Sculpt::Runtime_state : public Runtime_info
construction->gen_priority(xml);
construction->gen_affinity(xml);
+ construction->gen_monitor(xml);
+
xml.node("route", [&] () {
construction->gen_pd_cpu_route(xml);
diff --git a/repos/gems/src/app/sculpt_manager/view/debug_dialog.h b/repos/gems/src/app/sculpt_manager/view/debug_dialog.h
new file mode 100644
index 0000000000..7b7c7dce69
--- /dev/null
+++ b/repos/gems/src/app/sculpt_manager/view/debug_dialog.h
@@ -0,0 +1,109 @@
+/*
+ * \brief Debug options dialog
+ * \author Christian Prochaska
+ * \date 2022-09-06
+ */
+
+/*
+ * Copyright (C) 2023 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 _VIEW__DEBUG_DIALOG_H_
+#define _VIEW__DEBUG_DIALOG_H_
+
+/* local includes */
+#include
+#include
+#include
+
+namespace Sculpt { struct Debug_dialog; }
+
+
+struct Sculpt::Debug_dialog : Noncopyable, Deprecated_dialog
+{
+ bool _monitor;
+ bool _wait;
+ bool _wx;
+
+ Hoverable_item _item { };
+
+ Debug_dialog(bool monitor, bool wait, bool wx)
+ : _monitor(monitor), _wait(wait), _wx(wx) { }
+
+ Hover_result hover(Xml_node hover) override
+ {
+ return Deprecated_dialog::any_hover_changed(
+ _item.match(hover, "vbox", "hbox", "name"));
+ }
+
+ void click(Component &component)
+ {
+ Hoverable_item::Id const clicked = _item._hovered;
+
+ if (!clicked.valid())
+ return;
+
+ if (clicked == "monitor")
+ _monitor = component.monitor = !component.monitor;
+ else if (clicked == "wait") {
+ _wait = component.wait = !component.wait;
+ /* wait depends on wx */
+ if (_wait)
+ _wx = component.wx = true;
+ } else if (clicked == "wx") {
+ _wx = component.wx = !component.wx;
+ /* wait depends on wx */
+ if (!_wx)
+ _wait = component.wait = false;
+ }
+ }
+
+ void _gen_menu_entry(Xml_generator &xml, Start_name const &name,
+ Component::Info const &text, bool selected,
+ char const *style = "radio") const
+ {
+ gen_named_node(xml, "hbox", name, [&] () {
+
+ gen_named_node(xml, "float", "left", [&] () {
+ xml.attribute("west", "yes");
+
+ xml.node("hbox", [&] () {
+ gen_named_node(xml, "button", "button", [&] () {
+
+ if (selected)
+ xml.attribute("selected", "yes");
+
+ xml.attribute("style", style);
+ _item.gen_hovered_attr(xml, name);
+ xml.node("hbox", [&] () { });
+ });
+ gen_named_node(xml, "label", "name", [&] () {
+ xml.attribute("text", Path(" ", text)); });
+ });
+ });
+
+ gen_named_node(xml, "hbox", "right", [&] () { });
+ });
+ }
+
+ void generate(Xml_generator &xml) const override
+ {
+ xml.node("vbox", [&] () {
+ _gen_menu_entry(xml, "monitor", "monitor this component", _monitor, "checkbox");
+ if (_monitor) {
+ _gen_menu_entry(xml, "wait", " wait for GDB", _wait, "checkbox");
+ _gen_menu_entry(xml, "wx", " map executable segments writeable", _wx, "checkbox");
+ }
+ });
+ }
+
+ void reset() override
+ {
+ _item._hovered = Hoverable_item::Id();
+ }
+};
+
+#endif /* _VIEW__DEBUG_DIALOG_H_ */
diff --git a/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc b/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc
index 3345546dbe..06dca022ca 100644
--- a/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc
+++ b/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc
@@ -88,8 +88,7 @@ void Popup_dialog::_gen_pkg_elements(Xml_generator &xml,
_pd_route.generate(xml);
if (_resources.constructed()) {
-
- xml.node("frame", [&] {
+ gen_named_node(xml, "frame", "resources", [&] {
xml.node("vbox", [&] () {
bool const selected = _route_selected("resources");
@@ -108,6 +107,26 @@ void Popup_dialog::_gen_pkg_elements(Xml_generator &xml,
});
}
+ if (_debug.constructed()) {
+ gen_named_node(xml, "frame", "debug", [&] {
+ xml.node("vbox", [&] () {
+
+ bool const selected = _route_selected("debug");
+
+ if (!selected)
+ _gen_route_entry(xml, "debug",
+ "Debug options ...", false, "enter");
+
+ if (selected) {
+ _gen_route_entry(xml, "back", "Debug options ...",
+ true, "back");
+
+ _debug->generate(xml);
+ }
+ });
+ });
+ }
+
/*
* Display "Add component" button once all routes are defined
*/
@@ -476,6 +495,22 @@ void Popup_dialog::click(Action &action)
_resources->click(component); });
}
+ } else if (_debug_dialog_selected()) {
+
+ bool const clicked_on_different_route = clicked_route.valid()
+ && (clicked_route != "");
+ if (clicked_on_different_route) {
+
+ /* close debug options dialog */
+ _selected_route.construct(clicked_route);
+
+ } else {
+
+ if (_debug.constructed())
+ action.apply_to_construction([&] (Component &component) {
+ _debug->click(component); });
+ }
+
} else {
bool clicked_on_selected_route = false;
diff --git a/repos/gems/src/app/sculpt_manager/view/popup_dialog.h b/repos/gems/src/app/sculpt_manager/view/popup_dialog.h
index c303fe3fab..42ffe7387e 100644
--- a/repos/gems/src/app/sculpt_manager/view/popup_dialog.h
+++ b/repos/gems/src/app/sculpt_manager/view/popup_dialog.h
@@ -33,6 +33,7 @@
#include
#include
+#include
namespace Sculpt { struct Popup_dialog; }
@@ -123,6 +124,7 @@ struct Sculpt::Popup_dialog : Deprecated_dialog
Pd_route_dialog _pd_route { _runtime_config };
Constructible _resources { };
+ Constructible _debug { };
enum State { TOP_LEVEL, DEPOT_REQUESTED, DEPOT_SHOWN, DEPOT_SELECTION,
INDEX_REQUESTED, INDEX_SHOWN,
@@ -149,6 +151,11 @@ struct Sculpt::Popup_dialog : Deprecated_dialog
return _route_selected("resources");
}
+ bool _debug_dialog_selected() const
+ {
+ return _route_selected("debug");
+ }
+
template
void _apply_to_selected_route(Action &action, FN const &fn)
{
@@ -163,7 +170,7 @@ struct Sculpt::Popup_dialog : Deprecated_dialog
Hover_result hover(Xml_node hover) override
{
- Deprecated_dialog::Hover_result const hover_result = Deprecated_dialog::any_hover_changed(
+ Deprecated_dialog::Hover_result hover_result = Deprecated_dialog::any_hover_changed(
_item .match(hover, "frame", "vbox", "hbox", "name"),
_action_item .match(hover, "frame", "vbox", "button", "name"),
_install_item.match(hover, "frame", "vbox", "float", "vbox", "float", "button", "name"),
@@ -173,7 +180,11 @@ struct Sculpt::Popup_dialog : Deprecated_dialog
if (_resources.constructed() &&
hover_result == Deprecated_dialog::Hover_result::UNMODIFIED)
- return _resources->match_sub_dialog(hover, "frame", "vbox", "frame", "vbox");
+ hover_result = _resources->match_sub_dialog(hover, "frame", "vbox", "frame", "vbox");
+
+ if (_debug.constructed() &&
+ hover_result == Deprecated_dialog::Hover_result::UNMODIFIED)
+ hover_result = _debug->match_sub_dialog(hover, "frame", "vbox", "frame", "vbox");
return hover_result;
}
@@ -361,6 +372,7 @@ struct Sculpt::Popup_dialog : Deprecated_dialog
_selected_route.destruct();
_menu._level = 0;
_resources.destruct();
+ _debug.destruct();
_pd_route.reset();
}
@@ -415,6 +427,10 @@ struct Sculpt::Popup_dialog : Deprecated_dialog
construction.affinity_location,
construction.priority);
+ _debug.construct(construction.monitor,
+ construction.wait,
+ construction.wx);
+
construction.try_apply_blueprint(blueprint);
_blueprint_info = construction.blueprint_info;