diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-23 01:38:56 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-23 01:38:56 +0200 |
| commit | 526709a1e86d55dd88e2dbdbc471795efce9046b (patch) | |
| tree | 04d9de462f506f983d3a991179eccfd68300cc14 | |
| parent | 0361a4912affe1594def1aa24e387fe5440afaee (diff) | |
| download | kernel-526709a1e86d55dd88e2dbdbc471795efce9046b.tar.xz kernel-526709a1e86d55dd88e2dbdbc471795efce9046b.zip | |
kapi: bootstrap owning device tree
| -rw-r--r-- | arch/x86_64/arch/devices/init.cpp | 8 | ||||
| -rw-r--r-- | arch/x86_64/kapi/cpu.cpp | 8 | ||||
| -rw-r--r-- | kapi/kapi/devices.hpp | 4 | ||||
| -rw-r--r-- | kapi/kapi/devices/bus.hpp | 8 | ||||
| -rw-r--r-- | kapi/kapi/devices/device.hpp | 11 | ||||
| -rw-r--r-- | kapi/kapi/devices/manager.hpp | 6 | ||||
| -rw-r--r-- | kernel/kapi/devices.cpp | 56 | ||||
| -rw-r--r-- | kernel/kapi/devices/bus.cpp | 20 | ||||
| -rw-r--r-- | kernel/kapi/devices/device.cpp | 9 |
9 files changed, 79 insertions, 51 deletions
diff --git a/arch/x86_64/arch/devices/init.cpp b/arch/x86_64/arch/devices/init.cpp index 4ac287cf..2c4fb3c3 100644 --- a/arch/x86_64/arch/devices/init.cpp +++ b/arch/x86_64/arch/devices/init.cpp @@ -62,13 +62,13 @@ namespace arch::devices { kstd::println("[x86_64:DEV] Initializing ISA bus..."); - auto isa_bus = kstd::make_unique<arch::bus::isa>(); + auto isa_bus = kstd::make_shared<arch::bus::isa>(); - auto pit = kstd::make_unique<arch::devices::legacy_pit>(pit_frequency_in_hz); + auto pit = kstd::make_shared<arch::devices::legacy_pit>(pit_frequency_in_hz); isa_bus->add_child(std::move(pit)); - auto & root_bus = kapi::devices::get_root_bus(); - root_bus.add_child(std::move(isa_bus)); + auto root_bus = kapi::devices::get_root_bus(); + root_bus->add_child(std::move(isa_bus)); } } // namespace arch::devices diff --git a/arch/x86_64/kapi/cpu.cpp b/arch/x86_64/kapi/cpu.cpp index bd86f0fa..c45703e5 100644 --- a/arch/x86_64/kapi/cpu.cpp +++ b/arch/x86_64/kapi/cpu.cpp @@ -64,19 +64,19 @@ namespace kapi::cpu auto bsp_found = false; auto core_index = 0uz; auto local_apic_address = memory::physical_address{madt->local_interrupt_controller_address()}; - auto cpu_bus = kstd::make_unique<devices::cpu>(); + auto cpu_bus = kstd::make_shared<devices::cpu>(); for (auto const & apic : lapic_entries) { auto is_bsp = !bsp_found; bsp_found = true; - auto core = kstd::make_unique<devices::cpu::core>(core_index, apic.processor_id(), is_bsp); - core->add_child(kstd::make_unique<arch::devices::local_apic>(core_index, apic.id(), local_apic_address, is_bsp)); + auto core = kstd::make_shared<devices::cpu::core>(core_index, apic.processor_id(), is_bsp); + core->add_child(kstd::make_shared<arch::devices::local_apic>(core_index, apic.id(), local_apic_address, is_bsp)); cpu_bus->add_child(std::move(core)); ++core_index; } - devices::get_root_bus().add_child(std::move(cpu_bus)); + devices::get_root_bus()->add_child(std::move(cpu_bus)); kstd::println("[x86_64:PLT] Found {} CPU cores", core_index); return core_index > 0; diff --git a/kapi/kapi/devices.hpp b/kapi/kapi/devices.hpp index e86e9ee7..5c3d1b63 100644 --- a/kapi/kapi/devices.hpp +++ b/kapi/kapi/devices.hpp @@ -29,8 +29,8 @@ namespace kapi::devices //! //! @warning This function will panic if the root bus has not been initialized. //! - //! @return a reference to the root bus. - auto get_root_bus() -> bus &; + //! @return a shared pointer to the root bus. + auto get_root_bus() -> kstd::shared_ptr<bus>; //! Publish the fact that a given device implements a given interface. //! diff --git a/kapi/kapi/devices/bus.hpp b/kapi/kapi/devices/bus.hpp index 1f433efc..6356e166 100644 --- a/kapi/kapi/devices/bus.hpp +++ b/kapi/kapi/devices/bus.hpp @@ -11,6 +11,7 @@ #include <kstd/vector.hpp> #include <atomic> +#include <span> namespace kapi::devices { @@ -36,9 +37,9 @@ namespace kapi::devices //! Whenever a device is attached to a bus, the bus takes sole ownership of the device. //! //! @param child The child device to attach. - auto add_child(kstd::unique_ptr<device> child) -> void; + auto add_child(kstd::shared_ptr<device> child) -> void; - [[nodiscard]] auto children() const -> kstd::vector<kstd::observer_ptr<device>> const &; + [[nodiscard]] auto children() const -> std::span<kstd::shared_ptr<device> const>; protected: //! Enumerate the devices on the bus. @@ -47,8 +48,7 @@ namespace kapi::devices auto virtual enumerate() -> bool; private: - kstd::vector<kstd::unique_ptr<device>> m_devices; - kstd::vector<kstd::observer_ptr<device>> m_observers; + kstd::vector<kstd::shared_ptr<device>> m_devices; std::atomic_flag m_init_was_called{}; std::atomic_flag m_initialized{}; }; diff --git a/kapi/kapi/devices/device.hpp b/kapi/kapi/devices/device.hpp index d72a6bbd..6ffd052d 100644 --- a/kapi/kapi/devices/device.hpp +++ b/kapi/kapi/devices/device.hpp @@ -17,7 +17,7 @@ namespace kapi::devices /** * @brief Base device identified by a name. */ - struct device + struct device : kstd::enable_shared_from_this<device> { /** * @brief Create a device identified by @p name. @@ -60,16 +60,21 @@ namespace kapi::devices */ [[nodiscard]] auto name() const -> kstd::string const &; + //! Get the parent bus of this device. + //! + //! @return a shared pointer to the parent bus, or nullptr if this device has no parent. + [[nodiscard]] auto parent() const -> kstd::shared_ptr<struct bus>; + protected: auto virtual query_interface(interface interface) -> void *; private: friend struct bus; - auto set_parent(kstd::observer_ptr<struct bus> parent) -> void; + auto set_parent(kstd::weak_ptr<struct bus> parent) -> void; kstd::string m_name; - kstd::observer_ptr<bus> m_parent; + kstd::weak_ptr<bus> m_parent; }; //! @} diff --git a/kapi/kapi/devices/manager.hpp b/kapi/kapi/devices/manager.hpp index 25b22510..5b620b27 100644 --- a/kapi/kapi/devices/manager.hpp +++ b/kapi/kapi/devices/manager.hpp @@ -19,7 +19,7 @@ namespace kapi::devices //! //! @param device The device to register. //! @return true if the device was registered successfully, false otherwise. - auto register_device(device & device) -> bool; + auto register_device(kstd::shared_ptr<device> device) -> bool; //! Unregister a device from the kernel's device manager. //! @@ -30,8 +30,8 @@ namespace kapi::devices //! Find a device by its name. //! //! @param name the name of the device. - //! @return a pointer to the device iff. the device was found, nullptr otherwise. - auto find_device(std::string_view name) -> kstd::observer_ptr<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>; //! @} diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp index 6da503d9..8f3011fe 100644 --- a/kernel/kapi/devices.cpp +++ b/kernel/kapi/devices.cpp @@ -10,7 +10,6 @@ #include <kstd/print.hpp> #include <kstd/string.hpp> -#include <optional> #include <string_view> #include <utility> @@ -18,37 +17,55 @@ namespace kapi::devices { namespace { - auto constinit root_bus = std::optional<kernel::devices::root_bus>{}; - auto constinit device_tree = kstd::flat_map<kstd::string, kstd::observer_ptr<device>>{}; + auto constinit root_bus = kstd::shared_ptr<kernel::devices::root_bus>{}; + auto constinit device_tree = kstd::flat_map<kstd::string, kstd::weak_ptr<device>>{}; } // namespace auto init() -> void { - if (root_bus.has_value()) + if (root_bus) { kapi::system::panic("[OS:DEV] The device subsystem has already been initialized"); } interface_registry::init(); - auto & bus = root_bus.emplace(); - register_device(bus); - bus.init(); + root_bus = kstd::make_shared<kernel::devices::root_bus>(); + register_device(root_bus); + root_bus->init(); } - auto get_root_bus() -> bus & + auto get_root_bus() -> kstd::shared_ptr<bus> { - if (!root_bus.has_value()) + if (!root_bus) { kapi::system::panic("[OS:DEV] Root bus not initialized!"); } - return *root_bus; + return root_bus; } - auto register_device(device & device) -> bool + auto register_device(kstd::shared_ptr<device> device) -> bool { - kstd::println("[OS:DEV] Registering device {}", device.name()); - return device_tree.emplace(device.name(), &device).second; + 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 @@ -57,16 +74,15 @@ namespace kapi::devices return false; } - auto find_device(std::string_view name) -> kstd::observer_ptr<device> + auto find_device(std::string_view name) -> kstd::shared_ptr<device> { - for (auto const & [key, value] : device_tree) + auto found = device_tree.find(kstd::string{name}); + if (found == device_tree.end()) { - if (value->name() == name) - { - return value; - } + return nullptr; } - return nullptr; + + return found->second.lock(); } } // namespace kapi::devices diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp index d9f3f991..179a04a8 100644 --- a/kernel/kapi/devices/bus.cpp +++ b/kernel/kapi/devices/bus.cpp @@ -9,6 +9,7 @@ #include <kstd/vector.hpp> #include <algorithm> +#include <span> #include <utility> namespace kapi::devices @@ -41,29 +42,30 @@ namespace kapi::devices return child_status; } - auto bus::add_child(kstd::unique_ptr<device> child) -> void + auto bus::add_child(kstd::shared_ptr<device> child) -> void { - auto observer = m_observers.emplace_back(child.get()); - child->set_parent(kstd::make_observer(this)); - m_devices.push_back(std::move(child)); - if (!kapi::devices::register_device(*observer)) + child->set_parent(kstd::static_pointer_cast<bus>(shared_from_this())); + + if (!kapi::devices::register_device(child)) { kapi::system::panic("[OS:DEV] Failed to register child device"); } + auto & attached = m_devices.emplace_back(std::move(child)); + if (m_initialized.test()) { - kstd::println("[OS:DEV] Initializing child device {}@{}", observer->name(), name()); - if (!observer->init()) + kstd::println("[OS:DEV] Initializing child device {}@{}", attached->name(), name()); + if (!attached->init()) { kapi::system::panic("[OS:DEV] Failed to initialize child device"); } } } - [[nodiscard]] auto bus::children() const -> kstd::vector<kstd::observer_ptr<device>> const & + [[nodiscard]] auto bus::children() const -> std::span<kstd::shared_ptr<device> const> { - return m_observers; + return {m_devices.data(), m_devices.size()}; } auto bus::enumerate() -> bool diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp index 0d00d8fd..540d37b7 100644 --- a/kernel/kapi/devices/device.cpp +++ b/kernel/kapi/devices/device.cpp @@ -12,12 +12,17 @@ namespace kapi::devices : m_name(name) {} - [[nodiscard]] auto device::name() const -> kstd::string const & + auto device::name() const -> kstd::string const & { return m_name; } - auto device::set_parent(kstd::observer_ptr<bus> parent) -> void + auto device::parent() const -> kstd::shared_ptr<bus> + { + return m_parent.lock(); + } + + auto device::set_parent(kstd::weak_ptr<bus> parent) -> void { m_parent = parent; } |
