From db92fcd2a865889dbf5cc524f2c27e5855167e9c Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sat, 25 Jul 2026 13:49:21 +0200 Subject: kernel: bootstrap device_number_registry Previously, the device number registry would only receive devices from the interface registry that where published **after** the device number registry was constructed. This introduced a subtle state race, in which the device number registry would miss devices that already had published interfaces. --- .../kernel/filesystem/device_number_registry.cpp | 88 +++++++++++++--------- .../kernel/filesystem/device_number_registry.hpp | 3 + 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/kernel/kernel/filesystem/device_number_registry.cpp b/kernel/kernel/filesystem/device_number_registry.cpp index 92f59bc5..aca0c64c 100644 --- a/kernel/kernel/filesystem/device_number_registry.cpp +++ b/kernel/kernel/filesystem/device_number_registry.cpp @@ -37,6 +37,14 @@ namespace kernel::filesystem device_number_registry::device_number_registry(kapi::devices::interface_registry & interface_registry) : m_interface_registry{&interface_registry} { + for (auto const & binding : file_type_bindings) + { + for (auto const & published : interface_registry.all(binding.interface)) + { + try_number(binding.interface, published); + } + } + m_interface_registry->subscribe(*this); } @@ -109,6 +117,49 @@ namespace kernel::filesystem auto device_number_registry::on_interface_published(kapi::devices::interface_id interface, kapi::devices::interface_registry::entry const & published) -> void + { + try_number(interface, published); + } + + auto device_number_registry::on_interface_withdrawn(kapi::devices::interface_id interface, + kapi::devices::device & device) -> void + { + // Check if there even is a binding defined for the given interface. + auto binding = + std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); + if (binding == std::ranges::cend(file_type_bindings)) + { + return; + } + + // TODO: lock registry + + auto found = std::ranges::find_if(m_entries, [&](auto entry) { + auto locked = entry.device.lock(); + return entry.type == binding->posix_type && locked.get() == &device; + }); + + if (found == std::ranges::cend(m_entries)) + { + m_entries.erase(found); + } + + auto unnumbered = *found; + m_entries.erase(found); + + // TODO: drop lock + + std::ranges::for_each(m_observers, [&](auto const & weak_observer) { + auto observer = weak_observer.lock(); + if (observer) + { + observer->on_device_unnumbered(unnumbered); + } + }); + } + + auto device_number_registry::try_number(kapi::devices::interface_id interface, + kapi::devices::interface_registry::entry const & published) -> void { // Check if there even is a binding defined for the given interface. auto binding = @@ -171,43 +222,6 @@ namespace kernel::filesystem } }); } - - auto device_number_registry::on_interface_withdrawn(kapi::devices::interface_id interface, - kapi::devices::device & device) -> void - { - // Check if there even is a binding defined for the given interface. - auto binding = - std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); - if (binding == std::ranges::cend(file_type_bindings)) - { - return; - } - - // TODO: lock registry - - auto found = std::ranges::find_if(m_entries, [&](auto entry) { - auto locked = entry.device.lock(); - return entry.type == binding->posix_type && locked.get() == &device; - }); - - if (found == std::ranges::cend(m_entries)) - { - m_entries.erase(found); - } - - auto unnumbered = *found; - m_entries.erase(found); - - // TODO: drop lock - - std::ranges::for_each(m_observers, [&](auto const & weak_observer) { - auto observer = weak_observer.lock(); - if (observer) - { - observer->on_device_unnumbered(unnumbered); - } - }); - } } // namespace kernel::filesystem namespace kernel::tests::filesystem::device_number_registry diff --git a/kernel/kernel/filesystem/device_number_registry.hpp b/kernel/kernel/filesystem/device_number_registry.hpp index 949d7bba..20a26c22 100644 --- a/kernel/kernel/filesystem/device_number_registry.hpp +++ b/kernel/kernel/filesystem/device_number_registry.hpp @@ -83,6 +83,9 @@ namespace kernel::filesystem auto on_interface_withdrawn(kapi::devices::interface_id interface, kapi::devices::device & device) -> void override; + auto try_number(kapi::devices::interface_id interface, kapi::devices::interface_registry::entry const & published) + -> void; + kstd::observer_ptr m_interface_registry; mutable kstd::vector m_entries{}; kstd::flat_map m_next_minor; -- cgit v1.2.3