diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2019-12-17 23:01:19 +0300 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-12-20 20:19:46 +0100 |
commit | d91c40de3b86640e554654ee28d5c0dec0c8e1eb (patch) | |
tree | dfc1c9d041de0aefdde0fe33f3f36c21aa748aa8 /Libraries/LibC/malloc.cpp | |
parent | ac007218bc69370b069284f586867c6f2afa4954 (diff) | |
download | serenity-d91c40de3b86640e554654ee28d5c0dec0c8e1eb.zip |
LibC: Make empty malloc blocks purgeable
Diffstat (limited to 'Libraries/LibC/malloc.cpp')
-rw-r--r-- | Libraries/LibC/malloc.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/Libraries/LibC/malloc.cpp b/Libraries/LibC/malloc.cpp index 0a7258cdba..df4a547e10 100644 --- a/Libraries/LibC/malloc.cpp +++ b/Libraries/LibC/malloc.cpp @@ -134,7 +134,7 @@ size_t malloc_good_size(size_t size) static void* os_alloc(size_t size, const char* name) { - return mmap_with_name(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, name); + return mmap_with_name(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_PURGEABLE, 0, 0, name); } static void os_free(void* ptr, size_t size) @@ -162,10 +162,18 @@ void* malloc(size_t size) if (auto* allocator = big_allocator_for_size(real_size)) { if (!allocator->blocks.is_empty()) { auto* block = allocator->blocks.take_last(); + int rc = madvise(block, real_size, MADV_SET_NONVOLATILE); + bool this_block_was_purged = rc == 1; + if (rc < 0) { + perror("madvise"); + ASSERT_NOT_REACHED(); + } if (mprotect(block, real_size, PROT_READ | PROT_WRITE) < 0) { perror("mprotect"); ASSERT_NOT_REACHED(); } + if (this_block_was_purged) + new (block) BigAllocationBlock(real_size); set_mmap_name(block, PAGE_SIZE, "malloc: BigAllocationBlock (reused)"); return &block->m_slot[0]; } @@ -185,11 +193,19 @@ void* malloc(size_t size) if (!block && allocator->empty_block_count) { block = allocator->empty_blocks[--allocator->empty_block_count]; - int rc = mprotect(block, PAGE_SIZE, PROT_READ | PROT_WRITE); + int rc = madvise(block, PAGE_SIZE, MADV_SET_NONVOLATILE); + bool this_block_was_purged = rc == 1; + if (rc < 0) { + perror("madvise"); + ASSERT_NOT_REACHED(); + } + rc = mprotect(block, PAGE_SIZE, PROT_READ | PROT_WRITE); if (rc < 0) { perror("mprotect"); ASSERT_NOT_REACHED(); } + if (this_block_was_purged) + new (block) ChunkedBlock(good_size); char buffer[64]; snprintf(buffer, sizeof(buffer), "malloc: ChunkedBlock(%zu) (reused)", good_size); set_mmap_name(block, PAGE_SIZE, buffer); @@ -246,6 +262,10 @@ void free(void* ptr) perror("mprotect"); ASSERT_NOT_REACHED(); } + if (madvise(block, PAGE_SIZE, MADV_SET_VOLATILE) != 0) { + perror("madvise"); + ASSERT_NOT_REACHED(); + } return; } } @@ -293,6 +313,7 @@ void free(void* ptr) snprintf(buffer, sizeof(buffer), "malloc: ChunkedBlock(%zu) (free)", good_size); set_mmap_name(block, PAGE_SIZE, buffer); mprotect(block, PAGE_SIZE, PROT_NONE); + madvise(block, PAGE_SIZE, MADV_SET_VOLATILE); return; } #ifdef MALLOC_DEBUG |