diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-25 13:49:21 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-25 13:49:21 +0200 |
| commit | db92fcd2a865889dbf5cc524f2c27e5855167e9c (patch) | |
| tree | 9bb4df7eb2c53bcb2818f448e5ecc982b4265b91 | |
| parent | 501b4f27c5f8e114cc56762e30105112e86b885c (diff) | |
| download | kernel-db92fcd2a865889dbf5cc524f2c27e5855167e9c.tar.xz kernel-db92fcd2a865889dbf5cc524f2c27e5855167e9c.zip | |
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.
| -rw-r--r-- | kernel/kernel/filesystem/device_number_registry.cpp | 88 | ||||
| -rw-r--r-- | kernel/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); } @@ -110,6 +118,49 @@ namespace kernel::filesystem 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 = std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); @@ -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<kapi::devices::interface_registry> m_interface_registry; mutable kstd::vector<entry> m_entries{}; kstd::flat_map<kapi::devices::driver const *, std::uint8_t> m_next_minor; |
