Forráskód Böngészése

Kernel: Switch singletons to use new Singleton class

MemoryManager cannot use the Singleton class because
MemoryManager::initialize is called before the global constructors
are run. That caused the Singleton to be re-initialized, causing
it to create another MemoryManager instance.

Fixes #3226
Tom 5 éve
szülő
commit
d89582880e
46 módosított fájl, 221 hozzáadás és 170 törlés
  1. 4 4
      AK/FlyString.cpp
  2. 30 18
      AK/Singleton.h
  3. 1 0
      Kernel/CommandLine.cpp
  4. 8 4
      Kernel/Console.cpp
  5. 1 0
      Kernel/Console.h
  6. 7 2
      Kernel/Devices/BXVGADevice.cpp
  7. 1 0
      Kernel/Devices/BXVGADevice.h
  8. 2 3
      Kernel/Devices/Device.cpp
  9. 7 4
      Kernel/Devices/KeyboardDevice.cpp
  10. 1 0
      Kernel/Devices/KeyboardDevice.h
  11. 7 3
      Kernel/Devices/NullDevice.cpp
  12. 1 0
      Kernel/Devices/NullDevice.h
  13. 5 5
      Kernel/Devices/PATAChannel.cpp
  14. 7 2
      Kernel/Devices/PS2MouseDevice.cpp
  15. 1 0
      Kernel/Devices/PS2MouseDevice.h
  16. 7 2
      Kernel/Devices/SB16.cpp
  17. 1 0
      Kernel/Devices/SB16.h
  18. 30 21
      Kernel/Devices/VMWareBackdoor.cpp
  19. 1 2
      Kernel/Devices/VMWareBackdoor.h
  20. 7 10
      Kernel/FileSystem/DevPtsFS.cpp
  21. 3 3
      Kernel/FileSystem/FIFO.cpp
  22. 2 3
      Kernel/FileSystem/FileSystem.cpp
  23. 3 4
      Kernel/FileSystem/Inode.cpp
  24. 7 3
      Kernel/FileSystem/VirtualFileSystem.cpp
  25. 1 0
      Kernel/FileSystem/VirtualFileSystem.h
  26. 4 3
      Kernel/Interrupts/APIC.cpp
  27. 3 3
      Kernel/Net/IPv4Socket.cpp
  28. 3 3
      Kernel/Net/LocalSocket.cpp
  29. 4 4
      Kernel/Net/LoopbackAdapter.cpp
  30. 1 3
      Kernel/Net/LoopbackAdapter.h
  31. 4 4
      Kernel/Net/NetworkAdapter.cpp
  32. 4 4
      Kernel/Net/Routing.cpp
  33. 7 8
      Kernel/Net/TCPSocket.cpp
  34. 3 3
      Kernel/Net/UDPSocket.cpp
  35. 2 4
      Kernel/Random.cpp
  36. 1 2
      Kernel/Random.h
  37. 4 4
      Kernel/SharedBuffer.cpp
  38. 2 3
      Kernel/TTY/PTYMultiplexer.cpp
  39. 4 0
      Kernel/TTY/PTYMultiplexer.h
  40. 10 10
      Kernel/Time/TimeManagement.cpp
  41. 1 1
      Kernel/Time/TimeManagement.h
  42. 2 3
      Kernel/TimerQueue.cpp
  43. 1 2
      Kernel/TimerQueue.h
  44. 4 0
      Kernel/VM/MemoryManager.cpp
  45. 4 4
      Kernel/VM/PageDirectory.cpp
  46. 8 9
      Kernel/init.cpp

+ 4 - 4
AK/FlyString.cpp

@@ -27,6 +27,7 @@
 #include <AK/FlyString.h>
 #include <AK/HashTable.h>
 #include <AK/Optional.h>
+#include <AK/Singleton.h>
 #include <AK/String.h>
 #include <AK/StringUtils.h>
 #include <AK/StringView.h>
@@ -47,12 +48,11 @@ struct FlyStringImplTraits : public AK::Traits<StringImpl*> {
     }
 };
 
+static AK::Singleton<HashTable<StringImpl*, FlyStringImplTraits>> s_table;
+
 static HashTable<StringImpl*, FlyStringImplTraits>& fly_impls()
 {
-    static HashTable<StringImpl*, FlyStringImplTraits>* table;
-    if (!table)
-        table = new HashTable<StringImpl*, FlyStringImplTraits>;
-    return *table;
+    return *s_table;
 }
 
 void FlyString::did_destroy_impl(Badge<StringImpl>, StringImpl& impl)

+ 30 - 18
Kernel/Singleton.h → AK/Singleton.h

@@ -26,20 +26,42 @@
 
 #pragma once
 
+#include <AK/Assertions.h>
 #include <AK/Atomic.h>
+#include <AK/kmalloc.h>
+#ifdef KERNEL
 #include <Kernel/Arch/i386/CPU.h>
+#endif
 
