diff options
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r-- | linker/linker.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index d0c740baf..428dd25de 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -536,6 +536,10 @@ class SizeBasedAllocator { allocator_.free(ptr); } + static void purge() { + allocator_.purge(); + } + private: static LinkerBlockAllocator allocator_; }; @@ -553,6 +557,10 @@ class TypeBasedAllocator { static void free(T* ptr) { SizeBasedAllocator<sizeof(T)>::free(ptr); } + + static void purge() { + SizeBasedAllocator<sizeof(T)>::purge(); + } }; class LoadTask { @@ -2074,6 +2082,8 @@ void* do_dlopen(const char* name, int flags, ns == nullptr ? "(null)" : ns->get_name(), ns); + auto purge_guard = android::base::make_scope_guard([&]() { purge_unused_memory(); }); + auto failure_guard = android::base::make_scope_guard( [&]() { LD_LOG(kLogDlopen, "... dlopen failed: %s", linker_get_error_buffer()); }); @@ -4069,3 +4079,17 @@ android_namespace_t* get_exported_namespace(const char* name) { } return it->second; } + +void purge_unused_memory() { + // For now, we only purge the memory used by LoadTask because we know those + // are temporary objects. + // + // Purging other LinkerBlockAllocator hardly yields much because they hold + // information about namespaces and opened libraries, which are not freed + // when the control leaves the linker. + // + // Purging BionicAllocator may give us a few dirty pages back, but those pages + // would be already zeroed out, so they compress easily in ZRAM. Therefore, + // it is not worth munmap()'ing those pages. + TypeBasedAllocator<LoadTask>::purge(); +} |