linker: Purge block allocator memory when possible
If all allocated memory from a block allocator is freed, it is a good
opportunity to purge all the pages allocated to reduce lingering dirty
pages.
Memory saving varies with the platform and what processes are running.
Measuring right after boot, this saves ~1.8MB on cuttelfish and ~1.3MB
on a 32-bit ARM device.
Bug: 112073665
Test: Boot and check memory usage with 'showmap'.
Change-Id: I53769e0ec9699f0b3645cdf281a2c0bbffb98676
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index dca944e..34df9a5 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -52,7 +52,8 @@
: block_size_(
round_up(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size, 16)),
page_list_(nullptr),
- free_block_list_(nullptr)
+ free_block_list_(nullptr),
+ allocated_(0)
{}
void* LinkerBlockAllocator::alloc() {
@@ -73,6 +74,8 @@
memset(block_info, 0, block_size_);
+ ++allocated_;
+
return block_info;
}
@@ -101,6 +104,11 @@
block_info->num_free_blocks = 1;
free_block_list_ = block_info;
+
+ --allocated_;
+ if (allocated_ == 0) {
+ free_all_pages();
+ }
}
void LinkerBlockAllocator::protect_all(int prot) {
@@ -151,3 +159,18 @@
abort();
}
+
+void LinkerBlockAllocator::free_all_pages() {
+ if (allocated_) {
+ abort();
+ }
+
+ LinkerBlockAllocatorPage* page = page_list_;
+ while (page) {
+ LinkerBlockAllocatorPage* next = page->next;
+ munmap(page, PAGE_SIZE);
+ page = next;
+ }
+ page_list_ = nullptr;
+ free_block_list_ = nullptr;
+}