From aee4786d8e80a2a4b2b2422afc4f8f342433c599 Mon Sep 17 00:00:00 2001 From: Liav A Date: Sat, 11 Sep 2021 09:19:20 +0300 Subject: [PATCH] Kernel: Introduce the DeviceManagement singleton This singleton simplifies many aspects that we struggled with before: 1. There's no need to make derived classes of Device expose the constructor as public anymore. The singleton is a friend of them, so he can call the constructor. This solves the issue with try_create_device helper neatly, hopefully for good. 2. Getting a reference of the NullDevice is now being done from this singleton, which means that NullDevice no longer needs to use its own singleton, and we can apply the try_create_device helper on it too :) 3. We can now defer registration completely after the Device constructor which means the Device constructor is merely assigning the major and minor numbers of the Device, and the try_create_device helper ensures it calls the after_inserting method immediately after construction. This creates a great opportunity to make registration more OOM-safe. --- Kernel/CMakeLists.txt | 1 + Kernel/Devices/Device.cpp | 45 +---------- Kernel/Devices/Device.h | 14 ---- Kernel/Devices/DeviceManagement.cpp | 88 ++++++++++++++++++++++ Kernel/Devices/DeviceManagement.h | 54 +++++++++++++ Kernel/Devices/FullDevice.cpp | 3 +- Kernel/Devices/FullDevice.h | 5 +- Kernel/Devices/HID/PS2KeyboardDevice.cpp | 3 +- Kernel/Devices/HID/PS2KeyboardDevice.h | 5 +- Kernel/Devices/HID/PS2MouseDevice.cpp | 3 +- Kernel/Devices/HID/PS2MouseDevice.h | 5 +- Kernel/Devices/HID/VMWareMouseDevice.cpp | 3 +- Kernel/Devices/HID/VMWareMouseDevice.h | 3 +- Kernel/Devices/KCOVDevice.cpp | 3 +- Kernel/Devices/KCOVDevice.h | 4 +- Kernel/Devices/MemoryDevice.cpp | 3 +- Kernel/Devices/MemoryDevice.h | 5 +- Kernel/Devices/NullDevice.cpp | 16 ++-- Kernel/Devices/NullDevice.h | 7 +- Kernel/Devices/RandomDevice.cpp | 3 +- Kernel/Devices/RandomDevice.h | 5 +- Kernel/Devices/SerialDevice.cpp | 9 ++- Kernel/Devices/SerialDevice.h | 5 +- Kernel/Devices/ZeroDevice.cpp | 3 +- Kernel/Devices/ZeroDevice.h | 5 +- Kernel/FileSystem/DevPtsFS.cpp | 3 +- Kernel/FileSystem/DevTmpFS.cpp | 5 +- Kernel/FileSystem/VirtualFileSystem.cpp | 3 +- Kernel/GlobalProcessExposed.cpp | 3 +- Kernel/Graphics/FramebufferDevice.cpp | 3 +- Kernel/Graphics/FramebufferDevice.h | 5 +- Kernel/Process.cpp | 3 +- Kernel/Storage/PATADiskDevice.cpp | 3 +- Kernel/Storage/PATADiskDevice.h | 4 +- Kernel/Storage/Partition/DiskPartition.cpp | 3 +- Kernel/Storage/Partition/DiskPartition.h | 6 +- Kernel/Storage/RamdiskDevice.cpp | 3 +- Kernel/Storage/RamdiskDevice.h | 1 + Kernel/Storage/SATADiskDevice.cpp | 3 +- Kernel/Storage/SATADiskDevice.h | 4 +- Kernel/TTY/VirtualConsole.cpp | 5 +- Kernel/TTY/VirtualConsole.h | 5 +- Kernel/init.cpp | 5 +- 43 files changed, 244 insertions(+), 123 deletions(-) create mode 100644 Kernel/Devices/DeviceManagement.cpp create mode 100644 Kernel/Devices/DeviceManagement.h diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index e819ada537..d2e37b94bb 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -48,6 +48,7 @@ set(KERNEL_SOURCES Devices/BlockDevice.cpp Devices/CharacterDevice.cpp Devices/Device.cpp + Devices/DeviceManagement.cpp Devices/FullDevice.cpp Devices/KCOVDevice.cpp Devices/KCOVInstance.cpp diff --git a/Kernel/Devices/Device.cpp b/Kernel/Devices/Device.cpp index e3b809cb4e..f4301f2bce 100644 --- a/Kernel/Devices/Device.cpp +++ b/Kernel/Devices/Device.cpp @@ -6,20 +6,13 @@ #include #include +#include #include #include -#include #include namespace Kernel { -static Singleton>> s_all_devices; - -MutexProtected>& Device::all_devices() -{ - return *s_all_devices; -} - NonnullRefPtr SysFSDeviceComponent::must_create(Device const& device) { return adopt_ref_if_nonnull(new SysFSDeviceComponent(device)).release_nonnull(); @@ -115,41 +108,15 @@ RefPtr SysFSCharacterDevicesDirectory::lookup(StringView name) }); } -void Device::for_each(Function callback) -{ - all_devices().with_exclusive([&](auto& map) -> void { - for (auto& entry : map) - callback(*entry.value); - }); -} - -Device* Device::get_device(unsigned major, unsigned minor) -{ - return all_devices().with_exclusive([&](auto& map) -> Device* { - auto it = map.find(encoded_device(major, minor)); - if (it == map.end()) - return nullptr; - return it->value; - }); -} - Device::Device(unsigned major, unsigned minor) : m_major(major) , m_minor(minor) { - u32 device_id = encoded_device(major, minor); - all_devices().with_exclusive([&](auto& map) -> void { - auto it = map.find(device_id); - if (it != map.end()) { - dbgln("Already registered {},{}: {}", major, minor, it->value->class_name()); - } - VERIFY(!map.contains(device_id)); - map.set(device_id, this); - }); } void Device::after_inserting() { + DeviceManagement::the().after_inserting_device({}, *this); VERIFY(!m_sysfs_component); auto sys_fs_component = SysFSDeviceComponent::must_create(*this); m_sysfs_component = sys_fs_component; @@ -160,21 +127,17 @@ void Device::after_inserting() void Device::before_removing() { - m_state = State::BeingRemoved; VERIFY(m_sysfs_component); SysFSComponentRegistry::the().devices_list().with_exclusive([&](auto& list) -> void { list.remove(*m_sysfs_component); }); + DeviceManagement::the().before_device_removal({}, *this); + m_state = State::BeingRemoved; } Device::~Device() { VERIFY(m_state == State::BeingRemoved); - u32 device_id = encoded_device(m_major, m_minor); - all_devices().with_exclusive([&](auto& map) -> void { - VERIFY(map.contains(device_id)); - map.remove(encoded_device(m_major, m_minor)); - }); } String Device::absolute_path() const diff --git a/Kernel/Devices/Device.h b/Kernel/Devices/Device.h index e981d76d73..67af4f85e1 100644 --- a/Kernel/Devices/Device.h +++ b/Kernel/Devices/Device.h @@ -27,14 +27,6 @@ namespace Kernel { -template -inline KResultOr> try_create_device(Args&&... args) -{ - auto device = TRY(adopt_nonnull_ref_or_enomem(new DeviceType(forward(args)...))); - device->after_inserting(); - return device; -} - class Device : public File { protected: enum class State { @@ -57,10 +49,6 @@ public: virtual bool is_device() const override { return true; } virtual void before_removing() override; virtual void after_inserting(); - - static void for_each(Function); - static Device* get_device(unsigned major, unsigned minor); - void process_next_queued_request(Badge, const AsyncDeviceRequest&); template @@ -80,8 +68,6 @@ protected: void set_uid(UserID uid) { m_uid = uid; } void set_gid(GroupID gid) { m_gid = gid; } - static MutexProtected>& all_devices(); - private: unsigned m_major { 0 }; unsigned m_minor { 0 }; diff --git a/Kernel/Devices/DeviceManagement.cpp b/Kernel/Devices/DeviceManagement.cpp new file mode 100644 index 0000000000..b02fc06cbf --- /dev/null +++ b/Kernel/Devices/DeviceManagement.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Kernel { + +static Singleton s_the; + +UNMAP_AFTER_INIT DeviceManagement::DeviceManagement() +{ +} +UNMAP_AFTER_INIT void DeviceManagement::initialize() +{ + s_the.ensure_instance(); +} + +UNMAP_AFTER_INIT void DeviceManagement::attach_null_device(NullDevice const& device) +{ + m_null_device = device; +} + +DeviceManagement& DeviceManagement::the() +{ + return *s_the; +} + +Device* DeviceManagement::get_device(unsigned major, unsigned minor) +{ + return m_devices.with_exclusive([&](auto& map) -> Device* { + auto it = map.find(encoded_device(major, minor)); + if (it == map.end()) + return nullptr; + return it->value; + }); +} + +void DeviceManagement::before_device_removal(Badge, Device& device) +{ + u32 device_id = encoded_device(device.major(), device.minor()); + m_devices.with_exclusive([&](auto& map) -> void { + VERIFY(map.contains(device_id)); + map.remove(encoded_device(device.major(), device.minor())); + }); +} + +void DeviceManagement::after_inserting_device(Badge, Device& device) +{ + u32 device_id = encoded_device(device.major(), device.minor()); + m_devices.with_exclusive([&](auto& map) -> void { + if (map.contains(device_id)) { + dbgln("Already registered {},{}: {}", device.major(), device.minor(), device.class_name()); + VERIFY_NOT_REACHED(); + } + auto result = map.set(device_id, &device); + if (result != AK::HashSetResult::InsertedNewEntry) { + dbgln("Failed to register {},{}: {}", device.major(), device.minor(), device.class_name()); + VERIFY_NOT_REACHED(); + } + }); +} + +void DeviceManagement::for_each(Function callback) +{ + m_devices.with_exclusive([&](auto& map) -> void { + for (auto& entry : map) + callback(*entry.value); + }); +} + +NullDevice& DeviceManagement::null_device() +{ + return *m_null_device; +} + +NullDevice const& DeviceManagement::null_device() const +{ + return *m_null_device; +} + +} diff --git a/Kernel/Devices/DeviceManagement.h b/Kernel/Devices/DeviceManagement.h new file mode 100644 index 0000000000..4ec1720e11 --- /dev/null +++ b/Kernel/Devices/DeviceManagement.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +class DeviceManagement { + AK_MAKE_ETERNAL; + +public: + DeviceManagement(); + static void initialize(); + static DeviceManagement& the(); + void attach_null_device(NullDevice const&); + + void after_inserting_device(Badge, Device&); + void before_device_removal(Badge, Device&); + + void for_each(Function); + Device* get_device(unsigned major, unsigned minor); + NullDevice const& null_device() const; + NullDevice& null_device(); + + template + static inline KResultOr> try_create_device(Args&&... args) + { + auto device = TRY(adopt_nonnull_ref_or_enomem(new DeviceType(forward(args)...))); + device->after_inserting(); + return device; + } + +private: + RefPtr m_null_device; + MutexProtected> m_devices; +}; + +} diff --git a/Kernel/Devices/FullDevice.cpp b/Kernel/Devices/FullDevice.cpp index df425cfcea..48f0288b38 100644 --- a/Kernel/Devices/FullDevice.cpp +++ b/Kernel/Devices/FullDevice.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -13,7 +14,7 @@ namespace Kernel { UNMAP_AFTER_INIT NonnullRefPtr FullDevice::must_create() { - auto full_device_or_error = try_create_device(); + auto full_device_or_error = DeviceManagement::try_create_device(); // FIXME: Find a way to propagate errors VERIFY(!full_device_or_error.is_error()); return full_device_or_error.release_value(); diff --git a/Kernel/Devices/FullDevice.h b/Kernel/Devices/FullDevice.h index 3a3f7e09b9..2336e48cff 100644 --- a/Kernel/Devices/FullDevice.h +++ b/Kernel/Devices/FullDevice.h @@ -12,14 +12,15 @@ namespace Kernel { class FullDevice final : public CharacterDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: static NonnullRefPtr must_create(); virtual ~FullDevice() override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: FullDevice(); -private: // ^CharacterDevice virtual KResultOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; virtual KResultOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; diff --git a/Kernel/Devices/HID/PS2KeyboardDevice.cpp b/Kernel/Devices/HID/PS2KeyboardDevice.cpp index 0b569b632f..1f024a3303 100644 --- a/Kernel/Devices/HID/PS2KeyboardDevice.cpp +++ b/Kernel/Devices/HID/PS2KeyboardDevice.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,7 @@ bool PS2KeyboardDevice::handle_irq(const RegisterState&) UNMAP_AFTER_INIT RefPtr PS2KeyboardDevice::try_to_initialize(const I8042Controller& ps2_controller) { - auto keyboard_device_or_error = try_create_device(ps2_controller); + auto keyboard_device_or_error = DeviceManagement::try_create_device(ps2_controller); // FIXME: Find a way to propagate errors VERIFY(!keyboard_device_or_error.is_error()); if (keyboard_device_or_error.value()->initialize()) diff --git a/Kernel/Devices/HID/PS2KeyboardDevice.h b/Kernel/Devices/HID/PS2KeyboardDevice.h index cd8feca328..39f440a0a9 100644 --- a/Kernel/Devices/HID/PS2KeyboardDevice.h +++ b/Kernel/Devices/HID/PS2KeyboardDevice.h @@ -21,6 +21,8 @@ namespace Kernel { class PS2KeyboardDevice final : public IRQHandler , public KeyboardDevice , public I8042Device { + friend class DeviceManagement; + public: static RefPtr try_to_initialize(const I8042Controller&); virtual ~PS2KeyboardDevice() override; @@ -35,10 +37,9 @@ public: enable_irq(); } - // FIXME: We expose this constructor to make try_create_device helper to work +private: explicit PS2KeyboardDevice(const I8042Controller&); -private: // ^IRQHandler virtual bool handle_irq(const RegisterState&) override; diff --git a/Kernel/Devices/HID/PS2MouseDevice.cpp b/Kernel/Devices/HID/PS2MouseDevice.cpp index fce0609e2c..f04a4b1758 100644 --- a/Kernel/Devices/HID/PS2MouseDevice.cpp +++ b/Kernel/Devices/HID/PS2MouseDevice.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -174,7 +175,7 @@ void PS2MouseDevice::set_sample_rate(u8 rate) UNMAP_AFTER_INIT RefPtr PS2MouseDevice::try_to_initialize(const I8042Controller& ps2_controller) { - auto mouse_device_or_error = try_create_device(ps2_controller); + auto mouse_device_or_error = DeviceManagement::try_create_device(ps2_controller); // FIXME: Find a way to propagate errors VERIFY(!mouse_device_or_error.is_error()); if (mouse_device_or_error.value()->initialize()) diff --git a/Kernel/Devices/HID/PS2MouseDevice.h b/Kernel/Devices/HID/PS2MouseDevice.h index fc3b84cd00..b232bf2d1f 100644 --- a/Kernel/Devices/HID/PS2MouseDevice.h +++ b/Kernel/Devices/HID/PS2MouseDevice.h @@ -17,6 +17,8 @@ namespace Kernel { class PS2MouseDevice : public IRQHandler , public MouseDevice , public I8042Device { + friend class DeviceManagement; + public: static RefPtr try_to_initialize(const I8042Controller&); bool initialize(); @@ -32,10 +34,9 @@ public: enable_irq(); } - // FIXME: We expose this constructor to make try_create_device helper to work +protected: explicit PS2MouseDevice(const I8042Controller&); -protected: // ^IRQHandler virtual bool handle_irq(const RegisterState&) override; diff --git a/Kernel/Devices/HID/VMWareMouseDevice.cpp b/Kernel/Devices/HID/VMWareMouseDevice.cpp index 291cde6a78..f2a6908153 100644 --- a/Kernel/Devices/HID/VMWareMouseDevice.cpp +++ b/Kernel/Devices/HID/VMWareMouseDevice.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -16,7 +17,7 @@ UNMAP_AFTER_INIT RefPtr VMWareMouseDevice::try_to_initialize( return {}; if (!VMWareBackdoor::the()->vmmouse_is_absolute()) return {}; - auto mouse_device_or_error = try_create_device(ps2_controller); + auto mouse_device_or_error = DeviceManagement::try_create_device(ps2_controller); // FIXME: Find a way to propagate errors VERIFY(!mouse_device_or_error.is_error()); if (mouse_device_or_error.value()->initialize()) diff --git a/Kernel/Devices/HID/VMWareMouseDevice.h b/Kernel/Devices/HID/VMWareMouseDevice.h index 7f17e27392..3968099990 100644 --- a/Kernel/Devices/HID/VMWareMouseDevice.h +++ b/Kernel/Devices/HID/VMWareMouseDevice.h @@ -17,13 +17,14 @@ namespace Kernel { class VMWareMouseDevice final : public PS2MouseDevice { public: + friend class DeviceManagement; static RefPtr try_to_initialize(const I8042Controller&); virtual ~VMWareMouseDevice() override; // ^I8042Device virtual void irq_handle_byte_read(u8 byte) override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: explicit VMWareMouseDevice(const I8042Controller&); }; diff --git a/Kernel/Devices/KCOVDevice.cpp b/Kernel/Devices/KCOVDevice.cpp index 0d3dc59674..8534e8cbb1 100644 --- a/Kernel/Devices/KCOVDevice.cpp +++ b/Kernel/Devices/KCOVDevice.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -20,7 +21,7 @@ HashMap* KCOVDevice::thread_instance; UNMAP_AFTER_INIT NonnullRefPtr KCOVDevice::must_create() { - auto kcov_device_or_error = try_create_device(); + auto kcov_device_or_error = DeviceManagement::try_create_device(); // FIXME: Find a way to propagate errors VERIFY(!kcov_device_or_error.is_error()); return kcov_device_or_error.release_value(); diff --git a/Kernel/Devices/KCOVDevice.h b/Kernel/Devices/KCOVDevice.h index 0b7fcc8799..576577dff5 100644 --- a/Kernel/Devices/KCOVDevice.h +++ b/Kernel/Devices/KCOVDevice.h @@ -12,6 +12,7 @@ namespace Kernel { class KCOVDevice final : public BlockDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; public: static HashMap* proc_instance; @@ -25,10 +26,9 @@ public: KResultOr mmap(Process&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared) override; KResultOr> open(int options) override; - // FIXME: We expose this constructor to make try_create_device helper to work +protected: KCOVDevice(); -protected: virtual StringView class_name() const override { return "KCOVDevice"; } virtual bool can_read(const OpenFileDescription&, size_t) const override final { return true; } diff --git a/Kernel/Devices/MemoryDevice.cpp b/Kernel/Devices/MemoryDevice.cpp index 1bdb1b9b58..3a0d42ad7e 100644 --- a/Kernel/Devices/MemoryDevice.cpp +++ b/Kernel/Devices/MemoryDevice.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -15,7 +16,7 @@ namespace Kernel { UNMAP_AFTER_INIT NonnullRefPtr MemoryDevice::must_create() { - auto memory_device_or_error = try_create_device(); + auto memory_device_or_error = DeviceManagement::try_create_device(); // FIXME: Find a way to propagate errors VERIFY(!memory_device_or_error.is_error()); return memory_device_or_error.release_value(); diff --git a/Kernel/Devices/MemoryDevice.h b/Kernel/Devices/MemoryDevice.h index 0f40d26a4f..016ab6c556 100644 --- a/Kernel/Devices/MemoryDevice.h +++ b/Kernel/Devices/MemoryDevice.h @@ -15,16 +15,17 @@ namespace Kernel { class MemoryDevice final : public CharacterDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: static NonnullRefPtr must_create(); ~MemoryDevice(); virtual KResultOr mmap(Process&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared) override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: MemoryDevice(); -private: virtual StringView class_name() const override { return "MemoryDevice"; } virtual bool can_read(const OpenFileDescription&, size_t) const override { return true; } virtual bool can_write(const OpenFileDescription&, size_t) const override { return false; } diff --git a/Kernel/Devices/NullDevice.cpp b/Kernel/Devices/NullDevice.cpp index ae20bcfeba..29d27f6922 100644 --- a/Kernel/Devices/NullDevice.cpp +++ b/Kernel/Devices/NullDevice.cpp @@ -5,22 +5,18 @@ */ #include +#include #include #include namespace Kernel { -static Singleton s_the; - -UNMAP_AFTER_INIT void NullDevice::initialize() +UNMAP_AFTER_INIT NonnullRefPtr NullDevice::must_initialize() { - s_the.ensure_instance(); - s_the->after_inserting(); -} - -NullDevice& NullDevice::the() -{ - return *s_the; + auto null_device_or_error = DeviceManagement::try_create_device(); + // FIXME: Find a way to propagate errors + VERIFY(!null_device_or_error.is_error()); + return null_device_or_error.release_value(); } UNMAP_AFTER_INIT NullDevice::NullDevice() diff --git a/Kernel/Devices/NullDevice.h b/Kernel/Devices/NullDevice.h index d10729c44c..7078bac39d 100644 --- a/Kernel/Devices/NullDevice.h +++ b/Kernel/Devices/NullDevice.h @@ -12,14 +12,15 @@ namespace Kernel { class NullDevice final : public CharacterDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: - NullDevice(); virtual ~NullDevice() override; - static void initialize(); - static NullDevice& the(); + static NonnullRefPtr must_initialize(); private: + NullDevice(); // ^CharacterDevice virtual KResultOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; virtual KResultOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; diff --git a/Kernel/Devices/RandomDevice.cpp b/Kernel/Devices/RandomDevice.cpp index 1d2ab995e4..cc66978366 100644 --- a/Kernel/Devices/RandomDevice.cpp +++ b/Kernel/Devices/RandomDevice.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -12,7 +13,7 @@ namespace Kernel { UNMAP_AFTER_INIT NonnullRefPtr RandomDevice::must_create() { - auto random_device_or_error = try_create_device(); + auto random_device_or_error = DeviceManagement::try_create_device(); // FIXME: Find a way to propagate errors VERIFY(!random_device_or_error.is_error()); return random_device_or_error.release_value(); diff --git a/Kernel/Devices/RandomDevice.h b/Kernel/Devices/RandomDevice.h index 8e915cd1c5..06337479c9 100644 --- a/Kernel/Devices/RandomDevice.h +++ b/Kernel/Devices/RandomDevice.h @@ -12,14 +12,15 @@ namespace Kernel { class RandomDevice final : public CharacterDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: static NonnullRefPtr must_create(); virtual ~RandomDevice() override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: RandomDevice(); -private: // ^CharacterDevice virtual KResultOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; virtual KResultOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; diff --git a/Kernel/Devices/SerialDevice.cpp b/Kernel/Devices/SerialDevice.cpp index 81416502f1..8e881325f6 100644 --- a/Kernel/Devices/SerialDevice.cpp +++ b/Kernel/Devices/SerialDevice.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -23,19 +24,19 @@ UNMAP_AFTER_INIT NonnullRefPtr SerialDevice::must_create(size_t co RefPtr serial_device; switch (com_number) { case 0: { - serial_device = try_create_device(IOAddress(SERIAL_COM1_ADDR), 64).release_value(); + serial_device = DeviceManagement::try_create_device(IOAddress(SERIAL_COM1_ADDR), 64).release_value(); break; } case 1: { - serial_device = try_create_device(IOAddress(SERIAL_COM2_ADDR), 65).release_value(); + serial_device = DeviceManagement::try_create_device(IOAddress(SERIAL_COM2_ADDR), 65).release_value(); break; } case 2: { - serial_device = try_create_device(IOAddress(SERIAL_COM3_ADDR), 66).release_value(); + serial_device = DeviceManagement::try_create_device(IOAddress(SERIAL_COM3_ADDR), 66).release_value(); break; } case 3: { - serial_device = try_create_device(IOAddress(SERIAL_COM4_ADDR), 67).release_value(); + serial_device = DeviceManagement::try_create_device(IOAddress(SERIAL_COM4_ADDR), 67).release_value(); break; } default: diff --git a/Kernel/Devices/SerialDevice.h b/Kernel/Devices/SerialDevice.h index ac6c158720..d92f3e591e 100644 --- a/Kernel/Devices/SerialDevice.h +++ b/Kernel/Devices/SerialDevice.h @@ -13,6 +13,8 @@ namespace Kernel { class SerialDevice final : public CharacterDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: static NonnullRefPtr must_create(size_t com_number); @@ -102,10 +104,9 @@ public: DataReady = 0x01 << 0 }; - // FIXME: We expose this constructor to make try_create_device helper to work +private: SerialDevice(IOAddress base_addr, unsigned minor); -private: friend class PCISerialDevice; // ^CharacterDevice diff --git a/Kernel/Devices/ZeroDevice.cpp b/Kernel/Devices/ZeroDevice.cpp index fad3113f1a..ed10d1ef39 100644 --- a/Kernel/Devices/ZeroDevice.cpp +++ b/Kernel/Devices/ZeroDevice.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -12,7 +13,7 @@ namespace Kernel { UNMAP_AFTER_INIT NonnullRefPtr ZeroDevice::must_create() { - auto zero_device_or_error = try_create_device(); + auto zero_device_or_error = DeviceManagement::try_create_device(); // FIXME: Find a way to propagate errors VERIFY(!zero_device_or_error.is_error()); return zero_device_or_error.release_value(); diff --git a/Kernel/Devices/ZeroDevice.h b/Kernel/Devices/ZeroDevice.h index e5a2b6dea2..63d02f1500 100644 --- a/Kernel/Devices/ZeroDevice.h +++ b/Kernel/Devices/ZeroDevice.h @@ -12,14 +12,15 @@ namespace Kernel { class ZeroDevice final : public CharacterDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: static NonnullRefPtr must_create(); virtual ~ZeroDevice() override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: ZeroDevice(); -private: // ^CharacterDevice virtual KResultOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; virtual KResultOr write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override; diff --git a/Kernel/FileSystem/DevPtsFS.cpp b/Kernel/FileSystem/DevPtsFS.cpp index 9543c26ff2..4c64ef1958 100644 --- a/Kernel/FileSystem/DevPtsFS.cpp +++ b/Kernel/FileSystem/DevPtsFS.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -58,7 +59,7 @@ KResultOr> DevPtsFS::get_inode(InodeIdentifier inode_id) co return *m_root_inode; unsigned pty_index = inode_index_to_pty_index(inode_id.index()); - auto* device = Device::get_device(201, pty_index); + auto* device = DeviceManagement::the().get_device(201, pty_index); VERIFY(device); auto inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) DevPtsFSInode(const_cast(*this), inode_id.index(), static_cast(device)))); diff --git a/Kernel/FileSystem/DevTmpFS.cpp b/Kernel/FileSystem/DevTmpFS.cpp index 5921b8209b..93df86d516 100644 --- a/Kernel/FileSystem/DevTmpFS.cpp +++ b/Kernel/FileSystem/DevTmpFS.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -321,7 +322,7 @@ KResultOr DevTmpFSDeviceInode::read_bytes(off_t offset, size_t count, Us { MutexLocker locker(m_inode_lock); VERIFY(!!description); - RefPtr device = Device::get_device(m_major_number, m_minor_number); + RefPtr device = DeviceManagement::the().get_device(m_major_number, m_minor_number); if (!device) return KResult(ENODEV); if (!device->can_read(*description, offset)) @@ -336,7 +337,7 @@ KResultOr DevTmpFSDeviceInode::write_bytes(off_t offset, size_t count, c { MutexLocker locker(m_inode_lock); VERIFY(!!description); - RefPtr device = Device::get_device(m_major_number, m_minor_number); + RefPtr device = DeviceManagement::the().get_device(m_major_number, m_minor_number); if (!device) return KResult(ENODEV); if (!device->can_write(*description, offset)) diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 5378a58a2d..886c4cf7d3 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -270,7 +271,7 @@ KResultOr> VirtualFileSystem::open(StringView if (metadata.is_device()) { if (custody.mount_flags() & MS_NODEV) return EACCES; - auto device = Device::get_device(metadata.major_device, metadata.minor_device); + auto device = DeviceManagement::the().get_device(metadata.major_device, metadata.minor_device); if (device == nullptr) { return ENODEV; } diff --git a/Kernel/GlobalProcessExposed.cpp b/Kernel/GlobalProcessExposed.cpp index bad352eef3..3b6f567d11 100644 --- a/Kernel/GlobalProcessExposed.cpp +++ b/Kernel/GlobalProcessExposed.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -640,7 +641,7 @@ private: virtual KResult try_generate(KBufferBuilder& builder) override { JsonArraySerializer array { builder }; - Device::for_each([&array](auto& device) { + DeviceManagement::the().for_each([&array](auto& device) { auto obj = array.add_object(); obj.add("major", device.major()); obj.add("minor", device.minor()); diff --git a/Kernel/Graphics/FramebufferDevice.cpp b/Kernel/Graphics/FramebufferDevice.cpp index 0d36a3400e..07afd0b4b0 100644 --- a/Kernel/Graphics/FramebufferDevice.cpp +++ b/Kernel/Graphics/FramebufferDevice.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -22,7 +23,7 @@ namespace Kernel { NonnullRefPtr FramebufferDevice::create(const GraphicsDevice& adapter, size_t output_port_index, PhysicalAddress paddr, size_t width, size_t height, size_t pitch) { - auto framebuffer_device_or_error = try_create_device(adapter, output_port_index, paddr, width, height, pitch); + auto framebuffer_device_or_error = DeviceManagement::try_create_device(adapter, output_port_index, paddr, width, height, pitch); // FIXME: Find a way to propagate errors VERIFY(!framebuffer_device_or_error.is_error()); return framebuffer_device_or_error.release_value(); diff --git a/Kernel/Graphics/FramebufferDevice.h b/Kernel/Graphics/FramebufferDevice.h index 2b4e958bbf..531ea005fb 100644 --- a/Kernel/Graphics/FramebufferDevice.h +++ b/Kernel/Graphics/FramebufferDevice.h @@ -19,6 +19,8 @@ namespace Kernel { class FramebufferDevice : public BlockDevice { AK_MAKE_ETERNAL + friend class DeviceManagement; + public: static NonnullRefPtr create(const GraphicsDevice&, size_t, PhysicalAddress, size_t, size_t, size_t); @@ -32,10 +34,9 @@ public: virtual ~FramebufferDevice() {}; KResult initialize(); - // FIXME: We expose this constructor to make try_create_device helper to work +private: FramebufferDevice(const GraphicsDevice&, size_t, PhysicalAddress, size_t, size_t, size_t); -private: // ^File virtual StringView class_name() const override { return "FramebufferDevice"; } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 3d58a58278..aed6523c6a 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef ENABLE_KERNEL_COVERAGE_COLLECTION # include #endif @@ -156,7 +157,7 @@ KResultOr> Process::try_create_user_process(RefPtrm_fds.m_fds_metadatas[fd].allocate(); diff --git a/Kernel/Storage/PATADiskDevice.cpp b/Kernel/Storage/PATADiskDevice.cpp index d4aab035b0..11a594f1bb 100644 --- a/Kernel/Storage/PATADiskDevice.cpp +++ b/Kernel/Storage/PATADiskDevice.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -15,7 +16,7 @@ namespace Kernel { UNMAP_AFTER_INIT NonnullRefPtr PATADiskDevice::create(const IDEController& controller, IDEChannel& channel, DriveType type, InterfaceType interface_type, u16 capabilities, u64 max_addressable_block) { - auto device_or_error = try_create_device(controller, channel, type, interface_type, capabilities, max_addressable_block); + auto device_or_error = DeviceManagement::try_create_device(controller, channel, type, interface_type, capabilities, max_addressable_block); // FIXME: Find a way to propagate errors VERIFY(!device_or_error.is_error()); return device_or_error.release_value(); diff --git a/Kernel/Storage/PATADiskDevice.h b/Kernel/Storage/PATADiskDevice.h index 9de2561b36..77fc49b77a 100644 --- a/Kernel/Storage/PATADiskDevice.h +++ b/Kernel/Storage/PATADiskDevice.h @@ -20,6 +20,7 @@ class IDEController; class IDEChannel; class PATADiskDevice final : public StorageDevice { friend class IDEController; + friend class DeviceManagement; AK_MAKE_ETERNAL public: // Type of drive this IDEDiskDevice is on the ATA channel. @@ -44,10 +45,9 @@ public: virtual void start_request(AsyncBlockDeviceRequest&) override; virtual String storage_name() const override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: PATADiskDevice(const IDEController&, IDEChannel&, DriveType, InterfaceType, u16, u64); -private: // ^DiskDevice virtual StringView class_name() const override; diff --git a/Kernel/Storage/Partition/DiskPartition.cpp b/Kernel/Storage/Partition/DiskPartition.cpp index 5352528773..d1941a16de 100644 --- a/Kernel/Storage/Partition/DiskPartition.cpp +++ b/Kernel/Storage/Partition/DiskPartition.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -12,7 +13,7 @@ namespace Kernel { NonnullRefPtr DiskPartition::create(BlockDevice& device, unsigned minor_number, DiskPartitionMetadata metadata) { - auto partition_or_error = try_create_device(device, minor_number, metadata); + auto partition_or_error = DeviceManagement::try_create_device(device, minor_number, metadata); // FIXME: Find a way to propagate errors VERIFY(!partition_or_error.is_error()); return partition_or_error.release_value(); diff --git a/Kernel/Storage/Partition/DiskPartition.h b/Kernel/Storage/Partition/DiskPartition.h index 1d4bae1c75..4c172785be 100644 --- a/Kernel/Storage/Partition/DiskPartition.h +++ b/Kernel/Storage/Partition/DiskPartition.h @@ -14,6 +14,8 @@ namespace Kernel { class DiskPartition final : public BlockDevice { + friend class DeviceManagement; + public: static NonnullRefPtr create(BlockDevice&, unsigned, DiskPartitionMetadata); virtual ~DiskPartition(); @@ -28,10 +30,8 @@ public: const DiskPartitionMetadata& metadata() const; - // FIXME: We expose this constructor to make try_create_device helper to work - DiskPartition(BlockDevice&, unsigned, DiskPartitionMetadata); - private: + DiskPartition(BlockDevice&, unsigned, DiskPartitionMetadata); virtual StringView class_name() const override; WeakPtr m_device; diff --git a/Kernel/Storage/RamdiskDevice.cpp b/Kernel/Storage/RamdiskDevice.cpp index 5d831edae2..e08ecdbf87 100644 --- a/Kernel/Storage/RamdiskDevice.cpp +++ b/Kernel/Storage/RamdiskDevice.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,7 @@ namespace Kernel { NonnullRefPtr RamdiskDevice::create(const RamdiskController& controller, NonnullOwnPtr&& region, int major, int minor) { - auto device_or_error = try_create_device(controller, move(region), major, minor); + auto device_or_error = DeviceManagement::try_create_device(controller, move(region), major, minor); // FIXME: Find a way to propagate errors VERIFY(!device_or_error.is_error()); return device_or_error.release_value(); diff --git a/Kernel/Storage/RamdiskDevice.h b/Kernel/Storage/RamdiskDevice.h index a55c3fd026..91cf4a22cf 100644 --- a/Kernel/Storage/RamdiskDevice.h +++ b/Kernel/Storage/RamdiskDevice.h @@ -15,6 +15,7 @@ class RamdiskController; class RamdiskDevice final : public StorageDevice { friend class RamdiskController; + friend class DeviceManagement; AK_MAKE_ETERNAL public: static NonnullRefPtr create(const RamdiskController&, NonnullOwnPtr&& region, int major, int minor); diff --git a/Kernel/Storage/SATADiskDevice.cpp b/Kernel/Storage/SATADiskDevice.cpp index 0e7c7bd8d4..7563f0cb31 100644 --- a/Kernel/Storage/SATADiskDevice.cpp +++ b/Kernel/Storage/SATADiskDevice.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -14,7 +15,7 @@ namespace Kernel { NonnullRefPtr SATADiskDevice::create(const AHCIController& controller, const AHCIPort& port, size_t sector_size, u64 max_addressable_block) { - auto device_or_error = try_create_device(controller, port, sector_size, max_addressable_block); + auto device_or_error = DeviceManagement::try_create_device(controller, port, sector_size, max_addressable_block); // FIXME: Find a way to propagate errors VERIFY(!device_or_error.is_error()); return device_or_error.release_value(); diff --git a/Kernel/Storage/SATADiskDevice.h b/Kernel/Storage/SATADiskDevice.h index 97776b4500..76f6d21fb9 100644 --- a/Kernel/Storage/SATADiskDevice.h +++ b/Kernel/Storage/SATADiskDevice.h @@ -16,6 +16,7 @@ namespace Kernel { class AHCIController; class SATADiskDevice final : public StorageDevice { friend class AHCIController; + friend class DeviceManagement; public: enum class InterfaceType : u8 { @@ -32,10 +33,9 @@ public: virtual void start_request(AsyncBlockDeviceRequest&) override; virtual String storage_name() const override; - // FIXME: We expose this constructor to make try_create_device helper to work +private: SATADiskDevice(const AHCIController&, const AHCIPort&, size_t sector_size, u64 max_addressable_block); -private: // ^DiskDevice virtual StringView class_name() const override; WeakPtr m_port; diff --git a/Kernel/TTY/VirtualConsole.cpp b/Kernel/TTY/VirtualConsole.cpp index 58361a3a79..9cf1cc4ce4 100644 --- a/Kernel/TTY/VirtualConsole.cpp +++ b/Kernel/TTY/VirtualConsole.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -103,7 +104,7 @@ void VirtualConsole::set_graphical(bool graphical) UNMAP_AFTER_INIT NonnullRefPtr VirtualConsole::create(size_t index) { - auto virtual_console_or_error = try_create_device(index); + auto virtual_console_or_error = DeviceManagement::try_create_device(index); // FIXME: Find a way to propagate errors VERIFY(!virtual_console_or_error.is_error()); return virtual_console_or_error.release_value(); @@ -111,7 +112,7 @@ UNMAP_AFTER_INIT NonnullRefPtr VirtualConsole::create(size_t ind UNMAP_AFTER_INIT NonnullRefPtr VirtualConsole::create_with_preset_log(size_t index, const CircularQueue& log) { - auto virtual_console_or_error = try_create_device(index, log); + auto virtual_console_or_error = DeviceManagement::try_create_device(index, log); // FIXME: Find a way to propagate errors VERIFY(!virtual_console_or_error.is_error()); return virtual_console_or_error.release_value(); diff --git a/Kernel/TTY/VirtualConsole.h b/Kernel/TTY/VirtualConsole.h index d90e718cbe..fd0047cdcd 100644 --- a/Kernel/TTY/VirtualConsole.h +++ b/Kernel/TTY/VirtualConsole.h @@ -50,6 +50,7 @@ class VirtualConsole final : public TTY , public VT::TerminalClient { AK_MAKE_ETERNAL friend class ConsoleManagement; + friend class DeviceManagement; friend class ConsoleImpl; friend class VT::Terminal; @@ -84,11 +85,9 @@ public: void emit_char(char); - // FIXME: We expose these constructors to make try_create_device helper to work +private: explicit VirtualConsole(const unsigned index); VirtualConsole(const unsigned index, const CircularQueue&); - -private: // ^KeyboardClient virtual void on_key_pressed(KeyEvent) override; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 854b18a4b0..516eea7d0b 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -182,7 +183,10 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) load_kernel_symbol_table(); + DeviceManagement::initialize(); SysFSComponentRegistry::initialize(); + DeviceManagement::the().attach_null_device(*NullDevice::must_initialize()); + ConsoleDevice::initialize(); s_bsp_processor.initialize(0); @@ -281,7 +285,6 @@ void init_stage2(void*) VirtualFileSystem::initialize(); - NullDevice::initialize(); if (!get_serial_debug()) (void)SerialDevice::must_create(0).leak_ref(); (void)SerialDevice::must_create(1).leak_ref();