aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-24 17:50:16 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-24 17:50:16 +0200
commite99eb52d9923606dd325862a5f2e649eee0b2d3e (patch)
treee3a15138bfec8a630d02f0f858bb9f000c6da3f8
parentaa25bfac399e32efda039eb833b2c4d74f1edba0 (diff)
downloadkernel-e99eb52d9923606dd325862a5f2e649eee0b2d3e.tar.xz
kernel-e99eb52d9923606dd325862a5f2e649eee0b2d3e.zip
kapi: formally extract device registry
-rw-r--r--kapi/kapi/devices.hpp2
-rw-r--r--kapi/kapi/devices/device_registry.hpp60
-rw-r--r--kapi/kapi/devices/manager.hpp46
-rw-r--r--kapi/kapi/test_support/devices.hpp1
-rw-r--r--kernel/CMakeLists.txt1
-rw-r--r--kernel/kapi/devices.cpp65
-rw-r--r--kernel/kapi/devices.tests.cpp10
-rw-r--r--kernel/kapi/devices/bus.cpp2
-rw-r--r--kernel/kapi/devices/device_registry.cpp106
-rw-r--r--kernel/kapi/devices/driver.tests.cpp4
-rw-r--r--kernel/kapi/devices/driver_registry.cpp4
-rw-r--r--kernel/kapi/devices/driver_registry.tests.cpp8
12 files changed, 187 insertions, 122 deletions
diff --git a/kapi/kapi/devices.hpp b/kapi/kapi/devices.hpp
index 92c8df89..ed082bed 100644
--- a/kapi/kapi/devices.hpp
+++ b/kapi/kapi/devices.hpp
@@ -7,12 +7,12 @@
#include <kapi/devices/character_device.hpp> // IWYU pragma: export
#include <kapi/devices/cpu.hpp> // IWYU pragma: export
#include <kapi/devices/device.hpp> // IWYU pragma: export
+#include <kapi/devices/device_registry.hpp> // IWYU pragma: export
#include <kapi/devices/driver.hpp> // IWYU pragma: export
#include <kapi/devices/driver_registry.hpp> // IWYU pragma: export
#include <kapi/devices/error.hpp> // IWYU pragma: export
#include <kapi/devices/interface.hpp> // IWYU pragma: export
#include <kapi/devices/interface_registry.hpp> // IWYU pragma: export
-#include <kapi/devices/manager.hpp> // IWYU pragma: export
#include <kstd/memory.hpp>
#include <kstd/result.hpp>
diff --git a/kapi/kapi/devices/device_registry.hpp b/kapi/kapi/devices/device_registry.hpp
new file mode 100644
index 00000000..00d04311
--- /dev/null
+++ b/kapi/kapi/devices/device_registry.hpp
@@ -0,0 +1,60 @@
+#ifndef TEACHOS_KAPI_DEVICES_MANAGER_HPP
+#define TEACHOS_KAPI_DEVICES_MANAGER_HPP
+
+// IWYU pragma: private, include <kapi/devices.hpp>
+
+#include <kapi/devices/device.hpp>
+
+#include <kstd/flat_map.hpp>
+#include <kstd/memory.hpp>
+#include <kstd/string.hpp>
+#include <kstd/vector.hpp>
+
+#include <string_view>
+
+namespace kapi::devices
+{
+
+ //! @addtogroup kapi-devices-kernel-defined
+ //! @{
+
+ struct device_registry
+ {
+ device_registry() = default;
+
+ auto static init() -> void;
+
+ auto static get() -> device_registry &;
+
+ //! Add a new device tp the kernel's device registry.
+ //!
+ //! @param device The device to register.
+ //! @return true if the device was registered successfully, false otherwise.
+ auto add(kstd::shared_ptr<device> device) -> bool;
+
+ //! Remove a device from the kernel's device registry.
+ //!
+ //! @param device The device to unregister.
+ //! @return true if the device was unregistered successfully, false otherwise.
+ auto remove(device & device) -> bool;
+
+ //! Find a device by its name.
+ //!
+ //! @param name the name of the device.
+ //! @return a shared pointer to the device iff. the device was found and is still alive, nullptr otherwise.
+ [[nodiscard]] auto find(std::string_view name) const -> kstd::shared_ptr<device>;
+
+ //! Get all currently registered devices.
+ //!
+ //! @return every device current reachable through the registry.
+ [[nodiscard]] auto all() const -> kstd::vector<kstd::shared_ptr<device>>;
+
+ private:
+ kstd::flat_map<kstd::string, kstd::weak_ptr<device>> m_devices{};
+ };
+
+ //! @}
+
+} // namespace kapi::devices
+
+#endif \ No newline at end of file
diff --git a/kapi/kapi/devices/manager.hpp b/kapi/kapi/devices/manager.hpp
deleted file mode 100644
index de6ebf97..00000000
--- a/kapi/kapi/devices/manager.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef TEACHOS_KAPI_DEVICES_MANAGER_HPP
-#define TEACHOS_KAPI_DEVICES_MANAGER_HPP
-
-// IWYU pragma: private, include <kapi/devices.hpp>
-
-#include <kapi/devices/device.hpp>
-
-#include <kstd/memory.hpp>
-#include <kstd/vector.hpp>
-
-#include <string_view>
-
-namespace kapi::devices
-{
-
- //! @addtogroup kapi-devices-kernel-defined
- //! @{
-
- //! Register a new device with the kernel's device manager.
- //!
- //! @param device The device to register.
- //! @return true if the device was registered successfully, false otherwise.
- auto register_device(kstd::shared_ptr<device> device) -> bool;
-
- //! Unregister a device from the kernel's device manager.
- //!
- //! @param device The device to unregister.
- //! @return true if the device was unregistered successfully, false otherwise.
- auto unregister_device(device & device) -> bool;
-
- //! Find a device by its name.
- //!
- //! @param name the name of the device.
- //! @return a shared pointer to the device iff. the device was found and is still alive, nullptr otherwise.
- auto find_device(std::string_view name) -> kstd::shared_ptr<device>;
-
- //! Get all currently registered devices.
- //!
- //! @return every device current reachable through the registry.
- [[nodiscard]] auto all() -> kstd::vector<kstd::shared_ptr<device>>;
-
- //! @}
-
-} // namespace kapi::devices
-
-#endif \ No newline at end of file
diff --git a/kapi/kapi/test_support/devices.hpp b/kapi/kapi/test_support/devices.hpp
index b4d410d6..3cb1cd8b 100644
--- a/kapi/kapi/test_support/devices.hpp
+++ b/kapi/kapi/test_support/devices.hpp
@@ -6,6 +6,7 @@ namespace kapi::test_support::devices
auto deinit() -> void;
auto deinit_interface_registry() -> void;
auto deinit_driver_registry() -> void;
+ auto deinit_device_registry() -> void;
} // namespace kapi::test_support::devices
#endif
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index 082cb7be..f4d0d3b3 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -16,6 +16,7 @@ target_sources("kernel_lib" PRIVATE
"kapi/devices/bus.cpp"
"kapi/devices/cpu.cpp"
"kapi/devices/device.cpp"
+ "kapi/devices/device_registry.cpp"
"kapi/devices/driver.cpp"
"kapi/devices/driver_registry.cpp"
"kapi/devices/error.cpp"
diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp
index 64e549f3..b0f384ab 100644
--- a/kernel/kapi/devices.cpp
+++ b/kernel/kapi/devices.cpp
@@ -8,12 +8,9 @@
#include <kstd/flat_map.hpp>
#include <kstd/memory.hpp>
-#include <kstd/print.hpp>
#include <kstd/string.hpp>
-#include <kstd/vector.hpp>
#include <string_view>
-#include <utility>
namespace kapi::devices
{
@@ -30,11 +27,12 @@ namespace kapi::devices
kapi::system::panic("[OS:DEV] The device subsystem has already been initialized");
}
+ device_registry::init();
interface_registry::init();
kernel::drivers::init();
root_bus = kstd::make_shared<kernel::devices::root_bus>();
- register_device(root_bus);
+ device_registry::get().add(root_bus);
}
auto get_root_bus() -> kstd::shared_ptr<bus>
@@ -46,70 +44,15 @@ namespace kapi::devices
return root_bus;
}
- auto register_device(kstd::shared_ptr<device> device) -> bool
- {
- if (!device)
- {
- return false;
- }
-
- kstd::println("[OS:DEV] Registering device {}", device->name());
-
- auto found = device_tree.find(device->name());
- if (found != device_tree.end())
- {
- if (!found->second.expired())
- {
- return false;
- }
-
- found->second = device;
- return true;
- }
-
- return device_tree.emplace(device->name(), device).second;
- }
-
- auto unregister_device(device &) -> bool
- {
- kstd::println("[OS:DEV] TODO: implement device deregistration");
- return false;
- }
-
- auto find_device(std::string_view name) -> kstd::shared_ptr<device>
- {
- auto found = device_tree.find(kstd::string{name});
- if (found == device_tree.end())
- {
- return nullptr;
- }
-
- return found->second.lock();
- }
-
- auto all() -> kstd::vector<kstd::shared_ptr<device>>
- {
- auto result = kstd::vector<kstd::shared_ptr<device>>{};
-
- for (auto const & [name, weak_device] : device_tree)
- {
- if (auto device = weak_device.lock())
- {
- result.push_back(std::move(device));
- }
- }
-
- return result;
- }
-
} // namespace kapi::devices
namespace kapi::test_support::devices
{
auto deinit() -> void
{
- deinit_interface_registry();
deinit_driver_registry();
+ deinit_interface_registry();
+ deinit_device_registry();
kapi::devices::root_bus.reset();
}
diff --git a/kernel/kapi/devices.tests.cpp b/kernel/kapi/devices.tests.cpp
index 627c5ce0..1064c000 100644
--- a/kernel/kapi/devices.tests.cpp
+++ b/kernel/kapi/devices.tests.cpp
@@ -28,14 +28,14 @@ SCENARIO("the device registry holds devices weakly and prunes stale entries lazi
THEN("it is discoverable via find_devices")
{
- auto found = kapi::devices::find_device("registry_test_device");
+ auto found = kapi::devices::device_registry::get().find("registry_test_device");
REQUIRE(found);
REQUIRE(found->name() == "registry_test_device");
}
THEN("find_device reports no match for an uknown name")
{
- REQUIRE_FALSE(kapi::devices::find_device("does_not_exist"));
+ REQUIRE_FALSE(kapi::devices::device_registry::get().find("does_not_exist"));
}
WHEN("every strong reference to the device is dropped")
@@ -44,7 +44,7 @@ SCENARIO("the device registry holds devices weakly and prunes stale entries lazi
THEN("find_device no longer resolves it")
{
- REQUIRE_FALSE(kapi::devices::find_device("registry_test_device"));
+ REQUIRE_FALSE(kapi::devices::device_registry::get().find("registry_test_device"));
}
}
}
@@ -59,12 +59,12 @@ SCENARIO("the device registry holds devices weakly and prunes stale entries lazi
WHEN("a new device is registered under the very same name")
{
auto new_device = kstd::make_shared<test_device>("registry_reuse_device");
- auto registered = kapi::devices::register_device(new_device);
+ auto registered = kapi::devices::device_registry::get().add(new_device);
THEN("registration succeeds")
{
REQUIRE(registered);
- REQUIRE(kapi::devices::find_device("registry_reuse_device") == new_device);
+ REQUIRE(kapi::devices::device_registry::get().find("registry_reuse_device") == new_device);
}
}
}
diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp
index db693eac..1b3ad4bf 100644
--- a/kernel/kapi/devices/bus.cpp
+++ b/kernel/kapi/devices/bus.cpp
@@ -21,7 +21,7 @@ namespace kapi::devices
{
child->set_parent(kstd::static_pointer_cast<bus>(shared_from_this()));
- if (!kapi::devices::register_device(child))
+ if (!kapi::devices::device_registry::get().add(child))
{
kapi::system::panic("[OS:DEV] Failed to register child device {}", child->name());
}
diff --git a/kernel/kapi/devices/device_registry.cpp b/kernel/kapi/devices/device_registry.cpp
new file mode 100644
index 00000000..aca0e7fe
--- /dev/null
+++ b/kernel/kapi/devices/device_registry.cpp
@@ -0,0 +1,106 @@
+#include <kapi/devices/device_registry.hpp>
+
+#include <kapi/devices/device.hpp>
+#include <kapi/system.hpp>
+
+#include <kstd/memory.hpp>
+#include <kstd/print.hpp>
+#include <kstd/string.hpp>
+#include <kstd/vector.hpp>
+
+#include <optional>
+#include <string_view>
+#include <utility>
+
+namespace kapi::devices
+{
+
+ namespace
+ {
+ auto constinit instance = std::optional<device_registry>{};
+ }
+
+ auto device_registry::init() -> void
+ {
+ if (instance)
+ {
+ system::panic("[OS:DEV] Device registry has already been initialized");
+ }
+
+ instance = device_registry{};
+ }
+
+ auto device_registry::get() -> device_registry &
+ {
+ if (!instance)
+ {
+ system::panic("[OS:DEV] Device registry has not been initialized");
+ }
+
+ return *instance;
+ }
+
+ auto device_registry::add(kstd::shared_ptr<device> device) -> bool
+ {
+ if (!device)
+ {
+ return false;
+ }
+
+ kstd::println("[OS:DEV] Registering device {}", device->name());
+
+ auto found = m_devices.find(device->name());
+ if (found != m_devices.end())
+ {
+ if (!found->second.expired())
+ {
+ return false;
+ }
+
+ found->second = device;
+ return true;
+ }
+
+ return m_devices.emplace(device->name(), device).second;
+ }
+
+ auto device_registry::remove(device &) -> bool
+ {
+ kstd::println("[OS:DEV] TODO: implement device deregistration");
+ return false;
+ }
+
+ auto device_registry::find(std::string_view name) const -> kstd::shared_ptr<device>
+ {
+ auto found = m_devices.find(kstd::string{name});
+ if (found == m_devices.end())
+ {
+ return nullptr;
+ }
+
+ return found->second.lock();
+ }
+
+ auto device_registry::all() const -> kstd::vector<kstd::shared_ptr<device>>
+ {
+ auto result = kstd::vector<kstd::shared_ptr<device>>{};
+
+ for (auto const & [name, weak_device] : m_devices)
+ {
+ if (auto device = weak_device.lock())
+ {
+ result.push_back(std::move(device));
+ }
+ }
+
+ return result;
+ }
+} // namespace kapi::devices
+
+namespace kapi::test_support::devices
+{
+ auto deinit_device_registry() -> void
+ {
+ kapi::devices::instance.reset();
+ }
+} // namespace kapi::test_support::devices \ No newline at end of file
diff --git a/kernel/kapi/devices/driver.tests.cpp b/kernel/kapi/devices/driver.tests.cpp
index abce92d2..53c569dd 100644
--- a/kernel/kapi/devices/driver.tests.cpp
+++ b/kernel/kapi/devices/driver.tests.cpp
@@ -213,14 +213,14 @@ SCENARIO("a bound controller driver can attach a further, independently-typed bu
THEN("the controller device bound the controller driver")
{
- auto controller = kapi::devices::find_device("stacking_test_controller");
+ auto controller = kapi::devices::device_registry::get().find("stacking_test_controller");
REQUIRE(controller != nullptr);
REQUIRE(controller->state() == kapi::devices::state::bound);
}
THEN("the leaf device the controller driver attached is reachable and bound to the leaf driver")
{
- auto leaf = kapi::devices::find_device("stacking_test_leaf");
+ auto leaf = kapi::devices::device_registry::get().find("stacking_test_leaf");
REQUIRE(leaf != nullptr);
REQUIRE(leaf->state() == kapi::devices::state::bound);
REQUIRE(leaf->bound_driver() != nullptr);
diff --git a/kernel/kapi/devices/driver_registry.cpp b/kernel/kapi/devices/driver_registry.cpp
index 67da9877..5784694a 100644
--- a/kernel/kapi/devices/driver_registry.cpp
+++ b/kernel/kapi/devices/driver_registry.cpp
@@ -3,8 +3,8 @@
#include <kapi/devices/bus.hpp>
#include <kapi/devices/bus_protocol.hpp>
#include <kapi/devices/device.hpp>
+#include <kapi/devices/device_registry.hpp>
#include <kapi/devices/driver.hpp>
-#include <kapi/devices/manager.hpp>
#include <kapi/system.hpp>
#include <kapi/test_support/devices.hpp>
@@ -57,7 +57,7 @@ namespace kapi::devices
{
m_drivers.emplace_back(std::move(driver));
- for (auto const & device : kapi::devices::all())
+ for (auto const & device : kapi::devices::device_registry::get().all())
{
if (device->state() != state::bound)
{
diff --git a/kernel/kapi/devices/driver_registry.tests.cpp b/kernel/kapi/devices/driver_registry.tests.cpp
index 52f320f4..bf87fb47 100644
--- a/kernel/kapi/devices/driver_registry.tests.cpp
+++ b/kernel/kapi/devices/driver_registry.tests.cpp
@@ -131,7 +131,7 @@ SCENARIO("Driver registry binds devices and drivers regardless of arrival order"
THEN("the device binds")
{
- auto dev = kapi::devices::find_device("driver_registry_test_device_1");
+ auto dev = kapi::devices::device_registry::get().find("driver_registry_test_device_1");
REQUIRE(dev);
REQUIRE(dev->state() == kapi::devices::state::bound);
}
@@ -144,7 +144,7 @@ SCENARIO("Driver registry binds devices and drivers regardless of arrival order"
THEN("the device binds")
{
- auto dev = kapi::devices::find_device("driver_registry_test_device_2");
+ auto dev = kapi::devices::device_registry::get().find("driver_registry_test_device_2");
REQUIRE(dev);
REQUIRE(dev->state() == kapi::devices::state::bound);
}
@@ -169,7 +169,7 @@ SCENARIO("driver_registry picks the highest-priority match", "[devices][driver_r
THEN("it binds to the higher-priority driver")
{
- auto dev = kapi::devices::find_device("driver_registry_priority_device");
+ auto dev = kapi::devices::device_registry::get().find("driver_registry_priority_device");
REQUIRE(dev != nullptr);
REQUIRE(dev->bound_driver() == high_priority.get());
}
@@ -194,7 +194,7 @@ SCENARIO("driver_registry breaks ties by registration order", "[devices][driver_
THEN("the first-registered driver wins the tie")
{
- auto dev = kapi::devices::find_device("driver_registry_tie_device");
+ auto dev = kapi::devices::device_registry::get().find("driver_registry_tie_device");
REQUIRE(dev != nullptr);
REQUIRE(dev->bound_driver() == registered_first.get());
}