diff options
| -rw-r--r-- | kapi/kapi/devices.hpp | 2 | ||||
| -rw-r--r-- | kapi/kapi/devices/device_registry.hpp | 60 | ||||
| -rw-r--r-- | kapi/kapi/devices/manager.hpp | 46 | ||||
| -rw-r--r-- | kapi/kapi/test_support/devices.hpp | 1 | ||||
| -rw-r--r-- | kernel/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | kernel/kapi/devices.cpp | 65 | ||||
| -rw-r--r-- | kernel/kapi/devices.tests.cpp | 10 | ||||
| -rw-r--r-- | kernel/kapi/devices/bus.cpp | 2 | ||||
| -rw-r--r-- | kernel/kapi/devices/device_registry.cpp | 106 | ||||
| -rw-r--r-- | kernel/kapi/devices/driver.tests.cpp | 4 | ||||
| -rw-r--r-- | kernel/kapi/devices/driver_registry.cpp | 4 | ||||
| -rw-r--r-- | kernel/kapi/devices/driver_registry.tests.cpp | 8 |
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()); } |