-namespace Kernel {
+#ifndef __serenity__
+#    include <new>
+#endif
 
-template<typename T, T* (*InitFunction)()>
+namespace AK {
+
+template<typename T>
+struct SingletonInstanceCreator {
+    static T* create()
+    {
+        return new T();
+    }
+};
+
+template<typename T, T* (*InitFunction)() = SingletonInstanceCreator<T>::create>
 class Singleton {
+    AK_MAKE_NONCOPYABLE(Singleton);
+    AK_MAKE_NONMOVABLE(Singleton);
 public:
+    Singleton() = default;
+
     T* ptr() const
     {
         T* obj = AK::atomic_load(&m_obj, AK::memory_order_consume);
         if (FlatPtr(obj) <= 0x1) {
             // If this is the first time, see if we get to initialize it
-            ScopedCritical critical;
+#ifdef KERNEL
+            Kernel::ScopedCritical critical;
+#endif
             if (obj == nullptr && AK::atomic_compare_exchange_strong(&m_obj, obj, (T*)0x1, AK::memory_order_acq_rel)) {
                 // We're the first one
                 obj = InitFunction();
@@ -47,7 +69,11 @@ public:
             } else {
                 // Someone else was faster, wait until they're done
                 while (obj == (T*)0x1) {
-                    Processor::wait_check();
+#ifdef KERNEL
+                    Kernel::Processor::wait_check();
+#else
+                    // TODO: yield
+#endif
                     obj = AK::atomic_load(&m_obj, AK::memory_order_consume);
                 }
             }
@@ -93,18 +119,4 @@ private:
     mutable T* m_obj { nullptr }; // atomic
 };
 
-template<typename T>
-struct SingletonInstanceCreator {
-    static T* create()
-    {
-        return new T();
-    }
-};
-
-template<typename T>
-static Singleton<T, SingletonInstanceCreator<T>::create> make_singleton()
-{
-    return Singleton<T, SingletonInstanceCreator<T>::create>();
-}
-
 }

+ 1 - 0
Kernel/CommandLine.cpp

@@ -38,6 +38,7 @@ const CommandLine& kernel_command_line()
 
 void CommandLine::initialize(const String& string)
 {
+    ASSERT(!s_the);
     s_the = new CommandLine(string);
 }
 

+ 8 - 4
Kernel/Console.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/Console.h>
 #include <Kernel/IO.h>
 #include <Kernel/kstdio.h>
@@ -32,24 +33,27 @@
 // Bytes output to 0xE9 end up on the Bochs console. It's very handy.
 #define CONSOLE_OUT_TO_E9
 
-static Console* s_the;
+static AK::Singleton<Console> s_the;
 static Kernel::SpinLock g_console_lock;
 
+void Console::initialize()
+{
+    s_the.ensure_instance();
+}
+
 Console& Console::the()
 {
-    ASSERT(s_the);
     return *s_the;
 }
 
 bool Console::is_initialized()
 {
-    return s_the != nullptr;
+    return s_the.is_initialized();
 }
 
 Console::Console()
     : CharacterDevice(5, 1)
 {
-    s_the = this;
 }
 
 Console::~Console()

+ 1 - 0
Kernel/Console.h

@@ -34,6 +34,7 @@ class Console final : public Kernel::CharacterDevice {
     AK_MAKE_ETERNAL
 public:
     static Console& the();
+    static void initialize();
     static bool is_initialized();
 
     Console();

+ 7 - 2
Kernel/Devices/BXVGADevice.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/Checked.h>
+#include <AK/Singleton.h>
 #include <Kernel/Devices/BXVGADevice.h>
 #include <Kernel/IO.h>
 #include <Kernel/PCI/Access.h>
@@ -56,7 +57,12 @@ namespace Kernel {
 #define VBE_DISPI_ENABLED 0x01
 #define VBE_DISPI_LFB_ENABLED 0x40
 
-static BXVGADevice* s_the;
+static AK::Singleton<BXVGADevice> s_the;
+
+void BXVGADevice::initialize()
+{
+    s_the.ensure_instance();
+}
 
 BXVGADevice& BXVGADevice::the()
 {
@@ -67,7 +73,6 @@ BXVGADevice::BXVGADevice()
     : BlockDevice(29, 0)
 
 {
-    s_the = this;
     m_framebuffer_address = PhysicalAddress(find_framebuffer_address());
     set_safe_resolution();
 }

+ 1 - 0
Kernel/Devices/BXVGADevice.h

@@ -36,6 +36,7 @@ namespace Kernel {
 class BXVGADevice final : public BlockDevice {
     AK_MAKE_ETERNAL
 public:
+    static void initialize();
     static BXVGADevice& the();
 
     BXVGADevice();

+ 2 - 3
Kernel/Devices/Device.cpp

@@ -24,18 +24,17 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/Devices/Device.h>
 #include <Kernel/FileSystem/InodeMetadata.h>
 #include <LibC/errno_numbers.h>
 
 namespace Kernel {
 
-static HashMap<u32, Device*>* s_all_devices;
+static AK::Singleton<HashMap<u32, Device*>> s_all_devices;
 
 HashMap<u32, Device*>& Device::all_devices()
 {
-    if (s_all_devices == nullptr)
-        s_all_devices = new HashMap<u32, Device*>;
     return *s_all_devices;
 }
 

+ 7 - 4
Kernel/Devices/KeyboardDevice.cpp

@@ -26,6 +26,7 @@
 
 #include <AK/Assertions.h>
 #include <AK/ByteBuffer.h>
+#include <AK/Singleton.h>
 #include <AK/StringView.h>
 #include <AK/Types.h>
 #include <Kernel/Arch/i386/CPU.h>
@@ -335,11 +336,15 @@ void KeyboardDevice::handle_irq(const RegisterState&)
     }
 }
 
-static KeyboardDevice* s_the;
+static AK::Singleton<KeyboardDevice> s_the;
+
+void KeyboardDevice::initialize()
+{
+    s_the.ensure_instance();
+}
 
 KeyboardDevice& KeyboardDevice::the()
 {
-    ASSERT(s_the);
     return *s_the;
 }
 
@@ -347,8 +352,6 @@ KeyboardDevice::KeyboardDevice()
     : IRQHandler(IRQ_KEYBOARD)
     , CharacterDevice(85, 1)
 {
-    s_the = this;
-
     // Empty the buffer of any pending data.
     // I don't care what you've been pressing until now!
     while (IO::in8(I8042_STATUS) & I8042_BUFFER_FULL)

+ 1 - 0
Kernel/Devices/KeyboardDevice.h

@@ -45,6 +45,7 @@ class KeyboardDevice final : public IRQHandler
 public:
     using Event = KeyEvent;
 
+    static void initialize();
     static KeyboardDevice& the();
 
     virtual ~KeyboardDevice() override;

+ 7 - 3
Kernel/Devices/NullDevice.cpp

@@ -25,22 +25,26 @@
  */
 
 #include "NullDevice.h"
+#include <AK/Singleton.h>
 #include <AK/StdLibExtras.h>
 
 namespace Kernel {
 
-static NullDevice* s_the;
+static AK::Singleton<NullDevice> s_the;
+
+void NullDevice::initialize()
+{
+    s_the.ensure_instance();
+}
 
 NullDevice& NullDevice::the()
 {
-    ASSERT(s_the);
     return *s_the;
 }
 
 NullDevice::NullDevice()
     : CharacterDevice(1, 3)
 {
-    s_the = this;
 }
 
 NullDevice::~NullDevice()

+ 1 - 0
Kernel/Devices/NullDevice.h

@@ -36,6 +36,7 @@ public:
     NullDevice();
     virtual ~NullDevice() override;
 
+    static void initialize();
     static NullDevice& the();
 
 private:

+ 5 - 5
Kernel/Devices/PATAChannel.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/ByteBuffer.h>
+#include <AK/Singleton.h>
 #include <AK/StringView.h>
 #include <Kernel/Devices/PATAChannel.h>
 #include <Kernel/Devices/PATADiskDevice.h>
@@ -106,13 +107,12 @@ namespace Kernel {
 
 #define PCI_Mass_Storage_Class 0x1
 #define PCI_IDE_Controller_Subclass 0x1
+
+static AK::Singleton<Lock> s_pata_lock;
+
 static Lock& s_lock()
 {
-    static Lock* lock;
-    if (!lock)
-        lock = new Lock;
-
-    return *lock;
+    return *s_pata_lock;
 };
 
 OwnPtr<PATAChannel> PATAChannel::create(ChannelType type, bool force_pio)

+ 7 - 2
Kernel/Devices/PS2MouseDevice.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/Memory.h>
+#include <AK/Singleton.h>
 #include <Kernel/Devices/PS2MouseDevice.h>
 #include <Kernel/Devices/VMWareBackdoor.h>
 #include <Kernel/IO.h>
@@ -56,13 +57,12 @@ namespace Kernel {
 
 //#define PS2MOUSE_DEBUG
 
-static PS2MouseDevice* s_the;
+static AK::Singleton<PS2MouseDevice> s_the;
 
 PS2MouseDevice::PS2MouseDevice()
     : IRQHandler(IRQ_MOUSE)
     , CharacterDevice(10, 1)
 {
-    s_the = this;
     initialize();
 }
 
@@ -70,6 +70,11 @@ PS2MouseDevice::~PS2MouseDevice()
 {
 }
 
+void PS2MouseDevice::create()
+{
+   s_the.ensure_instance();
+}
+
 PS2MouseDevice& PS2MouseDevice::the()
 {
     return *s_the;

+ 1 - 0
Kernel/Devices/PS2MouseDevice.h

@@ -40,6 +40,7 @@ public:
     PS2MouseDevice();
     virtual ~PS2MouseDevice() override;
 
+    static void create();
     static PS2MouseDevice& the();
 
     // ^CharacterDevice

+ 7 - 2
Kernel/Devices/SB16.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/Memory.h>
+#include <AK/Singleton.h>
 #include <AK/StringView.h>
 #include <Kernel/Devices/SB16.h>
 #include <Kernel/Thread.h>
@@ -76,13 +77,12 @@ void SB16::set_sample_rate(uint16_t hz)
     dsp_write((u8)hz);
 }
 
-static SB16* s_the;
+static AK::Singleton<SB16> s_the;
 
 SB16::SB16()
     : IRQHandler(SB16_DEFAULT_IRQ)
     , CharacterDevice(42, 42) // ### ?
 {
-    s_the = this;
     initialize();
 }
 
@@ -90,6 +90,11 @@ SB16::~SB16()
 {
 }
 
+void SB16::create()
+{
+    s_the.ensure_instance();
+}
+
 SB16& SB16::the()
 {
     return *s_the;

+ 1 - 0
Kernel/Devices/SB16.h

@@ -42,6 +42,7 @@ public:
     SB16();
     virtual ~SB16() override;
 
+    static void create();
     static SB16& the();
 
     // ^CharacterDevice

+ 30 - 21
Kernel/Devices/VMWareBackdoor.cpp

@@ -25,6 +25,8 @@
  */
 
 #include <AK/Assertions.h>
+#include <AK/OwnPtr.h>
+#include <AK/Singleton.h>
 #include <AK/String.h>
 #include <Kernel/Arch/i386/CPU.h>
 #include <Kernel/CommandLine.h>
@@ -80,33 +82,40 @@ inline void vmware_high_bandwidth_get(VMWareCommand& command)
                  : "+a"(command.ax), "+b"(command.bx), "+c"(command.cx), "+d"(command.dx), "+S"(command.si), "+D"(command.di));
 }
 
-static VMWareBackdoor* s_vmware_backdoor;
-
-static bool detect_presence()
+class VMWareBackdoorDetector
 {
-    VMWareCommand command;
-    command.bx = ~VMWARE_MAGIC;
-    command.command = VMWARE_CMD_GETVERSION;
-    vmware_out(command);
-    if (command.bx != VMWARE_MAGIC || command.ax == 0xFFFFFFFF)
-        return false;
-    return true;
-}
+public:
+    VMWareBackdoorDetector()
+    {
+        if (detect_presence())
+            m_backdoor = make<VMWareBackdoor>();
+    }
 
-VMWareBackdoor* VMWareBackdoor::initialize()
-{
-    ASSERT(s_vmware_backdoor == nullptr);
-    if (!detect_presence())
-        return nullptr;
+    VMWareBackdoor* get_instance()
+    {
+        return m_backdoor.ptr();
+    }
 
-    s_vmware_backdoor = new VMWareBackdoor;
-    klog() << "VMWare backdoor opened.";
-    return s_vmware_backdoor;
-}
+private:
+    static bool detect_presence()
+    {
+        VMWareCommand command;
+        command.bx = ~VMWARE_MAGIC;
+        command.command = VMWARE_CMD_GETVERSION;
+        vmware_out(command);
+        if (command.bx != VMWARE_MAGIC || command.ax == 0xFFFFFFFF)
+            return false;
+        return true;
+    }
+
+    OwnPtr<VMWareBackdoor> m_backdoor;
+};
+
+static AK::Singleton<VMWareBackdoorDetector> s_vmware_backdoor;
 
 VMWareBackdoor* VMWareBackdoor::the()
 {
-    return s_vmware_backdoor;
+    return s_vmware_backdoor->get_instance();
 }
 
 VMWareBackdoor::VMWareBackdoor()

+ 1 - 2
Kernel/Devices/VMWareBackdoor.h

@@ -63,9 +63,9 @@ class VMWareBackdoor {
     AK_MAKE_ETERNAL;
 
 public:
+    VMWareBackdoor();
     static VMWareBackdoor* the();
 
-    static VMWareBackdoor* initialize();
     bool vmmouse_is_absolute() const;
     void enable_absolute_vmmouse();
     void disable_absolute_vmmouse();
@@ -76,7 +76,6 @@ public:
 private:
     void send_high_bandwidth(VMWareCommand& command);
     void get_high_bandwidth(VMWareCommand& command);
-    VMWareBackdoor();
     bool detect_vmmouse();
     bool m_vmmouse_absolute { false };
 };

+ 7 - 10
Kernel/FileSystem/DevPtsFS.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <AK/StringView.h>
 #include <Kernel/FileSystem/DevPtsFS.h>
@@ -45,14 +46,10 @@ DevPtsFS::~DevPtsFS()
 {
 }
 
-static HashTable<unsigned>* ptys;
+static AK::Singleton<HashTable<unsigned>> s_ptys;
 
 bool DevPtsFS::initialize()
 {
-    if (ptys == nullptr) {
-        ptys = new HashTable<unsigned>();
-    }
-
     m_root_inode = adopt(*new DevPtsFSInode(*this, 1));
     m_root_inode->m_metadata.inode = { fsid(), 1 };
     m_root_inode->m_metadata.mode = 0040555;
@@ -104,12 +101,12 @@ RefPtr<Inode> DevPtsFS::get_inode(InodeIdentifier inode_id) const
 
 void DevPtsFS::register_slave_pty(SlavePTY& slave_pty)
 {
-    ptys->set(slave_pty.index());
+    s_ptys->set(slave_pty.index());
 }
 
 void DevPtsFS::unregister_slave_pty(SlavePTY& slave_pty)
 {
-    ptys->remove(slave_pty.index());
+    s_ptys->remove(slave_pty.index());
 }
 
 DevPtsFSInode::DevPtsFSInode(DevPtsFS& fs, unsigned index)
@@ -144,7 +141,7 @@ KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEn
     callback({ ".", identifier(), 0 });
     callback({ "..", identifier(), 0 });
 
-    for (unsigned pty_index : *ptys) {
+    for (unsigned pty_index : *s_ptys) {
         String name = String::number(pty_index);
         InodeIdentifier identifier = { fsid(), pty_index_to_inode_index(pty_index) };
         callback({ name, identifier, 0 });
@@ -157,7 +154,7 @@ KResultOr<size_t> DevPtsFSInode::directory_entry_count() const
 {
     ASSERT(identifier().index() == 1);
 
-    return 2 + ptys->size();
+    return 2 + s_ptys->size();
 }
 
 RefPtr<Inode> DevPtsFSInode::lookup(StringView name)
@@ -170,7 +167,7 @@ RefPtr<Inode> DevPtsFSInode::lookup(StringView name)
     auto& fs = static_cast<DevPtsFS&>(this->fs());
 
     auto pty_index = name.to_uint();
-    if (pty_index.has_value() && ptys->contains(pty_index.value())) {
+    if (pty_index.has_value() && s_ptys->contains(pty_index.value())) {
         return fs.get_inode({ fsid(), pty_index_to_inode_index(pty_index.value()) });
     }
 

+ 3 - 3
Kernel/FileSystem/FIFO.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/HashTable.h>
+#include <AK/Singleton.h>
 #include <AK/StdLibExtras.h>
 #include <AK/StringView.h>
 #include <Kernel/FileSystem/FIFO.h>
@@ -37,11 +38,10 @@
 
 namespace Kernel {
 
+static AK::Singleton<Lockable<HashTable<FIFO*>>> s_table;
+
 static Lockable<HashTable<FIFO*>>& all_fifos()
 {
-    static Lockable<HashTable<FIFO*>>* s_table;
-    if (!s_table)
-        s_table = new Lockable<HashTable<FIFO*>>;
     return *s_table;
 }
 

+ 2 - 3
Kernel/FileSystem/FileSystem.cpp

@@ -26,6 +26,7 @@
 
 #include <AK/Assertions.h>
 #include <AK/HashMap.h>
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <AK/StringView.h>
 #include <Kernel/FileSystem/FileSystem.h>
@@ -37,12 +38,10 @@
 namespace Kernel {
 
 static u32 s_lastFileSystemID;
-static HashMap<u32, FS*>* s_fs_map;
+static AK::Singleton<HashMap<u32, FS*>> s_fs_map;
 
 static HashMap<u32, FS*>& all_fses()
 {
-    if (!s_fs_map)
-        s_fs_map = new HashMap<u32, FS*>();
     return *s_fs_map;
 }
 

+ 3 - 4
Kernel/FileSystem/Inode.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/NonnullRefPtrVector.h>
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <AK/StringView.h>
 #include <Kernel/FileSystem/Custody.h>
@@ -38,15 +39,13 @@
 namespace Kernel {
 
 static SpinLock s_all_inodes_lock;
+static AK::Singleton<InlineLinkedList<Inode>> s_list;
 
 InlineLinkedList<Inode>& Inode::all_with_lock()
 {
     ASSERT(s_all_inodes_lock.is_locked());
 
-    static InlineLinkedList<Inode>* list;
-    if (!list)
-        list = new InlineLinkedList<Inode>;
-    return *list;
+    return *s_list;
 }
 
 void Inode::sync()

+ 7 - 3
Kernel/FileSystem/VirtualFileSystem.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/LexicalPath.h>
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <Kernel/Devices/BlockDevice.h>
 #include <Kernel/FileSystem/Custody.h>
@@ -40,13 +41,17 @@
 
 namespace Kernel {
 
-static VFS* s_the;
+static AK::Singleton<VFS> s_the;
 static constexpr int symlink_recursion_limit { 5 }; // FIXME: increase?
 static constexpr int root_mount_flags = MS_NODEV | MS_NOSUID | MS_RDONLY;
 
+void VFS::initialize()
+{
+    s_the.ensure_instance();
+}
+
 VFS& VFS::the()
 {
-    ASSERT(s_the);
     return *s_the;
 }
 
@@ -55,7 +60,6 @@ VFS::VFS()
 #ifdef VFS_DEBUG
     klog() << "VFS: Constructing VFS";
 #endif
-    s_the = this;
 }
 
 VFS::~VFS()

+ 1 - 0
Kernel/FileSystem/VirtualFileSystem.h

@@ -78,6 +78,7 @@ public:
         int m_flags;
     };
 
+    static void initialize();
     static VFS& the();
 
     VFS();

+ 4 - 3
Kernel/Interrupts/APIC.cpp

@@ -26,6 +26,7 @@
 
 #include <AK/Assertions.h>
 #include <AK/Memory.h>
+#include <AK/Singleton.h>
 #include <AK/StringView.h>
 #include <AK/Types.h>
 #include <Kernel/ACPI/Parser.h>
@@ -68,7 +69,7 @@
 
 namespace Kernel {
 
-static APIC* s_apic;
+static AK::Singleton<APIC> s_apic;
 
 class APICIPIInterruptHandler final : public GenericInterruptHandler {
 public:
@@ -132,7 +133,7 @@ private:
 
 bool APIC::initialized()
 {
-    return (s_apic != nullptr);
+    return s_apic.is_initialized();
 }
 
 APIC& APIC::the()
@@ -144,7 +145,7 @@ APIC& APIC::the()
 void APIC::initialize()
 {
     ASSERT(!APIC::initialized());
-    s_apic = new APIC();
+    s_apic.ensure_instance();
 }
 
 PhysicalAddress APIC::get_base()

+ 3 - 3
Kernel/Net/IPv4Socket.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <Kernel/FileSystem/FileDescription.h>
 #include <Kernel/Net/ARP.h>
@@ -45,11 +46,10 @@
 
 namespace Kernel {
 
+static AK::Singleton<Lockable<HashTable<IPv4Socket*>>> s_table;
+
 Lockable<HashTable<IPv4Socket*>>& IPv4Socket::all_sockets()
 {
-    static Lockable<HashTable<IPv4Socket*>>* s_table;
-    if (!s_table)
-        s_table = new Lockable<HashTable<IPv4Socket*>>;
     return *s_table;
 }
 

+ 3 - 3
Kernel/Net/LocalSocket.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <Kernel/FileSystem/FileDescription.h>
 #include <Kernel/FileSystem/VirtualFileSystem.h>
@@ -37,11 +38,10 @@
 
 namespace Kernel {
 
+static AK::Singleton<Lockable<InlineLinkedList<LocalSocket>>> s_list;
+
 Lockable<InlineLinkedList<LocalSocket>>& LocalSocket::all_sockets()
 {
-    static Lockable<InlineLinkedList<LocalSocket>>* s_list;
-    if (!s_list)
-        s_list = new Lockable<InlineLinkedList<LocalSocket>>();
     return *s_list;
 }
 

+ 4 - 4
Kernel/Net/LoopbackAdapter.cpp

@@ -24,16 +24,16 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/Net/LoopbackAdapter.h>
 
 namespace Kernel {
 
+static AK::Singleton<LoopbackAdapter> s_loopback;
+
 LoopbackAdapter& LoopbackAdapter::the()
 {
-    static LoopbackAdapter* the;
-    if (!the)
-        the = new LoopbackAdapter;
-    return *the;
+    return *s_loopback;
 }
 
 LoopbackAdapter::LoopbackAdapter()

+ 1 - 3
Kernel/Net/LoopbackAdapter.h

@@ -33,15 +33,13 @@ namespace Kernel {
 class LoopbackAdapter final : public NetworkAdapter {
     AK_MAKE_ETERNAL
 public:
+    LoopbackAdapter();
     static LoopbackAdapter& the();
 
     virtual ~LoopbackAdapter() override;
 
     virtual void send_raw(ReadonlyBytes) override;
     virtual const char* class_name() const override { return "LoopbackAdapter"; }
-
-private:
-    LoopbackAdapter();
 };
 
 }

+ 4 - 4
Kernel/Net/NetworkAdapter.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/HashTable.h>
+#include <AK/Singleton.h>
 #include <AK/StringBuilder.h>
 #include <Kernel/Heap/kmalloc.h>
 #include <Kernel/Lock.h>
@@ -37,12 +38,11 @@
 
 namespace Kernel {
 
+static AK::Singleton<Lockable<HashTable<NetworkAdapter*>>> s_table;
+
 static Lockable<HashTable<NetworkAdapter*>>& all_adapters()
 {
-    static Lockable<HashTable<NetworkAdapter*>>* table;
-    if (!table)
-        table = new Lockable<HashTable<NetworkAdapter*>>;
-    return *table;
+    return *s_table;
 }
 
 void NetworkAdapter::for_each(Function<void(NetworkAdapter&)> callback)

+ 4 - 4
Kernel/Net/Routing.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/HashMap.h>
+#include <AK/Singleton.h>
 #include <Kernel/Net/LoopbackAdapter.h>
 #include <Kernel/Net/Routing.h>
 #include <Kernel/Thread.h>
@@ -33,12 +34,11 @@
 
 namespace Kernel {
 
+static AK::Singleton<Lockable<HashMap<IPv4Address, MACAddress>>> s_arp_table;
+
 Lockable<HashMap<IPv4Address, MACAddress>>& arp_table()
 {
-    static Lockable<HashMap<IPv4Address, MACAddress>>* the;
-    if (!the)
-        the = new Lockable<HashMap<IPv4Address, MACAddress>>;
-    return *the;
+    return *s_arp_table;
 }
 
 bool RoutingDecision::is_zero() const

+ 7 - 8
Kernel/Net/TCPSocket.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <AK/Time.h>
 #include <Kernel/Devices/RandomDevice.h>
 #include <Kernel/FileSystem/FileDescription.h>
@@ -62,20 +63,18 @@ void TCPSocket::set_state(State new_state)
     }
 }
 
+static AK::Singleton<Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>> s_socket_closing;
+
 Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>& TCPSocket::closing_sockets()
 {
-    static Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>* s_map;
-    if (!s_map)
-        s_map = new Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>;
-    return *s_map;
+    return *s_socket_closing;
 }
 
+static AK::Singleton<Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>> s_socket_tuples;
+
 Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>& TCPSocket::sockets_by_tuple()
 {
-    static Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>* s_map;
-    if (!s_map)
-        s_map = new Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>;
-    return *s_map;
+    return *s_socket_tuples;
 }
 
 RefPtr<TCPSocket> TCPSocket::from_tuple(const IPv4SocketTuple& tuple)

+ 3 - 3
Kernel/Net/UDPSocket.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/Devices/RandomDevice.h>
 #include <Kernel/Net/NetworkAdapter.h>
 #include <Kernel/Net/Routing.h>
@@ -41,11 +42,10 @@ void UDPSocket::for_each(Function<void(const UDPSocket&)> callback)
         callback(*it.value);
 }
 
+static AK::Singleton<Lockable<HashMap<u16, UDPSocket*>>> s_map;
+
 Lockable<HashMap<u16, UDPSocket*>>& UDPSocket::sockets_by_port()
 {
-    static Lockable<HashMap<u16, UDPSocket*>>* s_map;
-    if (!s_map)
-        s_map = new Lockable<HashMap<u16, UDPSocket*>>;
     return *s_map;
 }
 

+ 2 - 4
Kernel/Random.cpp

@@ -25,6 +25,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/Arch/i386/CPU.h>
 #include <Kernel/Devices/RandomDevice.h>
 #include <Kernel/Random.h>
@@ -32,13 +33,10 @@
 
 namespace Kernel {
 
-static KernelRng* s_the;
+static AK::Singleton<KernelRng> s_the;
 
 KernelRng& KernelRng::the()
 {
-    if (!s_the) {
-        s_the = new KernelRng;
-    }
     return *s_the;
 }
 

+ 1 - 2
Kernel/Random.h

@@ -127,6 +127,7 @@ class KernelRng : public Lockable<FortunaPRNG<Crypto::Cipher::AESCipher, Crypto:
     AK_MAKE_ETERNAL;
 
 public:
+    KernelRng();
     static KernelRng& the();
 
     void wait_for_entropy();
@@ -134,8 +135,6 @@ public:
     void wake_if_ready();
 
 private:
-    KernelRng();
-
     WaitQueue m_seed_queue;
 };
 

+ 4 - 4
Kernel/SharedBuffer.cpp

@@ -24,17 +24,17 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/Process.h>
 #include <Kernel/SharedBuffer.h>
 
 namespace Kernel {
 
+static AK::Singleton<Lockable<HashMap<int, NonnullOwnPtr<SharedBuffer>>>> s_map;
+
 Lockable<HashMap<int, NonnullOwnPtr<SharedBuffer>>>& shared_buffers()
 {
-    static Lockable<HashMap<int, NonnullOwnPtr<SharedBuffer>>>* map;
-    if (!map)
-        map = new Lockable<HashMap<int, NonnullOwnPtr<SharedBuffer>>>;
-    return *map;
+    return *s_map;
 }
 
 void SharedBuffer::sanity_check(const char* what)

+ 2 - 3
Kernel/TTY/PTYMultiplexer.cpp

@@ -26,6 +26,7 @@
 
 #include "PTYMultiplexer.h"
 #include "MasterPTY.h"
+#include <AK/Singleton.h>
 #include <Kernel/FileSystem/FileDescription.h>
 #include <Kernel/Process.h>
 #include <LibC/errno_numbers.h>
@@ -35,18 +36,16 @@
 namespace Kernel {
 
 static const unsigned s_max_pty_pairs = 8;
-static PTYMultiplexer* s_the;
+static AK::Singleton<PTYMultiplexer> s_the;
 
 PTYMultiplexer& PTYMultiplexer::the()
 {
-    ASSERT(s_the);
     return *s_the;
 }
 
 PTYMultiplexer::PTYMultiplexer()
     : CharacterDevice(5, 2)
 {
-    s_the = this;
     m_freelist.ensure_capacity(s_max_pty_pairs);
     for (int i = s_max_pty_pairs; i > 0; --i)
         m_freelist.unchecked_append(i - 1);

+ 4 - 0
Kernel/TTY/PTYMultiplexer.h

@@ -40,6 +40,10 @@ public:
     PTYMultiplexer();
     virtual ~PTYMultiplexer() override;
 
+    static void initialize()
+    {
+        the();
+    }
     static PTYMultiplexer& the();
 
     // ^CharacterDevice

+ 10 - 10
Kernel/Time/TimeManagement.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/Singleton.h>
 #include <Kernel/ACPI/Parser.h>
 #include <Kernel/CommandLine.h>
 #include <Kernel/Scheduler.h>
@@ -39,12 +40,11 @@
 
 namespace Kernel {
 
-static TimeManagement* s_time_management;
+static AK::Singleton<TimeManagement> s_the;
 
 TimeManagement& TimeManagement::the()
 {
-    ASSERT(s_time_management);
-    return *s_time_management;
+    return *s_the;
 }
 
 bool TimeManagement::is_system_timer(const HardwareTimer& timer) const
@@ -65,11 +65,9 @@ time_t TimeManagement::epoch_time() const
 
 void TimeManagement::initialize()
 {
-    ASSERT(!s_time_management);
-    if (kernel_command_line().lookup("time").value_or("modern") == "legacy")
-        s_time_management = new TimeManagement(false);
-    else
-        s_time_management = new TimeManagement(true);
+    ASSERT(!s_the.is_initialized());
+    s_the.ensure_instance();
+
 }
 time_t TimeManagement::seconds_since_boot() const
 {
@@ -90,8 +88,9 @@ time_t TimeManagement::boot_time() const
     return RTC::boot_time();
 }
 
-TimeManagement::TimeManagement(bool probe_non_legacy_hardware_timers)
+TimeManagement::TimeManagement()
 {
+    bool probe_non_legacy_hardware_timers = !(kernel_command_line().lookup("time").value_or("modern") == "legacy");
     if (ACPI::is_enabled()) {
         if (!ACPI::Parser::the()->x86_specific_flags().cmos_rtc_not_present) {
             RTC::initialize();
@@ -117,7 +116,8 @@ TimeManagement::TimeManagement(bool probe_non_legacy_hardware_timers)
 
 timeval TimeManagement::now_as_timeval()
 {
-    return { s_time_management->epoch_time(), (suseconds_t)s_time_management->ticks_this_second() * (suseconds_t)1000 };
+    auto* time_management = s_the.ptr();
+    return { time_management->epoch_time(), (suseconds_t)time_management->ticks_this_second() * (suseconds_t)1000 };
 }
 
 Vector<HardwareTimer*> TimeManagement::scan_and_initialize_periodic_timers()

+ 1 - 1
Kernel/Time/TimeManagement.h

@@ -42,6 +42,7 @@ class TimeManagement {
     AK_MAKE_ETERNAL;
 
 public:
+    TimeManagement();
     static bool initialized();
     static void initialize();
     static TimeManagement& the();
@@ -63,7 +64,6 @@ public:
     static timeval now_as_timeval();
 
 private:
-    explicit TimeManagement(bool probe_non_legacy_hardware_timers);
     bool probe_and_set_legacy_hardware_timers();
     bool probe_and_set_non_legacy_hardware_timers();
     Vector<HardwareTimer*> scan_and_initialize_periodic_timers();

+ 2 - 3
Kernel/TimerQueue.cpp

@@ -27,18 +27,17 @@
 #include <AK/Function.h>
 #include <AK/NonnullOwnPtr.h>
 #include <AK/OwnPtr.h>
+#include <AK/Singleton.h>
 #include <Kernel/Scheduler.h>
 #include <Kernel/Time/TimeManagement.h>
 #include <Kernel/TimerQueue.h>
 
 namespace Kernel {
 
-static TimerQueue* s_the;
+static AK::Singleton<TimerQueue> s_the;
 
 TimerQueue& TimerQueue::the()
 {
-    if (!s_the)
-        s_the = new TimerQueue;
     return *s_the;
 }
 

+ 1 - 2
Kernel/TimerQueue.h

@@ -56,6 +56,7 @@ struct Timer {
 
 class TimerQueue {
 public:
+    TimerQueue();
     static TimerQueue& the();
 
     TimerId add_timer(NonnullOwnPtr<Timer>&&);
@@ -64,8 +65,6 @@ public:
     void fire();
 
 private:
-    TimerQueue();
-
     void update_next_timer_due();
 
     u64 microseconds_to_ticks(u64 micro_seconds) { return micro_seconds * (m_ticks_per_second / 1'000'000); }

+ 4 - 0
Kernel/VM/MemoryManager.cpp

@@ -53,6 +53,10 @@ extern FlatPtr end_of_kernel_bss;
 
 namespace Kernel {
 
+// NOTE: We can NOT use AK::Singleton for this class, because
+// MemoryManager::initialize is called *before* global constructors are
+// run. If we do, then AK::Singleton would get re-initialized, causing
+// the memory manager to be initialized twice!
 static MemoryManager* s_the;
 RecursiveSpinLock s_mm_lock;
 

+ 4 - 4
Kernel/VM/PageDirectory.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/Memory.h>
+#include <AK/Singleton.h>
 #include <Kernel/Process.h>
 #include <Kernel/Random.h>
 #include <Kernel/Thread.h>
@@ -37,13 +38,12 @@ static const FlatPtr userspace_range_base = 0x00800000;
 static const FlatPtr userspace_range_ceiling = 0xbe000000;
 static const FlatPtr kernelspace_range_base = 0xc0800000;
 
+static AK::Singleton<HashMap<u32, PageDirectory*>> s_cr3_map;
+
 static HashMap<u32, PageDirectory*>& cr3_map()
 {
     ASSERT_INTERRUPTS_DISABLED();
-    static HashMap<u32, PageDirectory*>* map;
-    if (!map)
-        map = new HashMap<u32, PageDirectory*>;
-    return *map;
+    return *s_cr3_map;
 }
 
 RefPtr<PageDirectory> PageDirectory::find_by_cr3(u32 cr3)

+ 8 - 9
Kernel/init.cpp

@@ -135,10 +135,10 @@ extern "C" [[noreturn]] void init()
     InterruptManagement::initialize();
     ACPI::initialize();
 
-    new VFS;
-    new KeyboardDevice;
-    new PS2MouseDevice;
-    new Console;
+    VFS::initialize();
+    KeyboardDevice::initialize();
+    PS2MouseDevice::create();
+    Console::initialize();
 
     klog() << "Starting SerenityOS...";
 
@@ -146,7 +146,7 @@ extern "C" [[noreturn]] void init()
 
     TimeManagement::initialize();
 
-    new NullDevice;
+    NullDevice::initialize();
     if (!get_serial_debug())
         new SerialDevice(SERIAL_COM1_ADDR, 64);
     new SerialDevice(SERIAL_COM2_ADDR, 65);
@@ -228,7 +228,7 @@ void init_stage2()
         });
 
         if (bxvga_found) {
-            new BXVGADevice;
+            BXVGADevice::initialize();
         } else {
             if (multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB || multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT) {
                 new MBVGADevice(
@@ -237,7 +237,7 @@ void init_stage2()
                     multiboot_info_ptr->framebuffer_width,
                     multiboot_info_ptr->framebuffer_height);
             } else {
-                new BXVGADevice;
+                BXVGADevice::initialize();
             }
         }
     }
@@ -252,9 +252,8 @@ void init_stage2()
     new ZeroDevice;
     new FullDevice;
     new RandomDevice;
-    new PTYMultiplexer;
+    PTYMultiplexer::initialize();
     new SB16;
-    VMWareBackdoor::initialize();
 
     bool force_pio = kernel_command_line().contains("force_pio");