summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp24
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();
+}