mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-27 05:05:32 +03:00
Kernel: Remove the kmalloc_eternal heap :^)
This was a premature optimization from the early days of SerenityOS. The eternal heap was a simple bump pointer allocator over a static byte array. My original idea was to avoid heap fragmentation and improve data locality, but both ideas were rooted in cargo culting, not data. We would reserve 4 MiB at boot and only ended up using ~256 KiB, wasting the rest. This patch replaces all kmalloc_eternal() usage by regular kmalloc().
This commit is contained in:
parent
a1be135891
commit
ac7ce12123
Notes:
sideshowbarker
2024-07-17 22:02:59 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/ac7ce121236
11
AK/kmalloc.h
11
AK/kmalloc.h
@ -38,17 +38,6 @@ inline size_t malloc_good_size(size_t size) { return size; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef KERNEL
|
||||
# define AK_MAKE_ETERNAL \
|
||||
public: \
|
||||
void* operator new(size_t size) { return kmalloc_eternal(size); } \
|
||||
void operator delete(void*, size_t) { VERIFY_NOT_REACHED(); } \
|
||||
\
|
||||
private:
|
||||
#else
|
||||
# define AK_MAKE_ETERNAL
|
||||
#endif
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
inline void* kmalloc_array(Checked<size_t> a, Checked<size_t> b)
|
||||
|
@ -13,7 +13,6 @@
|
||||
namespace Kernel::USB {
|
||||
|
||||
class USBManagement {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
USBManagement();
|
||||
|
@ -42,7 +42,6 @@ enum class AHCIResetMode {
|
||||
};
|
||||
|
||||
class CommandLine {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
static void early_initialize(const char* cmd_line);
|
||||
|
@ -13,7 +13,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class ConsoleDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -24,7 +24,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class DeviceManagement {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
DeviceManagement();
|
||||
|
@ -11,7 +11,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class FullDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -31,7 +31,6 @@ class KeyboardClient;
|
||||
class HIDManagement {
|
||||
friend class KeyboardDevice;
|
||||
friend class MouseDevice;
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
HIDManagement();
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Kernel {
|
||||
class KCOVDevice final : public BlockDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -13,7 +13,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class MemoryDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -11,7 +11,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class NullDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -30,7 +30,7 @@ UNMAP_AFTER_INIT void PCISerialDevice::detect()
|
||||
// If this is the first port of the first pci serial device, store it as the debug PCI serial port (TODO: Make this configurable somehow?)
|
||||
if (!is_available())
|
||||
s_the = serial_device;
|
||||
// NOTE: We intentionally leak the reference to serial_device here, as it is eternal
|
||||
// NOTE: We intentionally leak the reference to serial_device here.
|
||||
}
|
||||
|
||||
dmesgln("PCISerialDevice: Found {} @ {}", board_definition.name, device_identifier.address());
|
||||
|
@ -14,7 +14,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class PCISerialDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static void detect();
|
||||
static SerialDevice& the();
|
||||
|
@ -11,7 +11,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class RandomDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class SerialDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -39,7 +39,6 @@ struct VMWareCommand {
|
||||
};
|
||||
|
||||
class VMWareBackdoor {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
VMWareBackdoor();
|
||||
|
@ -11,7 +11,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class ZeroDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -33,7 +33,6 @@ struct UidAndGid {
|
||||
};
|
||||
|
||||
class VirtualFileSystem {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
// Required to be at least 8 by POSIX
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
|
||||
|
@ -403,7 +403,6 @@ private:
|
||||
JsonObjectSerializer<KBufferBuilder> json { builder };
|
||||
json.add("kmalloc_allocated", stats.bytes_allocated);
|
||||
json.add("kmalloc_available", stats.bytes_free);
|
||||
json.add("kmalloc_eternal_allocated", stats.bytes_eternal);
|
||||
json.add("user_physical_allocated", system_memory.user_physical_pages_used);
|
||||
json.add("user_physical_available", system_memory.user_physical_pages - system_memory.user_physical_pages_used);
|
||||
json.add("user_physical_committed", system_memory.user_physical_pages_committed);
|
||||
|
@ -21,7 +21,6 @@ struct BochsDisplayMMIORegisters;
|
||||
|
||||
class BochsGraphicsAdapter final : public GenericGraphicsAdapter
|
||||
, public PCI::Device {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class GraphicsManagement;
|
||||
|
||||
private:
|
||||
|
@ -17,7 +17,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class FramebufferDevice final : public GenericFramebufferDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -16,7 +16,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class GenericFramebufferDevice : public BlockDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
|
@ -27,7 +27,6 @@ class GraphicsManagement {
|
||||
friend class IntelNativeGraphicsAdapter;
|
||||
friend class VGACompatibleAdapter;
|
||||
friend class Graphics::VirtIOGPU::GraphicsAdapter;
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
static GraphicsManagement& the();
|
||||
|
@ -47,7 +47,6 @@ enum RegisterIndex {
|
||||
|
||||
class IntelNativeGraphicsAdapter final
|
||||
: public VGACompatibleAdapter {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
struct PLLSettings {
|
||||
bool is_valid() const { return (n != 0 && m1 != 0 && m2 != 0 && p1 != 0 && p2 != 0); }
|
||||
|
@ -17,7 +17,6 @@ namespace Kernel {
|
||||
|
||||
class VGACompatibleAdapter : public GenericGraphicsAdapter
|
||||
, public PCI::Device {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static NonnullRefPtr<VGACompatibleAdapter> initialize_with_preset_resolution(PCI::DeviceIdentifier const&, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch);
|
||||
static NonnullRefPtr<VGACompatibleAdapter> initialize(PCI::DeviceIdentifier const&);
|
||||
|
@ -35,7 +35,6 @@ class FramebufferDevice;
|
||||
class GraphicsAdapter final
|
||||
: public GenericGraphicsAdapter
|
||||
, public VirtIO::Device {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class FramebufferDevice;
|
||||
|
||||
public:
|
||||
|
@ -29,7 +29,6 @@ static constexpr size_t CHUNK_SIZE = 64;
|
||||
#endif
|
||||
|
||||
#define POOL_SIZE (2 * MiB)
|
||||
#define ETERNAL_RANGE_SIZE (4 * MiB)
|
||||
|
||||
namespace std {
|
||||
const nothrow_t nothrow;
|
||||
@ -307,18 +306,13 @@ READONLY_AFTER_INIT static KmallocGlobalData* g_kmalloc_global;
|
||||
alignas(KmallocGlobalData) static u8 g_kmalloc_global_heap[sizeof(KmallocGlobalData)];
|
||||
|
||||
// Treat the heap as logically separate from .bss
|
||||
__attribute__((section(".heap"))) static u8 kmalloc_eternal_heap[ETERNAL_RANGE_SIZE];
|
||||
__attribute__((section(".heap"))) static u8 kmalloc_pool_heap[POOL_SIZE];
|
||||
|
||||
static size_t g_kmalloc_bytes_eternal = 0;
|
||||
static size_t g_kmalloc_call_count;
|
||||
static size_t g_kfree_call_count;
|
||||
static size_t g_nested_kfree_calls;
|
||||
bool g_dump_kmalloc_stacks;
|
||||
|
||||
static u8* s_next_eternal_ptr;
|
||||
READONLY_AFTER_INIT static u8* s_end_of_eternal_range;
|
||||
|
||||
void kmalloc_enable_expand()
|
||||
{
|
||||
g_kmalloc_global->enable_expansion();
|
||||
@ -335,28 +329,10 @@ static inline void kmalloc_verify_nospinlock_held()
|
||||
UNMAP_AFTER_INIT void kmalloc_init()
|
||||
{
|
||||
// Zero out heap since it's placed after end_of_kernel_bss.
|
||||
memset(kmalloc_eternal_heap, 0, sizeof(kmalloc_eternal_heap));
|
||||
memset(kmalloc_pool_heap, 0, sizeof(kmalloc_pool_heap));
|
||||
g_kmalloc_global = new (g_kmalloc_global_heap) KmallocGlobalData(kmalloc_pool_heap, sizeof(kmalloc_pool_heap));
|
||||
|
||||
s_lock.initialize();
|
||||
|
||||
s_next_eternal_ptr = kmalloc_eternal_heap;
|
||||
s_end_of_eternal_range = s_next_eternal_ptr + sizeof(kmalloc_eternal_heap);
|
||||
}
|
||||
|
||||
void* kmalloc_eternal(size_t size)
|
||||
{
|
||||
kmalloc_verify_nospinlock_held();
|
||||
|
||||
size = round_up_to_power_of_two(size, sizeof(void*));
|
||||
|
||||
SpinlockLocker lock(s_lock);
|
||||
void* ptr = s_next_eternal_ptr;
|
||||
s_next_eternal_ptr += size;
|
||||
VERIFY(s_next_eternal_ptr < s_end_of_eternal_range);
|
||||
g_kmalloc_bytes_eternal += size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* kmalloc(size_t size)
|
||||
@ -493,7 +469,6 @@ void get_kmalloc_stats(kmalloc_stats& stats)
|
||||
SpinlockLocker lock(s_lock);
|
||||
stats.bytes_allocated = g_kmalloc_global->allocated_bytes();
|
||||
stats.bytes_free = g_kmalloc_global->free_bytes();
|
||||
stats.bytes_eternal = g_kmalloc_bytes_eternal;
|
||||
stats.kmalloc_call_count = g_kmalloc_call_count;
|
||||
stats.kfree_call_count = g_kfree_call_count;
|
||||
}
|
||||
|
@ -39,14 +39,12 @@ enum class align_val_t : size_t {};
|
||||
};
|
||||
|
||||
void kmalloc_init();
|
||||
[[gnu::malloc, gnu::returns_nonnull, gnu::alloc_size(1)]] void* kmalloc_eternal(size_t);
|
||||
|
||||
void kfree_sized(void*, size_t);
|
||||
|
||||
struct kmalloc_stats {
|
||||
size_t bytes_allocated;
|
||||
size_t bytes_free;
|
||||
size_t bytes_eternal;
|
||||
size_t kmalloc_call_count;
|
||||
size_t kfree_call_count;
|
||||
};
|
||||
|
@ -65,7 +65,7 @@ UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(Bytes buffer)
|
||||
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
s_symbol_count = (s_symbol_count << 4) | parse_hex_digit(*(bufptr++));
|
||||
s_symbols = static_cast<KernelSymbol*>(kmalloc_eternal(sizeof(KernelSymbol) * s_symbol_count));
|
||||
s_symbols = static_cast<KernelSymbol*>(kmalloc(sizeof(KernelSymbol) * s_symbol_count));
|
||||
++bufptr; // skip newline
|
||||
|
||||
dmesgln("Loading kernel symbol table...");
|
||||
|
@ -137,7 +137,6 @@ private:
|
||||
};
|
||||
|
||||
class MemoryManager {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class PageDirectory;
|
||||
friend class AnonymousVMObject;
|
||||
friend class Region;
|
||||
|
@ -13,7 +13,6 @@
|
||||
namespace Kernel::Memory {
|
||||
|
||||
class PhysicalRegion {
|
||||
AK_MAKE_ETERNAL;
|
||||
AK_MAKE_NONCOPYABLE(PhysicalRegion);
|
||||
AK_MAKE_NONMOVABLE(PhysicalRegion);
|
||||
|
||||
|
@ -17,7 +17,6 @@ namespace Kernel::Memory {
|
||||
// The allocator uses a buddy block scheme internally.
|
||||
|
||||
class PhysicalZone {
|
||||
AK_MAKE_ETERNAL;
|
||||
AK_MAKE_NONCOPYABLE(PhysicalZone);
|
||||
AK_MAKE_NONMOVABLE(PhysicalZone);
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class LoopbackAdapter final : public NetworkAdapter {
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
private:
|
||||
LoopbackAdapter(NonnullOwnPtr<KString>);
|
||||
|
||||
|
@ -20,7 +20,6 @@ namespace Kernel {
|
||||
class NetworkAdapter;
|
||||
class NetworkingManagement {
|
||||
friend class NetworkAdapter;
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
static NetworkingManagement& the();
|
||||
|
@ -120,7 +120,6 @@ private:
|
||||
};
|
||||
|
||||
class KernelRng : public FortunaPRNG<Crypto::Cipher::AESCipher, Crypto::Hash::SHA256, 256> {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
KernelRng();
|
||||
|
@ -23,7 +23,7 @@ class AHCIController final : public ATAController
|
||||
, public PCI::Device {
|
||||
friend class AHCIPortHandler;
|
||||
friend class AHCIPort;
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
UNMAP_AFTER_INIT static NonnullRefPtr<AHCIController> initialize(PCI::DeviceIdentifier const& pci_device_identifier);
|
||||
virtual ~AHCIController() override;
|
||||
|
@ -37,7 +37,7 @@ class IDEController;
|
||||
class IDEChannel : public RefCounted<IDEChannel>
|
||||
, public IRQHandler {
|
||||
friend class IDEController;
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
enum class ChannelType : u8 {
|
||||
Primary,
|
||||
|
@ -19,7 +19,6 @@ class AsyncBlockDeviceRequest;
|
||||
|
||||
class IDEController final : public ATAController
|
||||
, public PCI::Device {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static NonnullRefPtr<IDEController> initialize(PCI::DeviceIdentifier const&, bool force_pio);
|
||||
virtual ~IDEController() override;
|
||||
|
@ -18,7 +18,6 @@ namespace Kernel {
|
||||
class AsyncBlockDeviceRequest;
|
||||
|
||||
class RamdiskController final : public StorageController {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
public:
|
||||
static NonnullRefPtr<RamdiskController> initialize();
|
||||
|
@ -16,7 +16,7 @@ class RamdiskController;
|
||||
class RamdiskDevice final : public StorageDevice {
|
||||
friend class RamdiskController;
|
||||
friend class DeviceManagement;
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<RamdiskDevice> create(const RamdiskController&, NonnullOwnPtr<Memory::Region>&& region, int major, int minor);
|
||||
virtual ~RamdiskDevice() override;
|
||||
|
@ -22,7 +22,6 @@ namespace Kernel {
|
||||
class AsyncBlockDeviceRequest;
|
||||
class StorageDevice;
|
||||
class StorageController : public RefCounted<StorageController> {
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
virtual ~StorageController() = default;
|
||||
|
@ -19,7 +19,6 @@ namespace Kernel {
|
||||
|
||||
class PartitionTable;
|
||||
class StorageManagement {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
StorageManagement();
|
||||
|
@ -14,7 +14,6 @@
|
||||
namespace Kernel {
|
||||
|
||||
class ConsoleManagement {
|
||||
AK_MAKE_ETERNAL;
|
||||
friend class VirtualConsole;
|
||||
|
||||
public:
|
||||
|
@ -15,7 +15,6 @@ namespace Kernel {
|
||||
class MasterPTY;
|
||||
|
||||
class PTYMultiplexer final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
PTYMultiplexer();
|
||||
virtual ~PTYMultiplexer() override;
|
||||
|
@ -47,7 +47,6 @@ private:
|
||||
class VirtualConsole final : public TTY
|
||||
, public KeyboardClient
|
||||
, public VT::TerminalClient {
|
||||
AK_MAKE_ETERNAL
|
||||
friend class ConsoleManagement;
|
||||
friend class DeviceManagement;
|
||||
friend class ConsoleImpl;
|
||||
|
@ -29,7 +29,6 @@ enum class TimePrecision {
|
||||
};
|
||||
|
||||
class TimeManagement {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
public:
|
||||
TimeManagement();
|
||||
|
@ -87,7 +87,6 @@ void MemoryStatsWidget::refresh()
|
||||
auto json_result = JsonValue::from_string(file_contents).release_value_but_fixme_should_propagate_errors();
|
||||
auto const& json = json_result.as_object();
|
||||
|
||||
[[maybe_unused]] u32 kmalloc_eternal_allocated = json.get("kmalloc_eternal_allocated").to_u32();
|
||||
u32 kmalloc_allocated = json.get("kmalloc_allocated").to_u32();
|
||||
u32 kmalloc_available = json.get("kmalloc_available").to_u32();
|
||||
u64 user_physical_allocated = json.get("user_physical_allocated").to_u64();
|
||||
|
Loading…
Reference in New Issue
Block a user