From 9a086b2d3584f13d47e8d625035fe72cc2f3aea2 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 31 Oct 2018 23:19:15 +0100 Subject: [PATCH] Add a kmalloc_eternal() for things that will never be destroyed. --- AK/Vector.h | 31 ++++++++++++++++++--------- AK/kmalloc.cpp | 12 +++++++++++ AK/kmalloc.h | 11 ++++++++++ Kernel/Console.h | 1 + Kernel/Keyboard.h | 1 + Kernel/MemoryManager.h | 1 + Kernel/ProcFileSystem.cpp | 2 +- Kernel/Task.cpp | 2 +- Kernel/VirtualConsole.cpp | 2 +- Kernel/VirtualConsole.h | 1 + Kernel/i386.cpp | 6 +++--- Kernel/init.cpp | 9 +++++--- Kernel/kmalloc.cpp | 17 +++++++++++++++ Kernel/kmalloc.h | 2 ++ Kernel/system.h | 2 +- VirtualFileSystem/FullDevice.h | 1 + VirtualFileSystem/NullDevice.h | 1 + VirtualFileSystem/RandomDevice.h | 1 + VirtualFileSystem/VirtualFileSystem.h | 1 + VirtualFileSystem/ZeroDevice.h | 1 + 20 files changed, 85 insertions(+), 20 deletions(-) diff --git a/AK/Vector.h b/AK/Vector.h index 10b7ee5dcdd..8eb757100a5 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -6,16 +6,26 @@ namespace AK { -template class Vector; +template class Vector; -template +struct KmallocAllocator { + static void* allocate(size_t size) { return kmalloc(size); } + static void deallocate(void* ptr) { kfree(ptr); } +}; + +struct KmallocEternalAllocator { + static void* allocate(size_t size) { return kmalloc_eternal(size); } + static void deallocate(void*) { } +}; + +template class VectorImpl { public: ~VectorImpl() { } static VectorImpl* create(size_t capacity) { size_t size = sizeof(VectorImpl) + sizeof(T) * capacity; - void* slot = kmalloc(size); + void* slot = Allocator::allocate(size); new (slot) VectorImpl(capacity); return (VectorImpl*)slot; } @@ -39,7 +49,7 @@ public: } private: - friend class Vector; + friend class Vector; VectorImpl(size_t capacity) : m_capacity(capacity) { } @@ -53,7 +63,7 @@ private: size_t m_capacity; }; -template +template class Vector { public: Vector() { } @@ -79,7 +89,7 @@ public: for (size_t i = 0; i < size(); ++i) { at(i).~T(); } - kfree(m_impl); + Allocator::deallocate(m_impl); m_impl = nullptr; } @@ -150,14 +160,14 @@ public: if (capacity() >= neededCapacity) return; size_t newCapacity = paddedCapacity(neededCapacity); - auto newImpl = VectorImpl::create(newCapacity); + auto newImpl = VectorImpl::create(newCapacity); if (m_impl) { newImpl->m_size = m_impl->m_size; for (size_t i = 0; i < size(); ++i) { new (newImpl->slot(i)) T(move(m_impl->at(i))); m_impl->at(i).~T(); } - kfree(m_impl); + Allocator::deallocate(m_impl); } m_impl = newImpl; } @@ -198,10 +208,11 @@ private: return max(size_t(4), capacity + (capacity / 4) + 4); } - VectorImpl* m_impl { nullptr }; + VectorImpl* m_impl { nullptr }; }; } using AK::Vector; - +using AK::KmallocEternalAllocator; +using AK::KmallocAllocator; diff --git a/AK/kmalloc.cpp b/AK/kmalloc.cpp index 80b662304f5..3a5200dc23f 100644 --- a/AK/kmalloc.cpp +++ b/AK/kmalloc.cpp @@ -39,6 +39,11 @@ void* krealloc(void* ptr, size_t size) return realloc(ptr, size); } +void* kmalloc_eternal(size_t size) +{ + return kmalloc(size); +} + } #else @@ -59,6 +64,13 @@ void* kmalloc(size_t size) return SimpleMalloc::allocate(size); } +void* kmalloc_eternal(size_t size) +{ + if (!size) + return nullptr; + return SimpleMalloc::allocate(size); +} + void kfree(void* ptr) { if (!ptr) diff --git a/AK/kmalloc.h b/AK/kmalloc.h index 02b66c2aabc..f62b6ea677b 100644 --- a/AK/kmalloc.h +++ b/AK/kmalloc.h @@ -2,6 +2,15 @@ #include "Compiler.h" +#if defined(SERENITY) && defined(KERNEL) +#define AK_MAKE_ETERNAL \ +public: \ + void* operator new(size_t size) { return kmalloc_eternal(size); } \ +private: +#else +#define AK_MAKE_ETERNAL +#endif + #ifdef SERENITY #ifdef KERNEL #include @@ -14,6 +23,7 @@ void* kcalloc(size_t nmemb, size_t size); void* kmalloc(size_t size) MALLOC_ATTR; void kfree(void* ptr); void* krealloc(void* ptr, size_t size); +void* kmalloc_eternal(size_t) MALLOC_ATTR; } @@ -61,6 +71,7 @@ void* kcalloc(size_t nmemb, size_t size); void* kmalloc(size_t size) MALLOC_ATTR; void kfree(void* ptr); void* krealloc(void* ptr, size_t size); +void* kmalloc_eternal(size_t) MALLOC_ATTR; } diff --git a/Kernel/Console.h b/Kernel/Console.h index c870b086d58..ff225bf42b8 100644 --- a/Kernel/Console.h +++ b/Kernel/Console.h @@ -11,6 +11,7 @@ public: }; class Console final : public CharacterDevice { + AK_MAKE_ETERNAL public: static Console& the() PURE; diff --git a/Kernel/Keyboard.h b/Kernel/Keyboard.h index 3b8e75c7472..7f374b840ac 100644 --- a/Kernel/Keyboard.h +++ b/Kernel/Keyboard.h @@ -13,6 +13,7 @@ public: }; class Keyboard final : public IRQHandler, public CharacterDevice { + AK_MAKE_ETERNAL public: static Keyboard& the() PURE; diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 0e749cbb535..c8e6a9ca5fa 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -36,6 +36,7 @@ bool copyToZone(Zone&, const void* data, size_t); #define MM MemoryManager::the() class MemoryManager { + AK_MAKE_ETERNAL friend ByteBuffer procfs$mm(); public: static MemoryManager& the() PURE; diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 64b2e6dc35a..d8ba73f983f 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -174,7 +174,7 @@ ByteBuffer procfs$kmalloc() InterruptDisabler disabler; auto buffer = ByteBuffer::createUninitialized(128); char* ptr = (char*)buffer.pointer(); - ptr += ksprintf(ptr, "alloc: %u\nfree: %u\n", sum_alloc, sum_free); + ptr += ksprintf(ptr, "eternal: %u\nallocated: %u\nfree: %u\n", kmalloc_sum_eternal, sum_alloc, sum_free); buffer.trim(ptr - (char*)buffer.pointer()); return buffer; } diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 8d26e9c02c9..818e137782e 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -454,7 +454,7 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring, if (isRing0()) { // FIXME: This memory is leaked. // But uh, there's also no kernel task termination, so I guess it's not technically leaked... - dword stackBottom = (dword)kmalloc(defaultStackSize); + dword stackBottom = (dword)kmalloc_eternal(defaultStackSize); m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8; m_tss.esp = m_stackTop0; } else { diff --git a/Kernel/VirtualConsole.cpp b/Kernel/VirtualConsole.cpp index b6479493e6a..433b438d485 100644 --- a/Kernel/VirtualConsole.cpp +++ b/Kernel/VirtualConsole.cpp @@ -22,7 +22,7 @@ VirtualConsole::VirtualConsole(unsigned index, InitialContents initialContents) , m_index(index) { s_consoles[index] = this; - m_buffer = (byte*)kmalloc(80 * 25 * 2); + m_buffer = (byte*)kmalloc_eternal(80 * 25 * 2); dbgprintf("VirtualConsole %u @ %p, m_buffer = %p\n", index, this, m_buffer); if (initialContents == AdoptCurrentVGABuffer) { memcpy(m_buffer, s_vgaBuffer, 80 * 25 * 2); diff --git a/Kernel/VirtualConsole.h b/Kernel/VirtualConsole.h index 79b4f0b5101..e89d503c27f 100644 --- a/Kernel/VirtualConsole.h +++ b/Kernel/VirtualConsole.h @@ -5,6 +5,7 @@ #include "Console.h" class VirtualConsole final : public TTY, public KeyboardClient, public ConsoleImplementation { + AK_MAKE_ETERNAL public: enum InitialContents { Cleared, AdoptCurrentVGABuffer }; diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index d2c968fa06c..562fd9a67bf 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -310,7 +310,7 @@ void flushGDT() void gdt_init() { - s_gdt = new Descriptor[256]; + s_gdt = static_cast(kmalloc_eternal(sizeof(Descriptor) * 256)); s_gdtLength = 5; s_gdtr.address = s_gdt; @@ -378,7 +378,7 @@ asm( void idt_init() { - s_idt = new Descriptor[256]; + s_idt = static_cast(kmalloc_eternal(sizeof(Descriptor) * 256)); s_idtr.address = s_idt; s_idtr.size = 0x100 * 8; @@ -406,7 +406,7 @@ void idt_init() registerInterruptHandler(0x57, irq7_handler); - s_irqHandler = new IRQHandler*[16]; + s_irqHandler = static_cast(kmalloc_eternal(sizeof(IRQHandler*) * 16)); for (byte i = 0; i < 16; ++i) { s_irqHandler[i] = nullptr; } diff --git a/Kernel/init.cpp b/Kernel/init.cpp index ea510179bf3..c9f4706d854 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -48,9 +48,9 @@ static byte parseHexDigit(char nibble) return 10 + (nibble - 'a'); } -static Vector* s_ksyms; +static Vector* s_ksyms; -Vector& ksyms() +Vector& ksyms() { return *s_ksyms; } @@ -68,7 +68,9 @@ const KSym* ksymbolicate(dword address) static void loadKsyms(const ByteBuffer& buffer) { - s_ksyms = new Vector; + // FIXME: It's gross that this vector grows dynamically rather than being sized-to-fit. + // We're wasting that eternal kmalloc memory. + s_ksyms = new Vector; auto* bufptr = (const char*)buffer.pointer(); auto* startOfName = bufptr; dword address = 0; @@ -83,6 +85,7 @@ static void loadKsyms(const ByteBuffer& buffer) break; } } + // FIXME: The Strings here should be eternally allocated too. ksyms().append({ address, String(startOfName, bufptr - startOfName) }); ++bufptr; } diff --git a/Kernel/kmalloc.cpp b/Kernel/kmalloc.cpp index 6d6825a5e2d..b65f4b59369 100644 --- a/Kernel/kmalloc.cpp +++ b/Kernel/kmalloc.cpp @@ -22,15 +22,21 @@ typedef struct #define CHUNK_SIZE 128 #define POOL_SIZE (1024 * 1024) +#define ETERNAL_BASE_PHYSICAL 0x300000 #define BASE_PHYS 0x200000 PRIVATE BYTE alloc_map[POOL_SIZE / CHUNK_SIZE / 8]; volatile DWORD sum_alloc = 0; volatile DWORD sum_free = POOL_SIZE; +volatile size_t kmalloc_sum_eternal = 0; + +static byte* s_next_eternal_ptr; bool is_kmalloc_address(void* ptr) { + if (ptr >= (byte*)ETERNAL_BASE_PHYSICAL && ptr < s_next_eternal_ptr) + return true; return ptr >= (void*)BASE_PHYS && ptr <= ((void*)BASE_PHYS + POOL_SIZE); } @@ -40,8 +46,19 @@ kmalloc_init() memset( &alloc_map, 0, sizeof(alloc_map) ); memset( (void *)BASE_PHYS, 0, POOL_SIZE ); + kmalloc_sum_eternal = 0; sum_alloc = 0; sum_free = POOL_SIZE; + + s_next_eternal_ptr = (byte*)ETERNAL_BASE_PHYSICAL; +} + +void* kmalloc_eternal(size_t size) +{ + void* ptr = s_next_eternal_ptr; + s_next_eternal_ptr += size; + kmalloc_sum_eternal += size; + return ptr; } PUBLIC void * diff --git a/Kernel/kmalloc.h b/Kernel/kmalloc.h index e0b5ac49557..72c295f465c 100644 --- a/Kernel/kmalloc.h +++ b/Kernel/kmalloc.h @@ -2,12 +2,14 @@ void kmalloc_init(); void *kmalloc(DWORD size) __attribute__ ((malloc)); +void* kmalloc_eternal(size_t) __attribute__ ((malloc)); void kfree(void*); bool is_kmalloc_address(void*); extern volatile DWORD sum_alloc; extern volatile DWORD sum_free; +extern volatile dword kmalloc_sum_eternal; inline void* operator new(size_t, void* p) { return p; } inline void* operator new[](size_t, void* p) { return p; } diff --git a/Kernel/system.h b/Kernel/system.h index 0839f28d45c..16fbc1220f3 100644 --- a/Kernel/system.h +++ b/Kernel/system.h @@ -9,7 +9,7 @@ struct KSym { String name; }; -Vector& ksyms() PURE; +Vector& ksyms() PURE; const KSym* ksymbolicate(dword address) PURE; struct system_t diff --git a/VirtualFileSystem/FullDevice.h b/VirtualFileSystem/FullDevice.h index f52dc5b8cb2..9ab209d2f9d 100644 --- a/VirtualFileSystem/FullDevice.h +++ b/VirtualFileSystem/FullDevice.h @@ -3,6 +3,7 @@ #include "CharacterDevice.h" class FullDevice final : public CharacterDevice { + AK_MAKE_ETERNAL public: FullDevice(); virtual ~FullDevice(); diff --git a/VirtualFileSystem/NullDevice.h b/VirtualFileSystem/NullDevice.h index 74cffee6861..3c22b1f7814 100644 --- a/VirtualFileSystem/NullDevice.h +++ b/VirtualFileSystem/NullDevice.h @@ -3,6 +3,7 @@ #include "CharacterDevice.h" class NullDevice final : public CharacterDevice { + AK_MAKE_ETERNAL public: NullDevice(); virtual ~NullDevice() override; diff --git a/VirtualFileSystem/RandomDevice.h b/VirtualFileSystem/RandomDevice.h index eaa91c223dc..e91c324c19b 100644 --- a/VirtualFileSystem/RandomDevice.h +++ b/VirtualFileSystem/RandomDevice.h @@ -3,6 +3,7 @@ #include "CharacterDevice.h" class RandomDevice final : public CharacterDevice { + AK_MAKE_ETERNAL public: RandomDevice(); virtual ~RandomDevice() override; diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index 07a8d9a442b..1ce34a36044 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -28,6 +28,7 @@ inline constexpr dword encodedDevice(unsigned major, unsigned minor) } class VirtualFileSystem { + AK_MAKE_ETERNAL public: static void initializeGlobals(); static SpinLock& lock(); diff --git a/VirtualFileSystem/ZeroDevice.h b/VirtualFileSystem/ZeroDevice.h index f83cae7d473..ca0fa7828bb 100644 --- a/VirtualFileSystem/ZeroDevice.h +++ b/VirtualFileSystem/ZeroDevice.h @@ -3,6 +3,7 @@ #include "CharacterDevice.h" class ZeroDevice final : public CharacterDevice { + AK_MAKE_ETERNAL public: ZeroDevice(); virtual ~ZeroDevice() override;