diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2019-01-25 22:39:27 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-01-25 22:39:27 +0000 |
commit | fbd6f3c7969a2a72e9384d3b50d037e414eedabf (patch) | |
tree | c96fa4939220ef9cda003204946db18557036510 /linker | |
parent | 65502ea8e0a9b5ca1dd326b29f25bfbfdfed646d (diff) | |
parent | dac328ad5118417a4622952ed8c62b3943612d09 (diff) | |
download | android_bionic-fbd6f3c7969a2a72e9384d3b50d037e414eedabf.tar.gz android_bionic-fbd6f3c7969a2a72e9384d3b50d037e414eedabf.tar.bz2 android_bionic-fbd6f3c7969a2a72e9384d3b50d037e414eedabf.zip |
Merge changes Iece631a5,I53769e0e
* changes:
linker: Reduce number of mmap()/prctl() calls in block allocator
linker: Purge block allocator memory when possible
Diffstat (limited to 'linker')
-rw-r--r-- | linker/linker_block_allocator.cpp | 42 | ||||
-rw-r--r-- | linker/linker_block_allocator.h | 5 |
2 files changed, 38 insertions, 9 deletions
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp index dca944e9c..27f1e3800 100644 --- a/linker/linker_block_allocator.cpp +++ b/linker/linker_block_allocator.cpp @@ -33,6 +33,9 @@ #include <sys/prctl.h> #include <unistd.h> +static constexpr size_t kAllocateSize = PAGE_SIZE * 100; +static_assert(kAllocateSize % PAGE_SIZE == 0, "Invalid kAllocateSize."); + // the multiplier should be power of 2 static constexpr size_t round_up(size_t size, size_t multiplier) { return (size + (multiplier - 1)) & ~(multiplier-1); @@ -40,7 +43,7 @@ static constexpr size_t round_up(size_t size, size_t multiplier) { struct LinkerBlockAllocatorPage { LinkerBlockAllocatorPage* next; - uint8_t bytes[PAGE_SIZE - 16] __attribute__((aligned(16))); + uint8_t bytes[kAllocateSize - 16] __attribute__((aligned(16))); }; struct FreeBlockInfo { @@ -52,7 +55,8 @@ LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size) : 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 +77,8 @@ void* LinkerBlockAllocator::alloc() { memset(block_info, 0, block_size_); + ++allocated_; + return block_info; } @@ -101,32 +107,37 @@ void LinkerBlockAllocator::free(void* block) { block_info->num_free_blocks = 1; free_block_list_ = block_info; + + --allocated_; + if (allocated_ == 0) { + free_all_pages(); + } } void LinkerBlockAllocator::protect_all(int prot) { for (LinkerBlockAllocatorPage* page = page_list_; page != nullptr; page = page->next) { - if (mprotect(page, PAGE_SIZE, prot) == -1) { + if (mprotect(page, kAllocateSize, prot) == -1) { abort(); } } } void LinkerBlockAllocator::create_new_page() { - static_assert(sizeof(LinkerBlockAllocatorPage) == PAGE_SIZE, + static_assert(sizeof(LinkerBlockAllocatorPage) == kAllocateSize, "Invalid sizeof(LinkerBlockAllocatorPage)"); LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>( - mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)); + mmap(nullptr, kAllocateSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)); if (page == MAP_FAILED) { abort(); // oom } - prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, PAGE_SIZE, "linker_alloc"); + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, kAllocateSize, "linker_alloc"); FreeBlockInfo* first_block = reinterpret_cast<FreeBlockInfo*>(page->bytes); first_block->next_block = free_block_list_; - first_block->num_free_blocks = (PAGE_SIZE - sizeof(LinkerBlockAllocatorPage*))/block_size_; + first_block->num_free_blocks = (kAllocateSize - sizeof(LinkerBlockAllocatorPage*))/block_size_; free_block_list_ = first_block; @@ -142,7 +153,7 @@ LinkerBlockAllocatorPage* LinkerBlockAllocator::find_page(void* block) { LinkerBlockAllocatorPage* page = page_list_; while (page != nullptr) { const uint8_t* page_ptr = reinterpret_cast<const uint8_t*>(page); - if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + PAGE_SIZE)) { + if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + kAllocateSize)) { return page; } @@ -151,3 +162,18 @@ LinkerBlockAllocatorPage* LinkerBlockAllocator::find_page(void* block) { abort(); } + +void LinkerBlockAllocator::free_all_pages() { + if (allocated_) { + abort(); + } + + LinkerBlockAllocatorPage* page = page_list_; + while (page) { + LinkerBlockAllocatorPage* next = page->next; + munmap(page, kAllocateSize); + page = next; + } + page_list_ = nullptr; + free_block_list_ = nullptr; +} diff --git a/linker/linker_block_allocator.h b/linker/linker_block_allocator.h index bd44fc829..85e6bd962 100644 --- a/linker/linker_block_allocator.h +++ b/linker/linker_block_allocator.h @@ -53,10 +53,12 @@ class LinkerBlockAllocator { private: void create_new_page(); LinkerBlockAllocatorPage* find_page(void* block); + void free_all_pages(); size_t block_size_; LinkerBlockAllocatorPage* page_list_; void* free_block_list_; + size_t allocated_; DISALLOW_COPY_AND_ASSIGN(LinkerBlockAllocator); }; @@ -73,7 +75,8 @@ class LinkerBlockAllocator { * with size 513 this allocator will use 516 (520 for lp64) bytes of data * where generalized implementation is going to use 1024 sized blocks. * - * 2. This allocator does not munmap allocated memory, where LinkerMemoryAllocator does. + * 2. Unless all allocated memory is freed, this allocator does not munmap + * allocated memory, where LinkerMemoryAllocator does. * * 3. This allocator provides mprotect services to the user, where LinkerMemoryAllocator * always treats it's memory as READ|WRITE. |