aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-25 13:49:21 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-25 13:49:21 +0200
commitdb92fcd2a865889dbf5cc524f2c27e5855167e9c (patch)
tree9bb4df7eb2c53bcb2818f448e5ecc982b4265b91
parent501b4f27c5f8e114cc56762e30105112e86b885c (diff)
downloadkernel-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.cpp88
-rw-r--r--kernel/kernel/filesystem/device_number_registry.hpp3
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;