mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
Add a kmalloc_eternal() for things that will never be destroyed.
This commit is contained in:
parent
d980ddc745
commit
9a086b2d35
Notes:
sideshowbarker
2024-07-19 18:35:26 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/9a086b2d358
20 changed files with 85 additions and 20 deletions
31
AK/Vector.h
31
AK/Vector.h
|
@ -6,16 +6,26 @@
|
|||
|
||||
namespace AK {
|
||||
|
||||
template<typename T> class Vector;
|
||||
template<typename T, typename Allocator> class Vector;
|
||||
|
||||
template<typename T>
|
||||
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<typename T, typename Allocator>
|
||||
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<T>;
|
||||
friend class Vector<T, Allocator>;
|
||||
|
||||
VectorImpl(size_t capacity) : m_capacity(capacity) { }
|
||||
|
||||
|
@ -53,7 +63,7 @@ private:
|
|||
size_t m_capacity;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename T, typename Allocator = KmallocAllocator>
|
||||
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<T>::create(newCapacity);
|
||||
auto newImpl = VectorImpl<T, Allocator>::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<T>* m_impl { nullptr };
|
||||
VectorImpl<T, Allocator>* m_impl { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using AK::Vector;
|
||||
|
||||
using AK::KmallocEternalAllocator;
|
||||
using AK::KmallocAllocator;
|
||||
|
|
|
@ -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)
|
||||
|
|
11
AK/kmalloc.h
11
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 <Kernel/kmalloc.h>
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ public:
|
|||
};
|
||||
|
||||
class Console final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static Console& the() PURE;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ public:
|
|||
};
|
||||
|
||||
class Keyboard final : public IRQHandler, public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static Keyboard& the() PURE;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Console.h"
|
||||
|
||||
class VirtualConsole final : public TTY, public KeyboardClient, public ConsoleImplementation {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
enum InitialContents { Cleared, AdoptCurrentVGABuffer };
|
||||
|
||||
|
|
|
@ -310,7 +310,7 @@ void flushGDT()
|
|||
|
||||
void gdt_init()
|
||||
{
|
||||
s_gdt = new Descriptor[256];
|
||||
s_gdt = static_cast<Descriptor*>(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<Descriptor*>(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<IRQHandler**>(kmalloc_eternal(sizeof(IRQHandler*) * 16));
|
||||
for (byte i = 0; i < 16; ++i) {
|
||||
s_irqHandler[i] = nullptr;
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ static byte parseHexDigit(char nibble)
|
|||
return 10 + (nibble - 'a');
|
||||
}
|
||||
|
||||
static Vector<KSym>* s_ksyms;
|
||||
static Vector<KSym, KmallocEternalAllocator>* s_ksyms;
|
||||
|
||||
Vector<KSym>& ksyms()
|
||||
Vector<KSym, KmallocEternalAllocator>& ksyms()
|
||||
{
|
||||
return *s_ksyms;
|
||||
}
|
||||
|
@ -68,7 +68,9 @@ const KSym* ksymbolicate(dword address)
|
|||
|
||||
static void loadKsyms(const ByteBuffer& buffer)
|
||||
{
|
||||
s_ksyms = new Vector<KSym>;
|
||||
// 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<KSym, KmallocEternalAllocator>;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -9,7 +9,7 @@ struct KSym {
|
|||
String name;
|
||||
};
|
||||
|
||||
Vector<KSym>& ksyms() PURE;
|
||||
Vector<KSym, KmallocEternalAllocator>& ksyms() PURE;
|
||||
const KSym* ksymbolicate(dword address) PURE;
|
||||
|
||||
struct system_t
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "CharacterDevice.h"
|
||||
|
||||
class FullDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
FullDevice();
|
||||
virtual ~FullDevice();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "CharacterDevice.h"
|
||||
|
||||
class NullDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
NullDevice();
|
||||
virtual ~NullDevice() override;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "CharacterDevice.h"
|
||||
|
||||
class RandomDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
RandomDevice();
|
||||
virtual ~RandomDevice() override;
|
||||
|
|
|
@ -28,6 +28,7 @@ inline constexpr dword encodedDevice(unsigned major, unsigned minor)
|
|||
}
|
||||
|
||||
class VirtualFileSystem {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
static void initializeGlobals();
|
||||
static SpinLock& lock();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "CharacterDevice.h"
|
||||
|
||||
class ZeroDevice final : public CharacterDevice {
|
||||
AK_MAKE_ETERNAL
|
||||
public:
|
||||
ZeroDevice();
|
||||
virtual ~ZeroDevice() override;
|
||||
|
|
Loading…
Reference in a new issue