From 59f54d012c71e782966e9d083f1ee9459fd3fd70 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sun, 26 Jul 2026 02:27:59 +0200 Subject: chore: replace "interface" with "facet" --- kernel/CMakeLists.txt | 2 +- kernel/kapi/boot_modules/device.cpp | 6 +- kernel/kapi/devices.cpp | 4 +- kernel/kapi/devices/bus.cpp | 11 +- kernel/kapi/devices/device.cpp | 14 +- kernel/kapi/devices/driver.cpp | 2 +- kernel/kapi/devices/driver.tests.cpp | 78 +++-- kernel/kapi/devices/driver_registry.cpp | 2 +- kernel/kapi/devices/driver_registry.tests.cpp | 21 +- kernel/kapi/devices/facet_registry.cpp | 216 ++++++++++++++ kernel/kapi/devices/facet_registry.tests.cpp | 327 ++++++++++++++++++++ kernel/kapi/devices/interface_registry.cpp | 218 -------------- kernel/kapi/devices/interface_registry.tests.cpp | 329 --------------------- kernel/kernel/bus/boot_modules.cpp | 15 +- kernel/kernel/bus/boot_modules.hpp | 2 +- kernel/kernel/devices/storage.cpp | 2 +- kernel/kernel/devices/storage.tests.cpp | 2 +- kernel/kernel/drivers/storage/ram_disk.cpp | 20 +- kernel/kernel/drivers/storage/ram_disk.hpp | 2 +- kernel/kernel/filesystem/device_inode.cpp | 4 +- kernel/kernel/filesystem/device_inode.tests.cpp | 2 +- .../kernel/filesystem/device_number_registry.cpp | 37 ++- .../kernel/filesystem/device_number_registry.hpp | 21 +- .../filesystem/device_number_registry.tests.cpp | 20 +- kernel/kernel/filesystem/file_type_bindings.hpp | 8 +- .../kernel/test_support/devices/block_device.cpp | 6 +- .../kernel/test_support/devices/block_device.hpp | 2 +- .../filesystem/storage_boot_module_fixture.cpp | 5 +- 28 files changed, 700 insertions(+), 678 deletions(-) create mode 100644 kernel/kapi/devices/facet_registry.cpp create mode 100644 kernel/kapi/devices/facet_registry.tests.cpp delete mode 100644 kernel/kapi/devices/interface_registry.cpp delete mode 100644 kernel/kapi/devices/interface_registry.tests.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9bb2efd8..d22ad107 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -19,7 +19,7 @@ target_sources("kernel_lib" PRIVATE "kapi/devices/driver.cpp" "kapi/devices/driver_registry.cpp" "kapi/devices/error.cpp" - "kapi/devices/interface_registry.cpp" + "kapi/devices/facet_registry.cpp" "kapi/filesystem.cpp" "kapi/interrupts.cpp" "kapi/memory.cpp" diff --git a/kernel/kapi/boot_modules/device.cpp b/kernel/kapi/boot_modules/device.cpp index 84a43c1c..b9262abf 100644 --- a/kernel/kapi/boot_modules/device.cpp +++ b/kernel/kapi/boot_modules/device.cpp @@ -26,14 +26,14 @@ namespace kapi::boot_modules return m_module; } - auto device::query_interface(kapi::devices::interface_id interface) -> void * + auto device::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == boot_module_signature::id) + if (facet == boot_module_signature::id) { return static_cast(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } } // namespace kapi::boot_modules \ No newline at end of file diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp index c3c9e595..2505779a 100644 --- a/kernel/kapi/devices.cpp +++ b/kernel/kapi/devices.cpp @@ -27,7 +27,7 @@ namespace kapi::devices } device_registry::init(); - interface_registry::init(); + facet_registry::init(); root_bus = kstd::make_shared(); device_registry::get().add(root_bus); @@ -49,7 +49,7 @@ namespace kapi::test_support::devices auto deinit() -> void { deinit_driver_registry(); - deinit_interface_registry(); + deinit_facet_registry(); deinit_device_registry(); kapi::devices::root_bus.reset(); diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp index a9bba4fb..9eecced0 100644 --- a/kernel/kapi/devices/bus.cpp +++ b/kernel/kapi/devices/bus.cpp @@ -37,19 +37,14 @@ namespace kapi::devices return {m_devices.data(), m_devices.size()}; } - auto bus::protocol() -> struct bus_protocol * + auto bus::query_facet(kapi::capabilities::facet_id facet) -> void * { - return nullptr; - } - - auto bus::query_interface(interface_id interface) -> void * - { - if (interface == bus::id) + if (facet == bus::id) { return this; } - return device::query_interface(interface); + return device::query_facet(facet); } } // namespace kapi::devices \ No newline at end of file diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp index 01096165..2628e4f4 100644 --- a/kernel/kapi/devices/device.cpp +++ b/kernel/kapi/devices/device.cpp @@ -12,19 +12,19 @@ namespace kapi::devices : m_name(name) {} - auto device::as(interface_id interface) noexcept -> void * + auto device::facet(kapi::capabilities::facet_id facet) noexcept -> void * { - return query_interface(interface); + return query_facet(facet); } - auto device::as(interface_id interface) const noexcept -> void const * + auto device::facet(kapi::capabilities::facet_id facet) const noexcept -> void const * { - return const_cast(this)->query_interface(interface); + return const_cast(this)->query_facet(facet); } - auto device::is_a(interface_id interface) const noexcept -> bool + auto device::has_facet(kapi::capabilities::facet_id facet) const noexcept -> bool { - return const_cast(this)->query_interface(interface) != nullptr; + return const_cast(this)->query_facet(facet) != nullptr; } auto device::name() const -> kstd::string const & @@ -67,7 +67,7 @@ namespace kapi::devices m_driver_data = data; } - auto device::query_interface(interface_id) -> void * + auto device::query_facet(kapi::capabilities::facet_id) -> void * { return nullptr; } diff --git a/kernel/kapi/devices/driver.cpp b/kernel/kapi/devices/driver.cpp index be2866f0..55b7507b 100644 --- a/kernel/kapi/devices/driver.cpp +++ b/kernel/kapi/devices/driver.cpp @@ -11,7 +11,7 @@ namespace kapi::devices return std::nullopt; } - auto driver::query_interface(interface_id) -> void * + auto driver::query_facet(kapi::capabilities::facet_id) -> void * { return nullptr; } diff --git a/kernel/kapi/devices/driver.tests.cpp b/kernel/kapi/devices/driver.tests.cpp index e65e48e0..560cc1bc 100644 --- a/kernel/kapi/devices/driver.tests.cpp +++ b/kernel/kapi/devices/driver.tests.cpp @@ -16,39 +16,49 @@ namespace { struct controller_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_controller_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_identification"}; virtual ~controller_identification() = default; [[nodiscard]] virtual auto controller_name() const -> std::string_view = 0; }; struct controller_driver_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_controller_driver_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_driver_identification"}; virtual ~controller_driver_identification() = default; [[nodiscard]] virtual auto supported_names() const -> std::span = 0; }; - struct controller_bus final : kapi::devices::bus, kapi::devices::bus_protocol + struct controller_protocol : kapi::devices::bus_protocol { - using kapi::devices::bus::bus; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_protocol"}; auto enumerate(kapi::devices::bus &) -> void override {} [[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const -> kstd::result override { - auto const * ident = dev.as(); - auto const * claims = drv.as(); + auto const * ident = dev.facet(); + auto const * claims = drv.facet(); if (!ident || !claims || !std::ranges::contains(claims->supported_names(), ident->controller_name())) { return kstd::failure(kapi::devices::driver_match_errc::no_match); } return 0u; } + } constinit controller_protocol_instance{}; + + struct controller_bus final : kapi::devices::bus + { + using kapi::devices::bus::bus; - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override { - return this; + if (id == controller_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &controller_protocol_instance; + } + + return kapi::devices::bus::query_facet(id); } }; @@ -64,26 +74,26 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == controller_identification::id) + if (facet == controller_identification::id) { return static_cast(this); } - return kapi::devices::bus::query_interface(interface); + return kapi::devices::bus::query_facet(facet); } }; struct leaf_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_leaf_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_identification"}; virtual ~leaf_identification() = default; [[nodiscard]] virtual auto leaf_name() const -> std::string_view = 0; }; struct leaf_driver_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_leaf_driver_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_driver_identification"}; virtual ~leaf_driver_identification() = default; [[nodiscard]] virtual auto supported_names() const -> std::span = 0; }; @@ -100,19 +110,19 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == leaf_identification::id) + if (facet == leaf_identification::id) { return static_cast(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } }; - struct leaf_bus final : kapi::devices::bus, kapi::devices::bus_protocol + struct leaf_protocol final : kapi::devices::bus_protocol { - using kapi::devices::bus::bus; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_protocol"}; auto enumerate(kapi::devices::bus & self) -> void override { @@ -122,18 +132,28 @@ namespace [[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const -> kstd::result override { - auto const * ident = dev.as(); - auto const * claims = drv.as(); + auto const * ident = dev.facet(); + auto const * claims = drv.facet(); if (!ident || !claims || !std::ranges::contains(claims->supported_names(), ident->leaf_name())) { return kstd::failure(kapi::devices::driver_match_errc::no_match); } return 0u; } + } constinit leaf_protocol_instance{}; + + struct leaf_bus final : kapi::devices::bus + { + using kapi::devices::bus::bus; - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override { - return this; + if (id == leaf_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &leaf_protocol_instance; + } + + return kapi::devices::bus::query_facet(id); } }; @@ -144,7 +164,7 @@ namespace auto self_as_bus = kstd::static_pointer_cast(dev.shared_from_this()); auto leaf = kstd::make_shared("stacking_test_leaf_bus"); self_as_bus->add_child(leaf); - leaf->enumerate(*leaf); + leaf->facet()->enumerate(*leaf); return kstd::success(); } @@ -163,14 +183,14 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == controller_driver_identification::id) + if (facet == controller_driver_identification::id) { return static_cast(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } }; @@ -195,14 +215,14 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == leaf_driver_identification::id) + if (facet == leaf_driver_identification::id) { return static_cast(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } }; } // namespace diff --git a/kernel/kapi/devices/driver_registry.cpp b/kernel/kapi/devices/driver_registry.cpp index cb101d27..842dbc1d 100644 --- a/kernel/kapi/devices/driver_registry.cpp +++ b/kernel/kapi/devices/driver_registry.cpp @@ -79,7 +79,7 @@ namespace kapi::devices } auto parent = device->parent(); - auto protocol = parent ? parent->protocol() : nullptr; + auto protocol = parent ? parent->facet() : nullptr; if (!protocol) { return; diff --git a/kernel/kapi/devices/driver_registry.tests.cpp b/kernel/kapi/devices/driver_registry.tests.cpp index d4d8a174..c7d1744d 100644 --- a/kernel/kapi/devices/driver_registry.tests.cpp +++ b/kernel/kapi/devices/driver_registry.tests.cpp @@ -15,7 +15,7 @@ namespace struct test_identification { - constexpr auto static id = kapi::devices::interface_id{"test_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"test_identification"}; virtual ~test_identification() = default; @@ -25,6 +25,8 @@ namespace struct test_protocol final : kapi::devices::bus_protocol { + constexpr auto static id = kapi::capabilities::facet_id{"test_protocol"}; + explicit test_protocol(unsigned * match_calls) : match_calls{match_calls} {} @@ -36,7 +38,7 @@ namespace { ++*match_calls; - auto const * identification = driver.as(); + auto const * identification = driver.facet(); if (!identification) { return kstd::failure(kapi::devices::driver_match_errc::no_match); @@ -52,9 +54,14 @@ namespace { using kapi::devices::bus::bus; - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override { - return &bus_protocol; + if (id == test_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &bus_protocol; + } + + return kapi::devices::bus::query_facet(id); } unsigned match_calls{}; @@ -106,14 +113,14 @@ namespace mutable unsigned probe_calls; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == test_identification::id) + if (facet == test_identification::id) { return static_cast(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } private: diff --git a/kernel/kapi/devices/facet_registry.cpp b/kernel/kapi/devices/facet_registry.cpp new file mode 100644 index 00000000..4aeebfc1 --- /dev/null +++ b/kernel/kapi/devices/facet_registry.cpp @@ -0,0 +1,216 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace kapi::devices +{ + + namespace + { + constinit auto static registry = std::optional{}; + } + + auto facet_registry::init() -> void + { + if (registry.has_value()) + { + system::panic("[kernel] Device facet registry has already been initialized."); + } + + registry.emplace(); + } + + auto facet_registry::get() -> facet_registry & + { + if (!registry) + { + system::panic("[kernel] Device facet registry has not been initialized."); + } + + return *registry; + } + + auto facet_registry::do_publish(kstd::shared_ptr device, kstd::string name, kapi::capabilities::facet_id id, + void * facet) -> kstd::result + { + // TODO: lock registry + + erase_if(m_entries, [id](auto e) { return e.id() == id && !e.device(); }); + + if (!device || !facet || name.empty()) + { + return kstd::failure(make_error_code(kstd::errc::invalid_argument)); + } + + auto already_published = std::ranges::any_of( + m_entries, [&](auto const & entry) { return entry.id() == id && entry.device().get() == device.get(); }); + + if (already_published) + { + return kstd::failure(make_error_code(kstd::errc::file_exists)); + } + + auto & published = m_entries.emplace_back(device, std::move(name), id, facet); + + do_notify_published(id, published); + + return kstd::success(); + } + + auto facet_registry::do_notify_published(kapi::capabilities::facet_id id, entry const & published) -> void + { + std::ranges::for_each(m_observers, [&](auto observer) { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_facet_published(id, published); + } + }); + + std::ranges::for_each(m_static_observers, [&](auto observer) { observer->on_facet_published(id, published); }); + } + + auto facet_registry::do_notify_withdrawn(kapi::capabilities::facet_id id, device const & device) -> void + { + std::ranges::for_each(m_observers, [&](auto observer) { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_facet_withdrawn(id, const_cast(device)); + } + }); + + std::ranges::for_each(m_static_observers, [&](auto observer) { + observer->on_facet_withdrawn(id, const_cast(device)); + }); + } + + auto facet_registry::withdraw(device const & device, kapi::capabilities::facet_id id) -> void + { + // TODO: lock registry + + auto did_remove = erase_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + return e.id() == id && locked_device && locked_device.get() == &device; + }) != 0; + + if (did_remove) + { + do_notify_withdrawn(id, device); + } + } + + auto facet_registry::withdraw_all_for(device const & device) -> void + { + // TODO: lock registry + + auto withdrawn_facets = kstd::vector{}; + + erase_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + auto do_erase = locked_device && locked_device.get() == &device; + if (do_erase) + { + withdrawn_facets.push_back(e.id()); + } + return do_erase; + }); + + std::ranges::for_each(withdrawn_facets, [&](auto facet) { do_notify_withdrawn(facet, device); }); + } + + auto facet_registry::all(kapi::capabilities::facet_id id) const -> kstd::vector + { + // TODO: lock registry + + auto filtered = m_entries; + erase_if(filtered, [&](auto e) { + auto locked_device = e.device(); + return !(e.id() == id && locked_device); + }); + return filtered; + } + + auto facet_registry::resolve(kapi::capabilities::facet_id id, std::string_view name) -> void * + { + // TODO: lock registry + + auto found = std::ranges::find_if(m_entries, [&](auto e) { return e.name() == name && e.device(); }); + + if (found == m_entries.cend()) + { + return nullptr; + } + else if (auto device = found->device()) + { + return resolve(id, *device); + } + + return nullptr; + } + + auto facet_registry::resolve(kapi::capabilities::facet_id id, device & device) -> void * + { + // TODO: lock registry + + if (auto by_device = device.facet(id)) + { + return by_device; + } + + auto found = std::ranges::find_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + return e.id() == id && locked_device && locked_device.get() == &device; + }); + + if (found == m_entries.cend()) + { + return nullptr; + } + + return found->untyped_facet(); + } + + auto facet_registry::subscribe(kstd::weak_ptr observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); + m_observers.push_back(observer); + } + + auto facet_registry::subscribe(facet_registry_observer & observer) -> void + { + // TODO: lock registry + + m_static_observers.push_back(&observer); + } + + auto facet_registry::unsubscribe(facet_registry_observer & observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [&](auto const & subscribed) { return subscribed.lock().get() == &observer; }); + erase(m_static_observers, &observer); + } + +} // namespace kapi::devices + +namespace kapi::test_support::devices +{ + auto deinit_facet_registry() -> void + { + kapi::devices::registry.reset(); + } +} // namespace kapi::test_support::devices diff --git a/kernel/kapi/devices/facet_registry.tests.cpp b/kernel/kapi/devices/facet_registry.tests.cpp new file mode 100644 index 00000000..4ad3f763 --- /dev/null +++ b/kernel/kapi/devices/facet_registry.tests.cpp @@ -0,0 +1,327 @@ +#include + +#include + +#include + +#include + +namespace +{ + struct probe_device + { + constexpr auto static id = kapi::capabilities::facet_id{"probe"}; + + virtual ~probe_device() = default; + + [[nodiscard]] auto virtual get_value() const noexcept -> int = 0; + }; + + struct const_device + { + constexpr auto static id = kapi::capabilities::facet_id{"flip"}; + + virtual ~const_device() = default; + + [[nodiscard]] auto get_constant() const noexcept -> int + { + return 0; + } + }; + + struct unimplemented_device + { + constexpr auto static id = kapi::capabilities::facet_id{"unimplemented"}; + + virtual ~unimplemented_device() = default; + }; + + struct test_device final : kapi::devices::device, probe_device + { + explicit test_device(int value, const_device & const_device) + : device{"probeable"} + , m_value{value} + , m_const_device{&const_device} + {} + + [[nodiscard]] constexpr auto get_value() const noexcept -> int override + { + return m_value; + } + + auto query_facet(kapi::capabilities::facet_id facet) -> void * override + { + if (facet == probe_device::id) + { + return static_cast(this); + } + if (facet == const_device::id) + { + return m_const_device; + } + + return kapi::devices::device::query_facet(facet); + } + + private: + int m_value; + const_device * m_const_device; + }; + + struct counting_observer final : kapi::devices::facet_registry_observer + { + auto on_facet_published(kapi::capabilities::facet_id, kapi::devices::facet_registry::entry const &) -> void override + { + ++published; + } + + auto on_facet_withdrawn(kapi::capabilities::facet_id, kapi::devices::device &) -> void override + { + ++withdrawn; + } + + std::size_t published{}; + std::size_t withdrawn{}; + }; + + struct evil_observer final : kapi::devices::facet_registry_observer + { + explicit evil_observer(kstd::shared_ptr & victim) + : m_victim{victim} + {} + + auto on_facet_published(kapi::capabilities::facet_id, kapi::devices::facet_registry::entry const &) -> void override + { + m_victim.reset(); + } + + auto on_facet_withdrawn(kapi::capabilities::facet_id, kapi::devices::device &) -> void override + { + m_victim.reset(); + } + + private: + kstd::shared_ptr & m_victim; // NOLINT + }; + +} // namespace + +SCENARIO("Publishing and finding a device", "[kapi][devices][facet_registry]") +{ + GIVEN("An empty registry, a device, and a facet the device implements by inheritance") + { + auto registry = kapi::devices::facet_registry{}; + auto free_standing_facet = const_device{}; + auto device = kstd::make_shared(128, free_standing_facet); + + THEN("Publishing an facet without a name fails") + { + REQUIRE_FALSE(registry.publish(device, "")); + } + + WHEN("publishing the facet for the device") + { + CHECK(device->has_facet()); + CHECK(device->has_facet()); + auto published = registry.publish(device, "probe0", device->facet()); + + THEN("publishing is successful") + { + REQUIRE(published); + } + + THEN("publishing the same device and facet with a different name fails") + { + REQUIRE_FALSE(registry.publish(device, "probe1", device->facet())); + } + + THEN("publishing a second facet for the same device succeeds") + { + REQUIRE(registry.publish(device, "probe0")); + } + + THEN("publishing a free standing second facet for the same device succeeds") + { + REQUIRE(registry.publish(device, "probe0", &free_standing_facet)); + } + + AND_WHEN("getting all devices implementing that facet") + { + auto probeable_devices = registry.all(probe_device::id); + + THEN("there is exactly one such device") + { + REQUIRE(probeable_devices.size() == 1); + } + + THEN("the name of the device is 'probe0'") + { + REQUIRE(probeable_devices[0].name() == "probe0"); + } + + THEN("the returned device pointer is valid") + { + REQUIRE(probeable_devices[0].device()); + } + + THEN("the returned implementation equals the result of device::as") + { + REQUIRE(probeable_devices[0].untyped_facet() == device->facet()); + } + + THEN("the facet provided function can be invoked") + { + auto implementation = probeable_devices[0].facet(); + REQUIRE(implementation->get_value() == device->get_value()); + } + } + + THEN("resolve finds the published capability by name") + { + REQUIRE(registry.resolve("probe0")); + } + + THEN("resolve finds a capability the device implements but never published") + { + REQUIRE(registry.resolve("probe0")); + } + + THEN("resolve for a capability the device implements nowhere at all does not find anything") + { + REQUIRE_FALSE(registry.resolve("probe0")); + } + + THEN("resolve for an unpublished device does not find a device") + { + REQUIRE_FALSE(registry.resolve("probe1")); + } + + THEN("withdrawing an facet for a device removes it from the registry") + { + registry.withdraw(*device, probe_device::id); + REQUIRE_FALSE(registry.resolve("probe0")); + } + } + + WHEN("the device is destroyed without withdrawing it") + { + CHECK(registry.publish(device, "probe0", device->facet())); + device.reset(); + + THEN("querying all does no longer report it") + { + REQUIRE(registry.all(probe_device::id).empty()); + } + + THEN("resolve() no longer finds it") + { + REQUIRE_FALSE(registry.resolve("probe0")); + } + } + } + + GIVEN("no device has ever been published") + { + auto registry = kapi::devices::facet_registry{}; + + THEN("all() returns an empty vector") + { + REQUIRE(registry.all(probe_device::id).empty()); + } + } + + GIVEN("a null device") + { + auto registry = kapi::devices::facet_registry{}; + auto device = kstd::shared_ptr{}; + auto facet = const_device{}; + + THEN("publishing the facet for the device fails") + { + REQUIRE_FALSE(registry.publish(device, "probe0", &facet)); + } + } +} + +SCENARIO("facet registry notifies subscribers", "[kapi][devices][facet_registry]") +{ + GIVEN("a device and a subscribed observer") + { + auto registry = kapi::devices::facet_registry{}; + auto free_standing_facet = const_device{}; + auto device = kstd::make_shared(128, free_standing_facet); + auto observer = kstd::make_shared(); + + registry.subscribe(observer); + + WHEN("an facet is published for the device") + { + CHECK(registry.publish(device, "probe0", device->facet())); + + THEN("the observer is notified exactly once") + { + REQUIRE(observer->published == 1); + REQUIRE(observer->withdrawn == 0); + } + } + + WHEN("an facet is published and then withdrawn") + { + CHECK(registry.publish(device, "probe0", device->facet())); + registry.withdraw(*device, probe_device::id); + + THEN("the observer is notified of both exactly one") + { + REQUIRE(observer->published == 1); + REQUIRE(observer->withdrawn == 1); + } + } + + WHEN("the observer is destroyed before anything is published") + { + observer.reset(); + + THEN("publishing afterward does not crash") + { + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet())); + } + } + + WHEN("the observer unsubscribes before anything is published") + { + registry.unsubscribe(*observer); + + THEN("publishing afterward does not crash") + { + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet())); + } + + THEN("the subscriber is not notified") + { + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet())); + REQUIRE_NOTHROW(registry.withdraw(*device, probe_device::id)); + REQUIRE(observer->published == 0); + REQUIRE(observer->withdrawn == 0); + } + } + } + + GIVEN("two subscriber, the first destroying the second") + { + auto registry = kapi::devices::facet_registry{}; + auto free_standing_facet = const_device{}; + auto device = kstd::make_shared(128, free_standing_facet); + + auto second = kstd::make_shared(); + auto first = kstd::make_shared(second); + + registry.subscribe(first); + registry.subscribe(second); + + THEN("publishing an facet does not crash") + { + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet())); + REQUIRE(second == nullptr); + } + } +} \ No newline at end of file diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp deleted file mode 100644 index 1d456b30..00000000 --- a/kernel/kapi/devices/interface_registry.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace kapi::devices -{ - - namespace - { - constinit auto static registry = std::optional{}; - } - - auto interface_registry::init() -> void - { - if (registry.has_value()) - { - system::panic("[kernel] Device interface registry has already been initialized."); - } - - registry.emplace(); - } - - auto interface_registry::get() -> interface_registry & - { - if (!registry) - { - system::panic("[kernel] Device interface registry has not been initialized."); - } - - return *registry; - } - - auto interface_registry::do_publish(kstd::shared_ptr device, kstd::string name, interface_id interface, - void * implementation) -> kstd::result - { - // TODO: lock registry - - erase_if(m_entries, [interface](auto e) { return e.interface() == interface && !e.device(); }); - - if (!device || !implementation || name.empty()) - { - return kstd::failure(make_error_code(kstd::errc::invalid_argument)); - } - - auto already_published = std::ranges::any_of(m_entries, [&](auto const & entry) { - return entry.interface() == interface && entry.device().get() == device.get(); - }); - - if (already_published) - { - return kstd::failure(make_error_code(kstd::errc::file_exists)); - } - - auto & published = m_entries.emplace_back(device, std::move(name), interface, implementation); - - do_notify_published(interface, published); - - return kstd::success(); - } - - auto interface_registry::do_notify_published(interface_id interface, entry const & published) -> void - { - std::ranges::for_each(m_observers, [&](auto observer) { - if (auto locked_observer = observer.lock()) - { - locked_observer->on_interface_published(interface, published); - } - }); - - std::ranges::for_each(m_static_observers, - [&](auto observer) { observer->on_interface_published(interface, published); }); - } - - auto interface_registry::do_notify_withdrawn(interface_id interface, device const & device) -> void - { - std::ranges::for_each(m_observers, [&](auto observer) { - if (auto locked_observer = observer.lock()) - { - locked_observer->on_interface_withdrawn(interface, const_cast(device)); - } - }); - - std::ranges::for_each(m_static_observers, [&](auto observer) { - observer->on_interface_withdrawn(interface, const_cast(device)); - }); - } - - auto interface_registry::withdraw(device const & device, interface_id interface) -> void - { - // TODO: lock registry - - auto did_remove = erase_if(m_entries, [&](auto e) { - auto locked_device = e.device(); - return e.interface() == interface && locked_device && locked_device.get() == &device; - }) != 0; - - if (did_remove) - { - do_notify_withdrawn(interface, device); - } - } - - auto interface_registry::withdraw_all_for(device const & device) -> void - { - // TODO: lock registry - - auto withdrawn_interfaces = kstd::vector{}; - - erase_if(m_entries, [&](auto e) { - auto locked_device = e.device(); - auto do_erase = locked_device && locked_device.get() == &device; - if (do_erase) - { - withdrawn_interfaces.push_back(e.interface()); - } - return do_erase; - }); - - std::ranges::for_each(withdrawn_interfaces, [&](auto interface) { do_notify_withdrawn(interface, device); }); - } - - auto interface_registry::all(interface_id interface) const -> kstd::vector - { - // TODO: lock registry - - auto filtered = m_entries; - erase_if(filtered, [&](auto e) { - auto locked_device = e.device(); - return !(e.interface() == interface && locked_device); - }); - return filtered; - } - - auto interface_registry::resolve(interface_id interface, std::string_view name) -> void * - { - // TODO: lock registry - - auto found = std::ranges::find_if(m_entries, [&](auto e) { return e.name() == name && e.device(); }); - - if (found == m_entries.cend()) - { - return nullptr; - } - else if (auto device = found->device()) - { - return resolve(interface, *device); - } - - return nullptr; - } - - auto interface_registry::resolve(interface_id interface, device & device) -> void * - { - // TODO: lock registry - - if (auto by_device = device.as(interface)) - { - return by_device; - } - - auto found = std::ranges::find_if(m_entries, [&](auto e) { - auto locked_device = e.device(); - return e.interface() == interface && locked_device && locked_device.get() == &device; - }); - - if (found == m_entries.cend()) - { - return nullptr; - } - - return found->implementation(); - } - - auto interface_registry::subscribe(kstd::weak_ptr observer) -> void - { - // TODO: lock registry - - erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); - m_observers.push_back(observer); - } - - auto interface_registry::subscribe(interface_registry_observer & observer) -> void - { - // TODO: lock registry - - m_static_observers.push_back(&observer); - } - - auto interface_registry::unsubscribe(interface_registry_observer & observer) -> void - { - // TODO: lock registry - - erase_if(m_observers, [&](auto const & subscribed) { return subscribed.lock().get() == &observer; }); - erase(m_static_observers, &observer); - } - -} // namespace kapi::devices - -namespace kapi::test_support::devices -{ - auto deinit_interface_registry() -> void - { - kapi::devices::registry.reset(); - } -} // namespace kapi::test_support::devices diff --git a/kernel/kapi/devices/interface_registry.tests.cpp b/kernel/kapi/devices/interface_registry.tests.cpp deleted file mode 100644 index 071b9a6d..00000000 --- a/kernel/kapi/devices/interface_registry.tests.cpp +++ /dev/null @@ -1,329 +0,0 @@ -#include - -#include - -#include - -#include - -namespace -{ - struct probe_device - { - constexpr auto static id = kapi::devices::interface_id{"probe"}; - - virtual ~probe_device() = default; - - [[nodiscard]] auto virtual get_value() const noexcept -> int = 0; - }; - - struct const_device - { - constexpr auto static id = kapi::devices::interface_id{"flip"}; - - virtual ~const_device() = default; - - [[nodiscard]] auto get_constant() const noexcept -> int - { - return 0; - } - }; - - struct unimplemented_device - { - constexpr auto static id = kapi::devices::interface_id{"unimplemented"}; - - virtual ~unimplemented_device() = default; - }; - - struct test_device final : kapi::devices::device, probe_device - { - explicit test_device(int value, const_device & const_device) - : device{"probeable"} - , m_value{value} - , m_const_device{&const_device} - {} - - [[nodiscard]] constexpr auto get_value() const noexcept -> int override - { - return m_value; - } - - auto query_interface(kapi::devices::interface_id interface) -> void * override - { - if (interface == probe_device::id) - { - return static_cast(this); - } - if (interface == const_device::id) - { - return m_const_device; - } - - return kapi::devices::device::query_interface(interface); - } - - private: - int m_value; - const_device * m_const_device; - }; - - struct counting_observer final : kapi::devices::interface_registry_observer - { - auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &) - -> void override - { - ++published; - } - - auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override - { - ++withdrawn; - } - - std::size_t published{}; - std::size_t withdrawn{}; - }; - - struct evil_observer final : kapi::devices::interface_registry_observer - { - explicit evil_observer(kstd::shared_ptr & victim) - : m_victim{victim} - {} - - auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &) - -> void override - { - m_victim.reset(); - } - - auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override - { - m_victim.reset(); - } - - private: - kstd::shared_ptr & m_victim; // NOLINT - }; - -} // namespace - -SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]") -{ - GIVEN("An empty registry, a device, and an interface the device implements by inheritance") - { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared(128, free_standing_interface); - - THEN("Publishing an interface without a name fails") - { - REQUIRE_FALSE(registry.publish(device, "")); - } - - WHEN("publishing the interface for the device") - { - CHECK(device->is_a()); - CHECK(device->is_a()); - auto published = registry.publish(device, "probe0", device->as()); - - THEN("publishing is successful") - { - REQUIRE(published); - } - - THEN("publishing the same device and interface with a different name fails") - { - REQUIRE_FALSE(registry.publish(device, "probe1", device->as())); - } - - THEN("publishing a second interface for the same device succeeds") - { - REQUIRE(registry.publish(device, "probe0")); - } - - THEN("publishing a free standing second interface for the same device succeeds") - { - REQUIRE(registry.publish(device, "probe0", &free_standing_interface)); - } - - AND_WHEN("getting all devices implementing that interface") - { - auto probeable_devices = registry.all(probe_device::id); - - THEN("there is exactly one such device") - { - REQUIRE(probeable_devices.size() == 1); - } - - THEN("the name of the device is 'probe0'") - { - REQUIRE(probeable_devices[0].name() == "probe0"); - } - - THEN("the returned device pointer is valid") - { - REQUIRE(probeable_devices[0].device()); - } - - THEN("the returned implementation equals the result of device::as") - { - REQUIRE(probeable_devices[0].implementation() == device->as()); - } - - THEN("the interface provided function can be invoked") - { - auto implementation = probeable_devices[0].as(); - REQUIRE(implementation->get_value() == device->get_value()); - } - } - - THEN("resolve finds the published capability by name") - { - REQUIRE(registry.resolve("probe0")); - } - - THEN("resolve finds a capability the device implements but never published") - { - REQUIRE(registry.resolve("probe0")); - } - - THEN("resolve for a capability the device implements nowhere at all does not find anything") - { - REQUIRE_FALSE(registry.resolve("probe0")); - } - - THEN("resolve for an unpublished device does not find a device") - { - REQUIRE_FALSE(registry.resolve("probe1")); - } - - THEN("withdrawing an interface for a device removes it from the registry") - { - registry.withdraw(*device, probe_device::id); - REQUIRE_FALSE(registry.resolve("probe0")); - } - } - - WHEN("the device is destroyed without withdrawing it") - { - CHECK(registry.publish(device, "probe0", device->as())); - device.reset(); - - THEN("querying all does no longer report it") - { - REQUIRE(registry.all(probe_device::id).empty()); - } - - THEN("resolve() no longer finds it") - { - REQUIRE_FALSE(registry.resolve("probe0")); - } - } - } - - GIVEN("no device has ever been published") - { - auto registry = kapi::devices::interface_registry{}; - - THEN("all() returns an empty vector") - { - REQUIRE(registry.all(probe_device::id).empty()); - } - } - - GIVEN("a null device") - { - auto registry = kapi::devices::interface_registry{}; - auto device = kstd::shared_ptr{}; - auto interface = const_device{}; - - THEN("publishing the interface for the device fails") - { - REQUIRE_FALSE(registry.publish(device, "probe0", &interface)); - } - } -} - -SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_registry]") -{ - GIVEN("a device and a subscribed observer") - { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared(128, free_standing_interface); - auto observer = kstd::make_shared(); - - registry.subscribe(observer); - - WHEN("an interface is published for the device") - { - CHECK(registry.publish(device, "probe0", device->as())); - - THEN("the observer is notified exactly once") - { - REQUIRE(observer->published == 1); - REQUIRE(observer->withdrawn == 0); - } - } - - WHEN("an interface is published and then withdrawn") - { - CHECK(registry.publish(device, "probe0", device->as())); - registry.withdraw(*device, probe_device::id); - - THEN("the observer is notified of both exactly one") - { - REQUIRE(observer->published == 1); - REQUIRE(observer->withdrawn == 1); - } - } - - WHEN("the observer is destroyed before anything is published") - { - observer.reset(); - - THEN("publishing afterward does not crash") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as())); - } - } - - WHEN("the observer unsubscribes before anything is published") - { - registry.unsubscribe(*observer); - - THEN("publishing afterward does not crash") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as())); - } - - THEN("the subscriber is not notified") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as())); - REQUIRE_NOTHROW(registry.withdraw(*device, probe_device::id)); - REQUIRE(observer->published == 0); - REQUIRE(observer->withdrawn == 0); - } - } - } - - GIVEN("two subscriber, the first destroying the second") - { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared(128, free_standing_interface); - - auto second = kstd::make_shared(); - auto first = kstd::make_shared(second); - - registry.subscribe(first); - registry.subscribe(second); - - THEN("publishing an interface does not crash") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as())); - REQUIRE(second == nullptr); - } - } -} \ No newline at end of file diff --git a/kernel/kernel/bus/boot_modules.cpp b/kernel/kernel/bus/boot_modules.cpp index 069d414f..be507eb5 100644 --- a/kernel/kernel/bus/boot_modules.cpp +++ b/kernel/kernel/bus/boot_modules.cpp @@ -29,6 +29,8 @@ namespace kernel::bus struct boot_modules_protocol : kapi::devices::bus_protocol { + constexpr auto static id = kapi::capabilities::facet_id{"boot_modules_bus"}; + auto enumerate(kapi::devices::bus &) -> void override { // The boot modules virtual bus does not support enumeration. @@ -37,8 +39,8 @@ namespace kernel::bus [[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const -> kstd::result override { - auto signature = dev.as(); - auto claim = drv.as(); + auto signature = dev.facet(); + auto claim = drv.facet(); if (!signature || !claim) { @@ -62,9 +64,14 @@ namespace kernel::bus : kapi::devices::bus{"boot_modules"} {} - auto boot_modules::protocol() -> kapi::devices::bus_protocol * + auto boot_modules::query_facet(kapi::capabilities::facet_id id) -> void * { - return &protocol_instance; + if (id == boot_modules_protocol::id || id == kapi::devices::bus_protocol::id) + { + return static_cast(&protocol_instance); + } + + return kapi::devices::bus::query_facet(id); } } // namespace kernel::bus diff --git a/kernel/kernel/bus/boot_modules.hpp b/kernel/kernel/bus/boot_modules.hpp index c73e0d74..011e2b2e 100644 --- a/kernel/kernel/bus/boot_modules.hpp +++ b/kernel/kernel/bus/boot_modules.hpp @@ -15,7 +15,7 @@ namespace kernel::bus { boot_modules(); - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override; + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override; }; } // namespace kernel::bus diff --git a/kernel/kernel/devices/storage.cpp b/kernel/kernel/devices/storage.cpp index 4f5776d2..d54e7056 100644 --- a/kernel/kernel/devices/storage.cpp +++ b/kernel/kernel/devices/storage.cpp @@ -18,7 +18,7 @@ namespace kernel::devices::storage auto determine_boot_device() -> kstd::shared_ptr { - auto block_devices = kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id); + auto block_devices = kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id); if (block_devices.empty()) { return nullptr; diff --git a/kernel/kernel/devices/storage.tests.cpp b/kernel/kernel/devices/storage.tests.cpp index 3cf21b01..46dfb5ab 100644 --- a/kernel/kernel/devices/storage.tests.cpp +++ b/kernel/kernel/devices/storage.tests.cpp @@ -29,7 +29,7 @@ TEST_CASE("Storage devices attached with init() are reachable from the root bus" bus->add_child(device); - auto block_devices = kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id); + auto block_devices = kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id); REQUIRE(block_devices.size() == 1); CHECK(block_devices[0].name() == "ram0"); diff --git a/kernel/kernel/drivers/storage/ram_disk.cpp b/kernel/kernel/drivers/storage/ram_disk.cpp index 97a6443b..987f4bbc 100644 --- a/kernel/kernel/drivers/storage/ram_disk.cpp +++ b/kernel/kernel/drivers/storage/ram_disk.cpp @@ -96,13 +96,13 @@ namespace kernel::drivers::storage auto ram_disk::probe(kapi::devices::device & device) -> kstd::result { - auto interface = device.as(); - if (!interface) + auto facet = device.facet(); + if (!facet) { return kstd::failure(make_error_code(kstd::errc::invalid_argument)); } - auto const & module = interface->module(); + auto const & module = facet->module(); if (module.start_address.raw() == 0 || module.size == 0) { return kstd::failure(make_error_code(kstd::errc::invalid_argument)); @@ -111,15 +111,15 @@ namespace kernel::drivers::storage auto implementation = kstd::make_shared(module); auto next_index = - std::ranges::count_if(kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id), + std::ranges::count_if(kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id), [this](auto const & published) { auto published_device = published.device(); return published_device && published_device->bound_driver() == this; }); auto name = kstd::format("ram{}", next_index); - auto published = kapi::devices::publish_interface(device.shared_from_this(), - name, implementation.get()); + auto published = kapi::devices::publish_facet(device.shared_from_this(), name, + implementation.get()); if (!published) { return published; @@ -132,7 +132,7 @@ namespace kernel::drivers::storage auto ram_disk::unbind(kapi::devices::device & device) -> void { - kapi::devices::interface_registry::get().withdraw(device, kapi::filesystem::block_special_file::id); + kapi::devices::facet_registry::get().withdraw(device, kapi::filesystem::block_special_file::id); device.set_driver_data(nullptr); } @@ -151,14 +151,14 @@ namespace kernel::drivers::storage return "Generic RAM Disk"; } - auto ram_disk::query_interface(kapi::devices::interface_id interface) -> void * + auto ram_disk::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == kapi::boot_modules::boot_module_claim::id) + if (facet == kapi::boot_modules::boot_module_claim::id) { return static_cast(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } } // namespace kernel::drivers::storage \ No newline at end of file diff --git a/kernel/kernel/drivers/storage/ram_disk.hpp b/kernel/kernel/drivers/storage/ram_disk.hpp index 2805466f..d5d54551 100644 --- a/kernel/kernel/drivers/storage/ram_disk.hpp +++ b/kernel/kernel/drivers/storage/ram_disk.hpp @@ -27,7 +27,7 @@ namespace kernel::drivers::storage [[nodiscard]] auto name() const noexcept -> std::string_view override; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override; + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; }; } // namespace kernel::drivers::storage diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp index ce0ad3fe..4dcff4a1 100644 --- a/kernel/kernel/filesystem/device_inode.cpp +++ b/kernel/kernel/filesystem/device_inode.cpp @@ -42,7 +42,7 @@ namespace kernel::filesystem -> kstd::result { if (auto block_device = - kapi::devices::interface_registry::get().resolve(*m_device)) + kapi::devices::facet_registry::get().resolve(*m_device)) { return devices::block_device_utils::read(*block_device, buffer, offset, size); } @@ -54,7 +54,7 @@ namespace kernel::filesystem -> kstd::result { if (auto block_device = - kapi::devices::interface_registry::get().resolve(*m_device)) + kapi::devices::facet_registry::get().resolve(*m_device)) { return devices::block_device_utils::write(*block_device, buffer, offset, size); } diff --git a/kernel/kernel/filesystem/device_inode.tests.cpp b/kernel/kernel/filesystem/device_inode.tests.cpp index 5f409a79..59800531 100644 --- a/kernel/kernel/filesystem/device_inode.tests.cpp +++ b/kernel/kernel/filesystem/device_inode.tests.cpp @@ -172,7 +172,7 @@ SCENARIO("Device inode raw_device()", "[filesystem][device-inode]") CHECK(kernel::tests::devices::bind(*device, std::uint8_t{1})); - REQUIRE(kapi::devices::interface_registry::get().publish(device, "ram0")); + REQUIRE(kapi::devices::facet_registry::get().publish(device, "ram0")); auto inode = kernel::filesystem::device_inode{device}; diff --git a/kernel/kernel/filesystem/device_number_registry.cpp b/kernel/kernel/filesystem/device_number_registry.cpp index aca0c64c..d51a343a 100644 --- a/kernel/kernel/filesystem/device_number_registry.cpp +++ b/kernel/kernel/filesystem/device_number_registry.cpp @@ -29,28 +29,28 @@ namespace kernel::filesystem { if (!instance) { - instance.emplace(kapi::devices::interface_registry::get()); + instance.emplace(kapi::devices::facet_registry::get()); } return *instance; } - device_number_registry::device_number_registry(kapi::devices::interface_registry & interface_registry) - : m_interface_registry{&interface_registry} + device_number_registry::device_number_registry(kapi::devices::facet_registry & facet_registry) + : m_facet_registry{&facet_registry} { for (auto const & binding : file_type_bindings) { - for (auto const & published : interface_registry.all(binding.interface)) + for (auto const & published : facet_registry.all(binding.facet)) { - try_number(binding.interface, published); + try_number(binding.facet, published); } } - m_interface_registry->subscribe(*this); + m_facet_registry->subscribe(*this); } device_number_registry::~device_number_registry() { - m_interface_registry->unsubscribe(*this); + m_facet_registry->unsubscribe(*this); } auto device_number_registry::resolve(kapi::filesystem::device_number number, file_type type) const @@ -114,19 +114,18 @@ namespace kernel::filesystem m_observers.push_back(std::move(observer)); } - auto device_number_registry::on_interface_published(kapi::devices::interface_id interface, - kapi::devices::interface_registry::entry const & published) - -> void + auto device_number_registry::on_facet_published(kapi::capabilities::facet_id facet, + kapi::devices::facet_registry::entry const & published) -> void { - try_number(interface, published); + try_number(facet, published); } - auto device_number_registry::on_interface_withdrawn(kapi::devices::interface_id interface, - kapi::devices::device & device) -> void + auto device_number_registry::on_facet_withdrawn(kapi::capabilities::facet_id facet, kapi::devices::device & device) + -> void { - // Check if there even is a binding defined for the given interface. + // Check if there even is a binding defined for the given facet. auto binding = - std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); + std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.facet == facet; }); if (binding == std::ranges::cend(file_type_bindings)) { return; @@ -158,12 +157,12 @@ namespace kernel::filesystem }); } - auto device_number_registry::try_number(kapi::devices::interface_id interface, - kapi::devices::interface_registry::entry const & published) -> void + auto device_number_registry::try_number(kapi::capabilities::facet_id facet, + kapi::devices::facet_registry::entry const & published) -> void { - // Check if there even is a binding defined for the given interface. + // Check if there even is a binding defined for the given facet. auto binding = - std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); + std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.facet == facet; }); if (binding == std::ranges::cend(file_type_bindings)) { return; diff --git a/kernel/kernel/filesystem/device_number_registry.hpp b/kernel/kernel/filesystem/device_number_registry.hpp index 20a26c22..8ace3727 100644 --- a/kernel/kernel/filesystem/device_number_registry.hpp +++ b/kernel/kernel/filesystem/device_number_registry.hpp @@ -20,7 +20,7 @@ namespace kernel::filesystem struct device_number_registry_observer; //! A registry to assign stable device numbers to published devices. - struct device_number_registry final : kapi::devices::interface_registry_observer + struct device_number_registry final : kapi::devices::facet_registry_observer { //! A single numbered device. //! @@ -33,10 +33,10 @@ namespace kernel::filesystem kstd::weak_ptr device; }; - //! Construct a new device number registry, subscribing to the given interface registry. + //! Construct a new device number registry, subscribing to the given facet registry. //! - //! @param interface_registry The interface registry to back this device number registry. - explicit device_number_registry(kapi::devices::interface_registry & interface_registry); + //! @param facet_registry The facet registry to back this device number registry. + explicit device_number_registry(kapi::devices::facet_registry & facet_registry); //! Destroy this registry. ~device_number_registry() override; @@ -78,21 +78,20 @@ namespace kernel::filesystem auto subscribe(kstd::weak_ptr observer) -> void; private: - auto on_interface_published(kapi::devices::interface_id interface, - kapi::devices::interface_registry::entry const & entry) -> void override; + auto on_facet_published(kapi::capabilities::facet_id facet, kapi::devices::facet_registry::entry const & entry) + -> void override; - auto on_interface_withdrawn(kapi::devices::interface_id interface, kapi::devices::device & device) -> void override; + auto on_facet_withdrawn(kapi::capabilities::facet_id facet, kapi::devices::device & device) -> void override; - auto try_number(kapi::devices::interface_id interface, kapi::devices::interface_registry::entry const & published) - -> void; + auto try_number(kapi::capabilities::facet_id facet, kapi::devices::facet_registry::entry const & published) -> void; - kstd::observer_ptr m_interface_registry; + kstd::observer_ptr m_facet_registry; mutable kstd::vector m_entries{}; kstd::flat_map m_next_minor; kstd::vector> m_observers{}; }; - //! The interface for types interested in observing numbering transactions on a device number registry. + //! The facet for types interested in observing numbering transactions on a device number registry. struct device_number_registry_observer { //! Enable correct destruction through base pointers. diff --git a/kernel/kernel/filesystem/device_number_registry.tests.cpp b/kernel/kernel/filesystem/device_number_registry.tests.cpp index 3791a16e..865a6de9 100644 --- a/kernel/kernel/filesystem/device_number_registry.tests.cpp +++ b/kernel/kernel/filesystem/device_number_registry.tests.cpp @@ -22,13 +22,13 @@ using namespace kstd::units_literals; namespace { - auto make_bound_block_device(kapi::devices::interface_registry & interfaces, kstd::string const & name, + auto make_bound_block_device(kapi::devices::facet_registry & facets, kstd::string const & name, kstd::units::bytes block_size, std::optional major) -> kstd::shared_ptr { auto device = kstd::make_shared(name, block_size); [[maybe_unused]] auto driver = kernel::tests::devices::bind(*device, major); - if (!interfaces.publish(device, name)) + if (!facets.publish(device, name)) { throw std::runtime_error{"failed to publish block device!"}; } @@ -39,8 +39,8 @@ namespace SCENARIO("Device number registry resolves and numbers published block devices", "[kernel][filesystem][device_number_registry]") { - auto interfaces = kapi::devices::interface_registry{}; - auto registry = kernel::filesystem::device_number_registry{interfaces}; + auto facets = kapi::devices::facet_registry{}; + auto registry = kernel::filesystem::device_number_registry{facets}; GIVEN("No devices have been published") { @@ -52,7 +52,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A single block device has been published, bound to a driver claiming major 1") { - auto device = make_bound_block_device(interfaces, "ram0", 512_B, std::uint8_t{1}); + auto device = make_bound_block_device(facets, "ram0", 512_B, std::uint8_t{1}); THEN("all() returns a vector with one element") { @@ -96,7 +96,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A device was published") { - auto device = make_bound_block_device(interfaces, "ram0", 512_B, std::uint8_t{1}); + auto device = make_bound_block_device(facets, "ram0", 512_B, std::uint8_t{1}); auto number = registry.number_of(*device); WHEN("destroying it with no further owner") @@ -112,8 +112,8 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("Two block-capable drivers claiming different majors") { - [[maybe_unused]] auto device_a = make_bound_block_device(interfaces, "ramA0", 512_B, std::uint8_t{1}); - [[maybe_unused]] auto device_b = make_bound_block_device(interfaces, "ramB0", 512_B, std::uint8_t{2}); + [[maybe_unused]] auto device_a = make_bound_block_device(facets, "ramA0", 512_B, std::uint8_t{1}); + [[maybe_unused]] auto device_b = make_bound_block_device(facets, "ramB0", 512_B, std::uint8_t{2}); THEN("their minors are numbered independently, starting at 0 for each driver") { @@ -134,7 +134,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A driver that never overrides claimed_major()") { - make_bound_block_device(interfaces, "unnumbered0", 512_B, std::nullopt); + make_bound_block_device(facets, "unnumbered0", 512_B, std::nullopt); THEN("it is never numbered, regardless of what it publishes") { @@ -145,7 +145,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A published device with no bound driver at all") { auto device = kstd::make_shared("unbound0", 512_B); - CHECK(interfaces.publish(device, "unbound0")); + CHECK(facets.publish(device, "unbound0")); THEN("it is never numbered") { diff --git a/kernel/kernel/filesystem/file_type_bindings.hpp b/kernel/kernel/filesystem/file_type_bindings.hpp index d771f49c..ea52972b 100644 --- a/kernel/kernel/filesystem/file_type_bindings.hpp +++ b/kernel/kernel/filesystem/file_type_bindings.hpp @@ -11,16 +11,16 @@ namespace kernel::filesystem { - //! A binding between an interface, a posix special file type + //! A binding between a facet, a posix special file type struct file_type_binding // NOLINT(cppcoreguidelines-pro-type-member-init) { - kapi::filesystem::interface_id interface; + kapi::capabilities::facet_id facet; file_type posix_type; }; - //! Predefined bindings for interface + file type + //! Predefined bindings for facet + file type //! - //! This array associates published interfaces with files types. + //! This array associates published facets with files types. constexpr auto inline file_type_bindings = std::array{ file_type_binding{kapi::filesystem::block_special_file::id, file_type::block}, }; diff --git a/kernel/kernel/test_support/devices/block_device.cpp b/kernel/kernel/test_support/devices/block_device.cpp index 2cde621c..a92b095b 100644 --- a/kernel/kernel/test_support/devices/block_device.cpp +++ b/kernel/kernel/test_support/devices/block_device.cpp @@ -68,13 +68,13 @@ namespace kernel::tests::devices return kstd::units::bytes{data.size()}; } - auto block_device::query_interface(kapi::devices::interface_id interface) -> void * + auto block_device::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == kapi::filesystem::block_special_file::id) + if (facet == kapi::filesystem::block_special_file::id) { return static_cast(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } } // namespace kernel::tests::devices \ No newline at end of file diff --git a/kernel/kernel/test_support/devices/block_device.hpp b/kernel/kernel/test_support/devices/block_device.hpp index 9546b0cc..94201da1 100644 --- a/kernel/kernel/test_support/devices/block_device.hpp +++ b/kernel/kernel/test_support/devices/block_device.hpp @@ -28,7 +28,7 @@ namespace kernel::tests::devices kstd::vector data{}; private: - [[nodiscard]] auto query_interface(kapi::devices::interface_id interface) -> void * override; + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id facet) -> void * override; kstd::units::bytes m_block_size{}; }; diff --git a/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp index 3464c6e8..d5068565 100644 --- a/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp @@ -104,8 +104,7 @@ namespace kernel::tests::filesystem m_boot_module_bus->add_child(kstd::make_shared(i, module)); } - if (module_count > 0 && - kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id).empty()) + if (module_count > 0 && kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id).empty()) { throw std::runtime_error{"No RAM disk driver bound to any of the test fixture's boot modules."}; } @@ -128,7 +127,7 @@ namespace kernel::tests::filesystem } if (!module_names.empty() && - kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id).empty()) + kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id).empty()) { throw std::runtime_error{"No RAM disk driver bound to any of the test fixture's boot modules."}; } -- cgit v1.2.3