diff --git a/repos/gems/recipes/pkg/window_layouter/runtime b/repos/gems/recipes/pkg/window_layouter/runtime index c4034a9062..15ffb76358 100644 --- a/repos/gems/recipes/pkg/window_layouter/runtime +++ b/repos/gems/recipes/pkg/window_layouter/runtime @@ -1,4 +1,4 @@ - + @@ -49,7 +49,7 @@ - + diff --git a/repos/gems/recipes/pkg/wm/runtime b/repos/gems/recipes/pkg/wm/runtime index d37fdf039f..4545d796c0 100644 --- a/repos/gems/recipes/pkg/wm/runtime +++ b/repos/gems/recipes/pkg/wm/runtime @@ -1,4 +1,4 @@ - + diff --git a/repos/gems/recipes/raw/motif_wm/wm.config b/repos/gems/recipes/raw/motif_wm/wm.config index 7a31d0009c..006af7a5ef 100644 --- a/repos/gems/recipes/raw/motif_wm/wm.config +++ b/repos/gems/recipes/raw/motif_wm/wm.config @@ -46,8 +46,8 @@ - - + + @@ -70,7 +70,7 @@ - + diff --git a/repos/gems/recipes/raw/wm/wm.config b/repos/gems/recipes/raw/wm/wm.config index a967d99475..56235b11c2 100644 --- a/repos/gems/recipes/raw/wm/wm.config +++ b/repos/gems/recipes/raw/wm/wm.config @@ -74,8 +74,8 @@ - - + + diff --git a/repos/gems/run/wm.run b/repos/gems/run/wm.run index 9db7234587..3cf51763a3 100644 --- a/repos/gems/run/wm.run +++ b/repos/gems/run/wm.run @@ -108,7 +108,7 @@ install_config { - + @@ -127,7 +127,7 @@ install_config { - + diff --git a/repos/gems/sculpt/leitzentrale/default b/repos/gems/sculpt/leitzentrale/default index 323b127b96..13c7801756 100644 --- a/repos/gems/sculpt/leitzentrale/default +++ b/repos/gems/sculpt/leitzentrale/default @@ -142,8 +142,8 @@ - - + + @@ -160,7 +160,7 @@ - + @@ -264,7 +264,7 @@ - + diff --git a/repos/gems/src/server/wm/decorator_gui.h b/repos/gems/src/server/wm/decorator_gui.h index 6941181810..7020efd52e 100644 --- a/repos/gems/src/server/wm/decorator_gui.h +++ b/repos/gems/src/server/wm/decorator_gui.h @@ -21,12 +21,12 @@ #include /* local includes */ +#include #include #include #include namespace Wm { class Main; - using Genode::size_t; using Genode::Allocator; using Genode::Arg_string; using Genode::Object_pool; @@ -59,7 +59,8 @@ struct Wm::Decorator_content_callback : Interface struct Wm::Decorator_gui_session : Genode::Session_object, - private List::Element + private List::Element, + private Upgradeable { friend class List; using List::Element::next; @@ -82,13 +83,15 @@ struct Wm::Decorator_gui_session : Genode::Session_object, Genode::Env &_env; - Genode::Heap _heap { _env.ram(), _env.rm() }; + Genode::Constrained_ram_allocator _ram { _env.ram(), _ram_quota_guard(), _cap_quota_guard() }; - Genode::Ram_allocator &_ram; + Genode::Sliced_heap _session_alloc { _ram, _env.rm() }; - Real_gui _gui { _env, "decorator" }; + Slab _content_view_ref_alloc { _session_alloc }; - Input::Session_client _input_session { _env.rm(), _gui.session.input() }; + Real_gui _real_gui { _env, "decorator" }; + + Input::Session_client _input_session { _env.rm(), _real_gui.session.input() }; Genode::Signal_context_capability _mode_sigh { }; @@ -102,8 +105,6 @@ struct Wm::Decorator_gui_session : Genode::Session_object, Decorator_content_callback &_content_callback; - Allocator &_md_alloc; - /* Gui::Connection requires a valid input session */ Input::Session_component _dummy_input_component { _env, _env.ram() }; Input::Session_capability _dummy_input_component_cap = @@ -120,22 +121,18 @@ struct Wm::Decorator_gui_session : Genode::Session_object, } Decorator_gui_session(Genode::Env &env, - Genode::Ram_allocator &ram, Resources const &resources, Label const &label, Diag const &diag, - Allocator &md_alloc, Pointer::Tracker &pointer_tracker, Input::Session_component &window_layouter_input, Decorator_content_callback &content_callback) : Session_object(env.ep(), resources, label, diag), _env(env), - _ram(ram), _pointer_state(pointer_tracker), _window_layouter_input(window_layouter_input), - _content_callback(content_callback), - _md_alloc(md_alloc) + _content_callback(content_callback) { _input_session.sigh(_input_handler); } @@ -145,6 +142,11 @@ struct Wm::Decorator_gui_session : Genode::Session_object, _env.ep().dissolve(_dummy_input_component); } + void upgrade_local_or_remote(Resources const &resources) + { + _upgrade_local_or_remote(resources, *this, _real_gui); + } + void _handle_input() { while (_input_session.pending()) @@ -170,7 +172,7 @@ struct Wm::Decorator_gui_session : Genode::Session_object, [&] { }); /* forward command */ - _gui.enqueue(cmd); + _real_gui.enqueue(cmd); return; case Command::OFFSET: @@ -181,7 +183,7 @@ struct Wm::Decorator_gui_session : Genode::Session_object, */ _content_view_ids.apply(cmd.geometry.view, [&] (Content_view_ref const &) { }, - [&] { _gui.enqueue(cmd); }); + [&] { _real_gui.enqueue(cmd); }); return; case Command::FRONT: @@ -194,23 +196,18 @@ struct Wm::Decorator_gui_session : Genode::Session_object, _content_callback.update_content_child_views(view_ref.win_id); }, [&] { }); - _gui.enqueue(cmd); + _real_gui.enqueue(cmd); return; case Command::TITLE: case Command::BACKGROUND: case Command::NOP: - _gui.enqueue(cmd); + _real_gui.enqueue(cmd); return; } } - void upgrade(const char *args) - { - _gui.connection.upgrade(Genode::session_resources_from_args(args)); - } - Pointer::Position last_observed_pointer_pos() const { return _pointer_state.last_observed_pos(); @@ -223,7 +220,7 @@ struct Wm::Decorator_gui_session : Genode::Session_object, Framebuffer::Session_capability framebuffer() override { - return _gui.session.framebuffer(); + return _real_gui.session.framebuffer(); } Input::Session_capability input() override @@ -245,13 +242,13 @@ struct Wm::Decorator_gui_session : Genode::Session_object, Window_registry::Id const win_id = _win_id_from_title(attr.title); if (win_id.valid()) { try { - Content_view_ref &view_ref_ptr = *new (_heap) + Content_view_ref &view_ref_ptr = *new (_content_view_ref_alloc) Content_view_ref(Window_registry::Id(win_id), _content_view_ids, id); View_capability view_cap = _content_callback.content_view(win_id); - Associate_result result = _gui.session.associate(id, view_cap); + Associate_result result = _real_gui.session.associate(id, view_cap); if (result != Associate_result::OK) - destroy(_heap, &view_ref_ptr); + destroy(_content_view_ref_alloc, &view_ref_ptr); switch (result) { case Associate_result::OUT_OF_RAM: return View_result::OUT_OF_RAM; @@ -260,15 +257,21 @@ struct Wm::Decorator_gui_session : Genode::Session_object, case Associate_result::INVALID: break; /* fall back to regular view */ }; } - catch (Genode::Out_of_ram) { return View_result::OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return View_result::OUT_OF_CAPS; } + catch (Genode::Out_of_ram) { + _starved_for_ram = true; + return View_result::OUT_OF_RAM; + } + catch (Genode::Out_of_caps) { + _starved_for_caps = true; + return View_result::OUT_OF_CAPS; + } } - return _gui.session.view(id, attr); + return _real_gui.session.view(id, attr); } Child_view_result child_view(View_id id, View_id parent, View_attr const &attr) override { - return _gui.session.child_view(id, parent, attr); + return _real_gui.session.child_view(id, parent, attr); } void destroy_view(View_id view) override @@ -282,33 +285,33 @@ struct Wm::Decorator_gui_session : Genode::Session_object, _content_callback.hide_content_child_views(view_ref.win_id); Gui::Rect rect(Gui::Point(0, 0), Gui::Area(0, 0)); - _gui.enqueue(view, rect); - _gui.execute(); + _real_gui.enqueue(view, rect); + _real_gui.execute(); - destroy(_heap, &view_ref); + destroy(_content_view_ref_alloc, &view_ref); }, [&] { }); - _gui.session.destroy_view(view); + _real_gui.session.destroy_view(view); } Associate_result associate(View_id id, View_capability view_cap) override { - return _gui.session.associate(id, view_cap); + return _real_gui.session.associate(id, view_cap); } View_capability_result view_capability(View_id view) override { - return _gui.session.view_capability(view); + return _real_gui.session.view_capability(view); } void release_view_id(View_id view) override { _content_view_ids.apply(view, - [&] (Content_view_ref &view_ref) { destroy(_heap, &view_ref); }, + [&] (Content_view_ref &view_ref) { destroy(_content_view_ref_alloc, &view_ref); }, [&] { }); - _gui.session.release_view_id(view); + _real_gui.session.release_view_id(view); } Genode::Dataspace_capability command_dataspace() override @@ -321,12 +324,12 @@ struct Wm::Decorator_gui_session : Genode::Session_object, for (unsigned i = 0; i < _client_command_buffer.num(); i++) _execute_command(_client_command_buffer.get(i)); - _gui.execute(); + _real_gui.execute(); } Framebuffer::Mode mode() override { - return _gui.session.mode(); + return _real_gui.session.mode(); } void mode_sigh(Genode::Signal_context_capability sigh) override @@ -336,12 +339,12 @@ struct Wm::Decorator_gui_session : Genode::Session_object, * transitive delegations of the capability. */ _mode_sigh = sigh; - _gui.session.mode_sigh(sigh); + _real_gui.session.mode_sigh(sigh); } Buffer_result buffer(Framebuffer::Mode mode, bool use_alpha) override { - return _gui.session.buffer(mode, use_alpha); + return _real_gui.session.buffer(mode, use_alpha); } void focus(Genode::Capability) override { } diff --git a/repos/gems/src/server/wm/gui.h b/repos/gems/src/server/wm/gui.h index a6055e05d3..290ce34e09 100644 --- a/repos/gems/src/server/wm/gui.h +++ b/repos/gems/src/server/wm/gui.h @@ -246,6 +246,10 @@ class Wm::Gui::View : private Genode::Weak_object, class Wm::Gui::Top_level_view : public View, private List::Element { + public: + + using View_result = Gui::Session::View_result; + private: friend class List; @@ -268,6 +272,15 @@ class Wm::Gui::Top_level_view : public View, private List::Eleme Session_label const _session_label; + View_result _init_real_view() + { + return _real_gui.session.view(_real_view.id(), { .title = _title, + .rect = { }, + .front = false }); + } + + View_result const _real_view_result = _init_real_view(); + using Command = Gui::Session::Command; public: @@ -281,14 +294,7 @@ class Wm::Gui::Top_level_view : public View, private List::Eleme _window_registry(window_registry), _input_origin_changed_handler(input_origin_changed_handler), _session_label(real_gui.label) - { - /* - * Create and configure physical GUI view. - */ - _real_gui.session.view(_real_view.id(), { .title = _title, - .rect = { }, - .front = false }); - } + { } ~Top_level_view() { @@ -298,6 +304,8 @@ class Wm::Gui::Top_level_view : public View, private List::Eleme View::lock_for_destruction(); } + View_result real_view_result() const { return _real_view_result; } + using List::Element::next; void _propagate_view_geometry() override { } @@ -372,6 +380,10 @@ class Wm::Gui::Top_level_view : public View, private List::Eleme class Wm::Gui::Child_view : public View, private List::Element { + public: + + using View_result = Gui::Session::Child_view_result; + private: friend class List; @@ -380,6 +392,8 @@ class Wm::Gui::Child_view : public View, private List::Element bool _visible = false; + View_result _real_view_result = try_to_init_real_view(); + public: Child_view(Real_gui &real_gui, @@ -387,15 +401,15 @@ class Wm::Gui::Child_view : public View, private List::Element Weak_ptr parent) : View(real_gui, real_gui.label, has_alpha), _parent(parent) - { - try_to_init_real_view(); - } + { } ~Child_view() { View::lock_for_destruction(); } + View_result real_view_result() const { return _real_view_result; } + using List::Element::next; void _propagate_view_geometry() override @@ -426,11 +440,15 @@ class Wm::Gui::Child_view : public View, private List::Element return Point(); } - void try_to_init_real_view() + View_result try_to_init_real_view() { + using Child_view_result = Gui::Session::Child_view_result; + + Child_view_result result = Child_view_result::INVALID; + Locked_ptr parent(_parent); if (!parent.valid()) - return; + return result; _with_temporary_view_id(parent->real_view_cap(), [&] (View_id parent_id) { @@ -441,15 +459,13 @@ class Wm::Gui::Child_view : public View, private List::Element .rect = _geometry, .front = false }; - switch (_real_gui.session.child_view(_real_view.id(), parent_id, attr)) { - case Gui::Session::Child_view_result::OUT_OF_RAM: - case Gui::Session::Child_view_result::OUT_OF_CAPS: - case Gui::Session::Child_view_result::INVALID: + result = _real_gui.session.child_view(_real_view.id(), parent_id, attr); + + if (result != Child_view_result::OK) { warning("unable to create child view"); return; - case Gui::Session::Child_view_result::OK: - break; - }; + } + _visible = true; }); @@ -457,6 +473,8 @@ class Wm::Gui::Child_view : public View, private List::Element _unsynchronized_apply_view_config(parent); else _apply_view_config(); + + return result; } void update_child_stacking() @@ -474,7 +492,8 @@ class Wm::Gui::Child_view : public View, private List::Element class Wm::Gui::Session_component : public Session_object, private List::Element, - private Input_origin_changed_handler + private Input_origin_changed_handler, + private Upgradeable { private: @@ -513,17 +532,33 @@ class Wm::Gui::Session_component : public Session_object, Genode::Env &_env; - Genode::Ram_allocator &_ram; + Genode::Constrained_ram_allocator _ram { + _env.ram(), _ram_quota_guard(), _cap_quota_guard() }; + + Genode::Sliced_heap _session_alloc { _ram, _env.rm() }; Real_gui _real_gui { _env, _label }; Window_registry &_window_registry; - Tslab _top_level_view_alloc; - Tslab _child_view_alloc; - Tslab _view_ref_alloc; + Slab _top_level_view_alloc { _session_alloc }; + Slab _child_view_alloc { _session_alloc }; + Slab _view_ref_alloc { _session_alloc }; List _top_level_views { }; List _child_views { }; View_ids _view_ids { }; - Input::Session_component _input_session { _env, _ram }; - Input::Session_capability _input_session_cap; + + struct Input_session : Input::Session_component + { + Entrypoint &_ep; + + Input_session(Env &env, Ram_allocator &ram) + : Input::Session_component(env, ram), _ep(env.ep()) + { + _ep.manage(*this); + } + + ~Input_session() { _ep.dissolve(*this); } + }; + + Input_session _input_session { _env, _ram }; Click_handler &_click_handler; Signal_context_capability _mode_sigh { }; Area _requested_size { }; @@ -701,17 +736,25 @@ class Wm::Gui::Session_component : public Session_object, _input_session.submit(Input::Absolute_motion { pos.x, pos.y }); } + void _dissolve_view_from_ep(View &view) + { + if (view.cap().valid()) { + _env.ep().dissolve(view); + replenish(Cap_quota { 1 }); + } + } + void _destroy_top_level_view(Top_level_view &view) { _top_level_views.remove(&view); - _env.ep().dissolve(view); + _dissolve_view_from_ep(view); Genode::destroy(&_top_level_view_alloc, &view); } void _destroy_child_view(Child_view &view) { _child_views.remove(&view); - _env.ep().dissolve(view); + _dissolve_view_from_ep(view); Genode::destroy(&_child_view_alloc, &view); } @@ -782,24 +825,17 @@ class Wm::Gui::Session_component : public Session_object, public: - Session_component(Genode::Env &env, - Genode::Ram_allocator &ram, - Resources const &resources, - Label const &label, - Diag const diag, - Window_registry &window_registry, - Allocator &session_alloc, - Pointer::Tracker &pointer_tracker, - Click_handler &click_handler) + Session_component(Genode::Env &env, + Resources const &resources, + Label const &label, + Diag const diag, + Window_registry &window_registry, + Pointer::Tracker &pointer_tracker, + Click_handler &click_handler) : Session_object(env.ep(), resources, label, diag), _env(env), - _ram(ram), _window_registry(window_registry), - _top_level_view_alloc(&session_alloc), - _child_view_alloc(&session_alloc), - _view_ref_alloc(&session_alloc), - _input_session_cap(env.ep().manage(_input_session)), _click_handler(click_handler), _pointer_state(pointer_tracker) { @@ -818,15 +854,13 @@ class Wm::Gui::Session_component : public Session_object, while (Child_view *view = _child_views.first()) _destroy_child_view(*view); - - _env.ep().dissolve(_input_session); } using List::Element::next; - void upgrade(char const *args) + void upgrade_local_or_remote(Resources const &resources) { - _real_gui.connection.upgrade(Genode::session_resources_from_args(args)); + _upgrade_local_or_remote(resources, *this, _real_gui); } void try_to_init_real_child_views() @@ -930,39 +964,64 @@ class Wm::Gui::Session_component : public Session_object, Input::Session_capability input() override { - return _input_session_cap; + return _input_session.cap(); } template - View_result _create_view_with_id(auto &dealloc, View_id id, View_attr const &attr, auto const &create_fn) + VIEW::View_result _create_view_with_id(auto &dealloc, View_id id, View_attr const &attr, auto const &create_fn) { + using Result = VIEW::View_result; + + /* precondition for obtaining 'real_view_cap' */ + if (!try_withdraw(Cap_quota { 1 })) { + _starved_for_caps = true; + return Result::OUT_OF_CAPS; + } + release_view_id(id); - View_result error { }; + Result error { }; VIEW *view_ptr = nullptr; try { view_ptr = &create_fn(); } - catch (Out_of_ram) { error = View_result::OUT_OF_RAM; } - catch (Out_of_caps) { error = View_result::OUT_OF_CAPS; } + catch (Out_of_ram) { + _starved_for_ram = true; + error = Result::OUT_OF_RAM; + } + catch (Out_of_caps) { + _starved_for_caps = true; + error = Result::OUT_OF_CAPS; + } if (!view_ptr) return error; + /* _real_gui view creation may return OUT_OF_RAM or OUT_OF_CAPS */ + if (view_ptr->real_view_result() != Result::OK) { + error = view_ptr->real_view_result(); + destroy(dealloc, view_ptr); + return error; + } + View_ref *view_ref_ptr = nullptr; try { view_ref_ptr = new (_view_ref_alloc) View_ref(view_ptr->weak_ptr(), _view_ids, id); } - catch (Out_of_ram) { error = View_result::OUT_OF_RAM; } - catch (Out_of_caps) { error = View_result::OUT_OF_CAPS; } + catch (Out_of_ram) { + _starved_for_ram = true; + error = Result::OUT_OF_RAM; + } + catch (Out_of_caps) { + _starved_for_caps = true; + error = Result::OUT_OF_CAPS; + } if (!view_ref_ptr) { destroy(dealloc, view_ptr); return error; } - _env.ep().manage(*view_ptr); - /* apply initial view attributes */ _execute_command(Command::Title { id, attr.title }); _execute_command(Command::Geometry { id, attr.rect }); @@ -971,7 +1030,7 @@ class Wm::Gui::Session_component : public Session_object, _window_registry.flush(); } - return View_result::OK; + return Result::OK; } View_result view(View_id id, View_attr const &attr) override @@ -1001,7 +1060,7 @@ class Wm::Gui::Session_component : public Session_object, Child_view *view_ptr = nullptr; - View_result const result = + Child_view_result const result = _create_view_with_id(_child_view_alloc, id, attr, [&] () -> Child_view & { view_ptr = new (_child_view_alloc) @@ -1009,16 +1068,10 @@ class Wm::Gui::Session_component : public Session_object, return *view_ptr; }); - switch (result) { - case View_result::OUT_OF_RAM: return Child_view_result::OUT_OF_RAM; - case View_result::OUT_OF_CAPS: return Child_view_result::OUT_OF_CAPS; - case View_result::OK: break; - } - - if (view_ptr) + if (result == Child_view_result::OK && view_ptr) _child_views.insert(view_ptr); - return Child_view_result::OK; + return result; }, [&] () -> Child_view_result { return Child_view_result::INVALID; }); } @@ -1030,11 +1083,13 @@ class Wm::Gui::Session_component : public Session_object, for (Child_view *v = _child_views.first(); v; v = v->next()) if (&view == v) { _destroy_child_view(*v); + replenish(Cap_quota { 1 }); return; } for (Top_level_view *v = _top_level_views.first(); v; v = v->next()) if (&view == v) { _destroy_top_level_view(*v); + replenish(Cap_quota { 1 }); return; } }, @@ -1056,16 +1111,32 @@ class Wm::Gui::Session_component : public Session_object, new (_view_ref_alloc) View_ref(view_ptr->weak_ptr(), _view_ids, id); return Associate_result::OK; } - catch (Out_of_ram) { return Associate_result::OUT_OF_RAM; } - catch (Out_of_caps) { return Associate_result::OUT_OF_CAPS; } + catch (Out_of_ram) { + _starved_for_ram = true; + return Associate_result::OUT_OF_RAM; + } + catch (Out_of_caps) { + _starved_for_caps = true; + return Associate_result::OUT_OF_CAPS; + } }); } View_capability_result view_capability(View_id id) override { return _with_view(id, - [&] (View &view) { return view.cap(); }, - [&] /* view does not exist */ { return View_capability(); }); + [&] (View &view) -> View_capability_result + { + if (!view.cap().valid()) { + if (!try_withdraw(Cap_quota { 1 })) { + _starved_for_caps = true; + return View_capability_error::OUT_OF_CAPS; + } + _env.ep().manage(view); + } + return view.cap(); + }, + [&] () -> View_capability_result { return View_capability(); }); } void release_view_id(View_id id) override @@ -1166,9 +1237,7 @@ class Wm::Gui::Root : public Genode::Rpc_object Genode::Attached_rom_dataspace _config { _env, "config" }; - Allocator &_md_alloc; - - Genode::Ram_allocator &_ram; + Sliced_heap _sliced_heap { _env.ram(), _env.rm() }; enum { STACK_SIZE = 1024*sizeof(long) }; @@ -1224,14 +1293,11 @@ class Wm::Gui::Root : public Genode::Rpc_object /** * Constructor */ - Root(Genode::Env &env, - Window_registry &window_registry, Allocator &md_alloc, - Genode::Ram_allocator &ram, + Root(Genode::Env &env, Window_registry &window_registry, Pointer::Tracker &pointer_tracker, Reporter &focus_request_reporter, Gui::Connection &focus_gui_session) : _env(env), - _md_alloc(md_alloc), _ram(ram), _pointer_tracker(pointer_tracker), _focus_request_reporter(focus_request_reporter), _window_registry(window_registry), @@ -1265,12 +1331,14 @@ class Wm::Gui::Root : public Genode::Rpc_object ** Root interface ** ********************/ + static_assert(Gui::Session::CAP_QUOTA == 9); + Genode::Session_capability session(Session_args const &args, Affinity const &) override { - Genode::Session::Label const label = Genode::label_from_args(args.string()); - Genode::Session::Resources const resources = Genode::session_resources_from_args(args.string()); - Genode::Session::Diag const diag = Genode::session_diag_from_args(args.string()); + Genode::Session::Label label = Genode::label_from_args(args.string()); + Genode::Session::Resources resources = Genode::session_resources_from_args(args.string()); + Genode::Session::Diag diag = Genode::session_diag_from_args(args.string()); enum Role { ROLE_DECORATOR, ROLE_LAYOUTER, ROLE_REGULAR, ROLE_DIRECT }; Role role = ROLE_REGULAR; @@ -1290,34 +1358,65 @@ class Wm::Gui::Root : public Genode::Rpc_object } catch (...) { } + if (role == ROLE_REGULAR || role == ROLE_DECORATOR) { + + size_t const needed_ram = Real_gui::RAM_QUOTA + + sizeof(Session_component) + + _sliced_heap.overhead(sizeof(Session_component)) + + 8*1024; + + if (resources.ram_quota.value < needed_ram) + throw Insufficient_ram_quota(); + resources.ram_quota.value -= needed_ram; + + static constexpr unsigned needed_caps = + 1 + /* Sliced_heap alloc of Session_component */ + 1 + /* Session_component RPC cap */ + 9 + /* Wrapped nitpicker GUI session (_real_gui) */ + 1 + /* Input_session RPC cap (_input_session) */ + 1 + /* Input_session events dataspace (_input_session) */ + 1 + /* Command buffer (_command_buffer) */ + 1 + /* Input signal handler (_input_handler) */ + 1 + /* Mode signal handler (_mode_handler) */ + 1; /* Content-view capability */ + + if (resources.cap_quota.value < needed_caps) + throw Insufficient_cap_quota(); + /* preserve caps for content_view and command buffer ds */ + resources.cap_quota.value -= needed_caps - 2; + } + switch (role) { case ROLE_REGULAR: - { - Session_component &session = *new (_md_alloc) - Session_component(_env, _ram, resources, label, diag, - _window_registry, _md_alloc, + try { + Session_component &session = *new (_sliced_heap) + Session_component(_env, resources, label, diag, + _window_registry, _pointer_tracker, _click_handler); _sessions.insert(&session); return session.cap(); } + catch (Out_of_ram) { throw Insufficient_ram_quota(); } + catch (Out_of_caps) { throw Insufficient_cap_quota(); } case ROLE_DECORATOR: - { - Decorator_gui_session &session = *new (_md_alloc) - Decorator_gui_session(_env, _ram, resources, label, diag, - _md_alloc, + try { + Decorator_gui_session &session = *new (_sliced_heap) + Decorator_gui_session(_env, resources, label, diag, _pointer_tracker, _window_layouter_input, *this); _decorator_sessions.insert(&session); return session.cap(); } + catch (Out_of_ram) { throw Insufficient_ram_quota(); } + catch (Out_of_caps) { throw Insufficient_cap_quota(); } case ROLE_LAYOUTER: { - _layouter_session = new (_md_alloc) + _layouter_session = new (_sliced_heap) Layouter_gui_session(_env, resources, label, diag, _window_layouter_input_cap); @@ -1326,7 +1425,7 @@ class Wm::Gui::Root : public Genode::Rpc_object case ROLE_DIRECT: { - Direct_gui_session &session = *new (_md_alloc) + Direct_gui_session &session = *new (_sliced_heap) Direct_gui_session(_env, resources, label, diag); return session.cap(); @@ -1350,13 +1449,13 @@ class Wm::Gui::Root : public Genode::Rpc_object dynamic_cast(session); if (regular_session) - regular_session->upgrade(args.string()); + regular_session->upgrade_local_or_remote(session_resources_from_args(args.string())); Decorator_gui_session *decorator_session = dynamic_cast(session); if (decorator_session) - decorator_session->upgrade(args.string()); + decorator_session->upgrade_local_or_remote(session_resources_from_args(args.string())); Direct_gui_session *direct_session = dynamic_cast(session); @@ -1378,7 +1477,7 @@ class Wm::Gui::Root : public Genode::Rpc_object return session; }); if (regular_session) { - Genode::destroy(_md_alloc, regular_session); + Genode::destroy(_sliced_heap, regular_session); return; } @@ -1387,7 +1486,7 @@ class Wm::Gui::Root : public Genode::Rpc_object return session; }); if (direct_session) { - Genode::destroy(_md_alloc, direct_session); + Genode::destroy(_sliced_heap, direct_session); return; } @@ -1398,7 +1497,7 @@ class Wm::Gui::Root : public Genode::Rpc_object return session; }); if (decorator_session) { - Genode::destroy(_md_alloc, decorator_session); + Genode::destroy(_sliced_heap, decorator_session); return; } @@ -1408,7 +1507,7 @@ class Wm::Gui::Root : public Genode::Rpc_object }; if (ep.apply(session_cap, layouter_lambda) == _layouter_session) { - Genode::destroy(_md_alloc, _layouter_session); + Genode::destroy(_sliced_heap, _layouter_session); return; } } diff --git a/repos/gems/src/server/wm/main.cc b/repos/gems/src/server/wm/main.cc index 82d0fdbd49..9518188310 100644 --- a/repos/gems/src/server/wm/main.cc +++ b/repos/gems/src/server/wm/main.cc @@ -29,11 +29,6 @@ namespace Wm { class Main; - using Genode::size_t; - using Genode::Rom_session_client; - using Genode::Rom_connection; - using Genode::Xml_node; - using Genode::Attached_rom_dataspace; } @@ -62,7 +57,7 @@ struct Wm::Main : Pointer::Tracker Gui::Connection focus_gui_session { env }; - Gui::Root gui_root { env, window_registry, heap, env.ram(), + Gui::Root gui_root { env, window_registry, *this, focus_request_reporter, focus_gui_session }; diff --git a/repos/gems/src/server/wm/real_gui.h b/repos/gems/src/server/wm/real_gui.h index f41af24b0e..0cdcb382e9 100644 --- a/repos/gems/src/server/wm/real_gui.h +++ b/repos/gems/src/server/wm/real_gui.h @@ -34,6 +34,8 @@ struct Wm::Real_gui using Command_buffer = Gui::Session::Command_buffer; + static constexpr Genode::size_t RAM_QUOTA = 36*1024; + public: Real_gui(Genode::Env &env, Genode::Session_label const &label) @@ -42,7 +44,7 @@ struct Wm::Real_gui { } Genode::Connection connection { - _env, label, Genode::Ram_quota { 36*1024 }, /* Args */ { } }; + _env, label, Genode::Ram_quota { RAM_QUOTA }, /* Args */ { } }; Gui::Session_client session { connection.cap() }; diff --git a/repos/gems/src/server/wm/types.h b/repos/gems/src/server/wm/types.h new file mode 100644 index 0000000000..7f88379c23 --- /dev/null +++ b/repos/gems/src/server/wm/types.h @@ -0,0 +1,72 @@ +/* + * \brief Common types used within the window manager + * \author Norman Feske + * \date 2024-09-04 + */ + +/* + * Copyright (C) 2024 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 _TYPES_H_ +#define _TYPES_H_ + +/* Genode includes */ +#include +#include + +namespace Wm { + + using Genode::uint8_t; + using Genode::size_t; + using Genode::Rom_connection; + using Genode::Xml_node; + using Genode::Attached_rom_dataspace; + using Genode::Tslab; + using Genode::Cap_quota; + using Genode::Ram_quota; + + /* + * Slab allocator that includes an initial block as member + */ + template + struct Initial_slab_block { uint8_t buf[BLOCK_SIZE]; }; + template + struct Slab : private Initial_slab_block, Tslab + { + Slab(Allocator &block_alloc) + : Tslab(block_alloc, Initial_slab_block::buf) { }; + }; + + struct Upgradeable : Genode::Noncopyable + { + bool _starved_for_ram = false, _starved_for_caps = false; + + void _upgrade_local_or_remote(auto const &resources, auto &session_obj, auto &real_gui) + { + Ram_quota ram = resources.ram_quota; + Cap_quota caps = resources.cap_quota; + + if (_starved_for_caps && caps.value) { + session_obj.upgrade(caps); + _starved_for_caps = false; + caps = { }; + } + + if (_starved_for_ram && ram.value) { + session_obj.upgrade(ram); + _starved_for_ram = false; + ram = { }; + } + + if (ram.value || caps.value) { + real_gui.connection.upgrade({ ram, caps }); + } + } + }; +} + +#endif /* _TYPES_H_ */