1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 08:08:12 +00:00

LibC: malloc() should use mmap() directly for allocations >= PAGE_SIZE.

This is a solid speedup on PNG loading, and basically everything else.
Once again I find a way to defer writing a better allocator for now. :^)
This commit is contained in:
Andreas Kling 2019-03-21 13:29:20 +01:00
parent 65348e7dc1
commit 93a6681388

View file

@ -21,7 +21,8 @@ extern "C" {
struct MallocHeader {
uint16_t first_chunk_index;
uint16_t chunk_count;
uint16_t chunk_count : 15;
bool is_mmap : 1;
size_t size;
uint32_t compute_xorcheck() const
@ -52,6 +53,23 @@ void* malloc(size_t size)
// We need space for the MallocHeader structure at the head of the block.
size_t real_size = size + sizeof(MallocHeader) + sizeof(MallocFooter);
if (real_size >= PAGE_SIZE) {
auto* memory = mmap(nullptr, real_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (memory == MAP_FAILED) {
fprintf(stderr, "malloc() failed to mmap() for a %u-byte allocation: %s", size, strerror(errno));
volatile char* crashme = (char*)0xf007d00d;
*crashme = 0;
return nullptr;
}
auto* header = (MallocHeader*)(memory);
byte* ptr = ((byte*)header) + sizeof(MallocHeader);
header->chunk_count = 0;
header->first_chunk_index = 0;
header->size = real_size;
header->is_mmap = true;
return ptr;
}
if (s_malloc_sum_free < real_size) {
fprintf(stderr, "malloc(): Out of memory\ns_malloc_sum_free=%u, real_size=%u\n", s_malloc_sum_free, real_size);
assert(false);
@ -90,6 +108,7 @@ void* malloc(size_t size)
byte* ptr = ((byte*)header) + sizeof(MallocHeader);
header->chunk_count = chunks_needed;
header->first_chunk_index = first_chunk;
header->is_mmap = false;
header->size = size;
auto* footer = (MallocFooter*)((byte*)header + (header->chunk_count * CHUNK_SIZE) - sizeof(MallocFooter));
@ -133,8 +152,15 @@ void free(void* ptr)
if (!ptr)
return;
validate_mallocation(ptr, "free()");
auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
if (header->is_mmap) {
int rc = munmap(header, header->size);
if (rc < 0)
fprintf(stderr, "free(): munmap(%p) for allocation %p with size %u failed: %s\n", header, ptr, header->size, strerror(errno));
return;
}
validate_mallocation(ptr, "free()");
for (unsigned i = header->first_chunk_index; i < (header->first_chunk_index + header->chunk_count); ++i)
s_malloc_map[i / 8] &= ~(1 << (i % 8));