From 080d3b6b637653e80a54e3c2c65c2b03e179af5d Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Wed, 14 Feb 2024 14:46:06 +0100 Subject: [PATCH] vfs: support watch handlers on application signal level Fixes #4092 --- repos/gems/src/app/menu_view/main.cc | 4 +- repos/gems/src/app/menu_view/style_database.h | 13 ++++-- repos/gems/src/app/text_area/main.cc | 3 +- repos/gems/src/lib/vfs/trace/vfs.cc | 4 +- repos/gems/src/server/terminal/main.cc | 11 ++++- repos/libports/src/lib/libc/internal/kernel.h | 4 +- repos/libports/src/lib/vfs/oss/vfs_oss.cc | 18 ++++---- repos/os/include/os/vfs.h | 46 ++++++++++++++++++- repos/os/src/lib/vfs/tap/vfs_tap.cc | 2 +- 9 files changed, 79 insertions(+), 26 deletions(-) diff --git a/repos/gems/src/app/menu_view/main.cc b/repos/gems/src/app/menu_view/main.cc index 94c38d7054..ed97ae2505 100644 --- a/repos/gems/src/app/menu_view/main.cc +++ b/repos/gems/src/app/menu_view/main.cc @@ -103,8 +103,8 @@ struct Menu_view::Main Directory _fonts_dir { _root_dir, "fonts" }; Directory _styles_dir { _root_dir, "styles" }; - Style_database _styles { _env.ram(), _env.rm(), _heap, _fonts_dir, _styles_dir, - _dialog_update_handler }; + Style_database _styles { _env.ep(), _env.ram(), _env.rm(), _heap, + _fonts_dir, _styles_dir, _dialog_update_handler }; Animator _animator { }; diff --git a/repos/gems/src/app/menu_view/style_database.h b/repos/gems/src/app/menu_view/style_database.h index 640d2d3165..d828721b85 100644 --- a/repos/gems/src/app/menu_view/style_database.h +++ b/repos/gems/src/app/menu_view/style_database.h @@ -148,19 +148,21 @@ class Menu_view::Style_database * * \throw Reading_failed */ - Font_entry(Directory const &fonts_dir, Path const &path, Allocator &alloc, + Font_entry(Entrypoint &ep, Directory const &fonts_dir, + Path const &path, Allocator &alloc, Style_database const &style_database) try : path(path), _style_database(style_database), _vfs_font(alloc, fonts_dir, path), _cached_font(alloc, _vfs_font, _font_cache_limit), - _glyphs_changed_handler(fonts_dir, Path(path, "/glyphs"), + _glyphs_changed_handler(ep, fonts_dir, Path(path, "/glyphs"), *this, &Font_entry::_handle_glyphs_changed) { } catch (...) { throw Reading_failed(); } }; + Entrypoint &_ep; Ram_allocator &_ram; Region_map &_rm; Allocator &_alloc; @@ -228,11 +230,12 @@ class Menu_view::Style_database public: - Style_database(Ram_allocator &ram, Region_map &rm, Allocator &alloc, + Style_database(Entrypoint &ep, Ram_allocator &ram, Region_map &rm, + Allocator &alloc, Directory const &fonts_dir, Directory const &styles_dir, Signal_context_capability style_changed_sigh) : - _ram(ram), _rm(rm), _alloc(alloc), + _ep(ep), _ram(ram), _rm(rm), _alloc(alloc), _fonts_dir(fonts_dir), _styles_dir(styles_dir), _style_changed_sigh(style_changed_sigh) { } @@ -273,7 +276,7 @@ class Menu_view::Style_database */ try { Font_entry *e = new (_alloc) - Font_entry(_fonts_dir, path, _alloc, *this); + Font_entry(_ep, _fonts_dir, path, _alloc, *this); _fonts.insert(e); return &e->font(); diff --git a/repos/gems/src/app/text_area/main.cc b/repos/gems/src/app/text_area/main.cc index 1b446b0833..1dcd540385 100644 --- a/repos/gems/src/app/text_area/main.cc +++ b/repos/gems/src/app/text_area/main.cc @@ -136,7 +136,8 @@ struct Text_area::Main : Text_area_widget::Action void _watch(bool enabled) { - _watch_handler.conditional(enabled, _vfs, _path(), *this, &Main::_handle_watch); + _watch_handler.conditional(enabled, _env.ep(), _vfs, _path(), *this, + &Main::_handle_watch); } bool _editable() const { return !_watch_handler.constructed(); } diff --git a/repos/gems/src/lib/vfs/trace/vfs.cc b/repos/gems/src/lib/vfs/trace/vfs.cc index bf3acee1b0..4d887e2c57 100644 --- a/repos/gems/src/lib/vfs/trace/vfs.cc +++ b/repos/gems/src/lib/vfs/trace/vfs.cc @@ -279,12 +279,12 @@ class Vfs_trace::Subject : private Subject_factory, typedef String<200> Config; - Watch_handler _enable_handler { + Io::Watch_handler _enable_handler { _enabled_fs, "/enable", Subject_factory::_env.alloc(), *this, &Subject::_enable_subject }; - Watch_handler _buffer_size_handler { + Io::Watch_handler _buffer_size_handler { _buffer_size_fs, "/buffer_size", Subject_factory::_env.alloc(), *this, &Subject::_buffer_size }; diff --git a/repos/gems/src/server/terminal/main.cc b/repos/gems/src/server/terminal/main.cc index a77da2c8a5..2d45f6ed96 100644 --- a/repos/gems/src/server/terminal/main.cc +++ b/repos/gems/src/server/terminal/main.cc @@ -80,8 +80,15 @@ struct Terminal::Main : Character_consumer _config_handler.local_submit(); } - Watch_handler
_glyphs_changed_handler { - _root_dir, "fonts/monospace/regular/glyphs", *this, &Main::_handle_glyphs_changed }; + /* + * XXX Currently an I/O-level watch handler is used + * to prevent a config/watch handler cycle as + * side-effect of '_root_dir.apply_config()' with + * an application-level watch handler. + */ + Io::Watch_handler
_glyphs_changed_handler { + _root_dir, "fonts/monospace/regular/glyphs", *this, + &Main::_handle_glyphs_changed }; Color_palette _color_palette { }; diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index c00aab4fa1..0b16e3b913 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -202,12 +202,12 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler, Constructible _rtc { }; /* handler for watching the stdout's info pseudo file */ - Constructible> _terminal_resize_handler { }; + Constructible> _terminal_resize_handler { }; void _handle_terminal_resize(); /* handler for watching user interrupts (control-c) */ - Constructible> _user_interrupt_handler { }; + Constructible> _user_interrupt_handler { }; void _handle_user_interrupt(); diff --git a/repos/libports/src/lib/vfs/oss/vfs_oss.cc b/repos/libports/src/lib/vfs/oss/vfs_oss.cc index fe0874b3d2..ad8958f9bf 100644 --- a/repos/libports/src/lib/vfs/oss/vfs_oss.cc +++ b/repos/libports/src/lib/vfs/oss/vfs_oss.cc @@ -813,55 +813,55 @@ struct Vfs::Oss_file_system::Local_factory : File_system_factory Audio _audio { _env.env(), _info, _info_fs }; - Genode::Watch_handler _enable_input_handler { + Genode::Io::Watch_handler _enable_input_handler { _enable_input_fs, "/enable_input", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_enable_input_changed }; - Genode::Watch_handler _enable_output_handler { + Genode::Io::Watch_handler _enable_output_handler { _enable_output_fs, "/enable_output", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_enable_output_changed }; - Genode::Watch_handler _halt_input_handler { + Genode::Io::Watch_handler _halt_input_handler { _halt_input_fs, "/halt_input", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_halt_input_changed }; - Genode::Watch_handler _halt_output_handler { + Genode::Io::Watch_handler _halt_output_handler { _halt_output_fs, "/halt_output", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_halt_output_changed }; - Genode::Watch_handler _ifrag_total_handler { + Genode::Io::Watch_handler _ifrag_total_handler { _ifrag_total_fs, "/ifrag_total", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_ifrag_total_changed }; - Genode::Watch_handler _ifrag_size_handler { + Genode::Io::Watch_handler _ifrag_size_handler { _ifrag_size_fs, "/ifrag_size", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_ofrag_size_changed }; - Genode::Watch_handler _ofrag_total_handler { + Genode::Io::Watch_handler _ofrag_total_handler { _ofrag_total_fs, "/ofrag_total", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_ofrag_total_changed }; - Genode::Watch_handler _ofrag_size_handler { + Genode::Io::Watch_handler _ofrag_size_handler { _ofrag_size_fs, "/ofrag_size", _env.alloc(), *this, &Vfs::Oss_file_system::Local_factory::_ofrag_size_changed }; - Genode::Watch_handler _play_underruns_handler { + Genode::Io::Watch_handler _play_underruns_handler { _play_underruns_fs, "/play_underruns", _env.alloc(), *this, diff --git a/repos/os/include/os/vfs.h b/repos/os/include/os/vfs.h index a5a4ab8ea6..ac414cb471 100644 --- a/repos/os/include/os/vfs.h +++ b/repos/os/include/os/vfs.h @@ -31,6 +31,10 @@ namespace Genode { class Append_file; class New_file; class Watcher; + namespace Io { + template + class Watch_handler; + } template class Watch_handler; template @@ -954,9 +958,12 @@ class Genode::Watcher }; +/** + * Watch handler that operates on I/O signal level + */ template -class Genode::Watch_handler : public Vfs::Watch_response_handler, - private Watcher +class Genode::Io::Watch_handler : public Vfs::Watch_response_handler, + private Watcher { private: @@ -981,4 +988,39 @@ class Genode::Watch_handler : public Vfs::Watch_response_handler, void watch_response() override { (_obj.*_member)(); } }; + +/** + * Watch handler that operates on application signal level + */ +template +class Genode::Watch_handler : public Signal_handler> +{ + private: + + Io::Watch_handler _io_watch_handler; + + T &_obj; + void (T::*_member) (); + + void _handle_watch_response() + { + Signal_handler>::local_submit(); + } + + void _handle_signal() + { + (_obj.*_member)(); + } + + public: + + Watch_handler(Genode::Entrypoint &ep, Directory const &dir, + Directory::Path const &rel_path, + T &obj, void (T::*member)()) + : Signal_handler>(ep, *this, &Watch_handler::_handle_signal), + _io_watch_handler(dir, rel_path, *this, &Watch_handler::_handle_watch_response), + _obj(obj), _member(member) + { } +}; + #endif /* _INCLUDE__OS__VFS_H_ */ diff --git a/repos/os/src/lib/vfs/tap/vfs_tap.cc b/repos/os/src/lib/vfs/tap/vfs_tap.cc index f8a0eeb7a2..1a177065cc 100644 --- a/repos/os/src/lib/vfs/tap/vfs_tap.cc +++ b/repos/os/src/lib/vfs/tap/vfs_tap.cc @@ -244,7 +244,7 @@ struct Vfs::Tap_file_system::Local_factory : File_system_factory, ** Watch handlers ** ********************/ - Genode::Watch_handler> _mac_addr_changed_handler { + Genode::Io::Watch_handler> _mac_addr_changed_handler { _mac_addr_fs, "/mac_addr", _env.alloc(), *this,