aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-23 01:38:56 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-23 01:38:56 +0200
commit526709a1e86d55dd88e2dbdbc471795efce9046b (patch)
tree04d9de462f506f983d3a991179eccfd68300cc14
parent0361a4912affe1594def1aa24e387fe5440afaee (diff)
downloadkernel-526709a1e86d55dd88e2dbdbc471795efce9046b.tar.xz
kernel-526709a1e86d55dd88e2dbdbc471795efce9046b.zip
kapi: bootstrap owning device tree
-rw-r--r--arch/x86_64/arch/devices/init.cpp8
-rw-r--r--arch/x86_64/kapi/cpu.cpp8
-rw-r--r--kapi/kapi/devices.hpp4
-rw-r--r--kapi/kapi/devices/bus.hpp8
-rw-r--r--kapi/kapi/devices/device.hpp11
-rw-r--r--kapi/kapi/devices/manager.hpp6
-rw-r--r--kernel/kapi/devices.cpp56
-rw-r--r--kernel/kapi/devices/bus.cpp20
-rw-r--r--kernel/kapi/devices/device.cpp9
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;
}