Skip to content

Commit

Permalink
Kernel: Switch singletons to use new Singleton class
Browse files Browse the repository at this point in the history
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 SerenityOS#3226
  • Loading branch information
tomuta authored and awesomekling committed Aug 25, 2020
1 parent ba6e4fb commit d895828
Show file tree
Hide file tree
Showing 46 changed files with 221 additions and 170 deletions.
8 changes: 4 additions & 4 deletions AK/FlyString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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)
Expand Down
48 changes: 30 additions & 18 deletions Kernel/Singleton.h → AK/Singleton.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,54 @@

#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();
AK::atomic_store(&m_obj, obj, AK::memory_order_release);
} 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);
}
}
Expand Down Expand Up @@ -93,18 +119,4 @@ class Singleton {
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 change: 1 addition & 0 deletions Kernel/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const CommandLine& kernel_command_line()

void CommandLine::initialize(const String& string)
{
ASSERT(!s_the);
s_the = new CommandLine(string);
}

Expand Down
12 changes: 8 additions & 4 deletions Kernel/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions Kernel/Console.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 7 additions & 2 deletions Kernel/Devices/BXVGADevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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()
{
Expand All @@ -67,7 +73,6 @@ BXVGADevice::BXVGADevice()
: BlockDevice(29, 0)

{
s_the = this;
m_framebuffer_address = PhysicalAddress(find_framebuffer_address());
set_safe_resolution();
}
Expand Down
1 change: 1 addition & 0 deletions Kernel/Devices/BXVGADevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace Kernel {
class BXVGADevice final : public BlockDevice {
AK_MAKE_ETERNAL
public:
static void initialize();
static BXVGADevice& the();

BXVGADevice();
Expand Down
5 changes: 2 additions & 3 deletions Kernel/Devices/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
11 changes: 7 additions & 4 deletions Kernel/Devices/KeyboardDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -335,20 +336,22 @@ 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;
}

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)
Expand Down
1 change: 1 addition & 0 deletions Kernel/Devices/KeyboardDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class KeyboardDevice final : public IRQHandler
public:
using Event = KeyEvent;

static void initialize();
static KeyboardDevice& the();

virtual ~KeyboardDevice() override;
Expand Down
10 changes: 7 additions & 3 deletions Kernel/Devices/NullDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
1 change: 1 addition & 0 deletions Kernel/Devices/NullDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class NullDevice final : public CharacterDevice {
NullDevice();
virtual ~NullDevice() override;

static void initialize();
static NullDevice& the();

private:
Expand Down
10 changes: 5 additions & 5 deletions Kernel/Devices/PATAChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 7 additions & 2 deletions Kernel/Devices/PS2MouseDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -56,20 +57,24 @@ 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();
}

PS2MouseDevice::~PS2MouseDevice()
{
}

void PS2MouseDevice::create()
{
s_the.ensure_instance();
}

PS2MouseDevice& PS2MouseDevice::the()
{
return *s_the;
Expand Down
1 change: 1 addition & 0 deletions Kernel/Devices/PS2MouseDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class PS2MouseDevice final : public IRQHandler
PS2MouseDevice();
virtual ~PS2MouseDevice() override;

static void create();
static PS2MouseDevice& the();

// ^CharacterDevice
Expand Down
Loading

0 comments on commit d895828

Please sign in to comment.