diff options
author | 2024-10-31 16:21:45 +0000 | |
---|---|---|
committer | 2024-12-19 17:27:36 +0000 | |
commit | f9a04e35ce5dbd1b3cf5704ac7574ec4d537aeaa (patch) | |
tree | 053ea8af257f501120b91236480c18f6daee5257 | |
parent | 3df940f58e08880c9537870de56d5f876eac439f (diff) |
Also use two-step mmap allocation on target if 'addr' hint is provided.
The issues isn't Ubuntu specific. All new kernels are affected.
The hint isn't ignored intentionally by the kernel.
It is unintended side effect of other changes.
Bug: 373931708
Test: m
Change-Id: I5060f69a41c59d61065343fe28d394757adaa061
-rw-r--r-- | libartbase/base/mem_map.cc | 18 | ||||
-rw-r--r-- | libartbase/base/utils.cc | 17 |
2 files changed, 21 insertions, 14 deletions
diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc index 5c785618ba..bdc3c3dc27 100644 --- a/libartbase/base/mem_map.cc +++ b/libartbase/base/mem_map.cc @@ -30,10 +30,9 @@ #include <memory> #include <sstream> +#include "allocator.h" #include "android-base/stringprintf.h" #include "android-base/unique_fd.h" - -#include "allocator.h" #include "bit_utils.h" #include "globals.h" #include "logging.h" // For VLOG_IS_ON. @@ -346,15 +345,18 @@ MemMap MemMap::MapAnonymous(const char* name, void* actual = nullptr; - // New Ubuntu linux kerners seem to ignore the address hint, so make it a firm request. - // Whereas old kernels allocated at 'addr' if provided, newer kernels seem to ignore it. - // However, MAP_FIXED_NOREPLACE tells the kernel it must allocate at the address or fail. - // Do this only on host since android kernels still obey the hint without flag (for now). - if (!kIsTargetBuild && (flags & MAP_FIXED) == 0 && addr != nullptr) { +#if defined(__linux__) + // Recent kernels have a bug where the address hint might be ignored. + // See https://lore.kernel.org/all/20241115215256.578125-1-kaleshsingh@google.com/ + // We use MAP_FIXED_NOREPLACE to tell the kernel it must allocate at the address or fail. + // If the fixed-address allocation fails, we fallback to the default path (random address). + // Therefore, non-null 'addr' still behaves as hint-only as far as ART api is concerned. + if ((flags & MAP_FIXED) == 0 && addr != nullptr && IsKernelVersionAtLeast(4, 17)) { actual = MapInternal( addr, page_aligned_byte_count, prot, flags | MAP_FIXED_NOREPLACE, fd.get(), 0, low_4gb); - // If the fixed-address allocation failed, fallback to the default path (random address). } +#endif // __linux__ + if (actual == nullptr || actual == MAP_FAILED) { actual = MapInternal(addr, page_aligned_byte_count, prot, flags, fd.get(), 0, low_4gb); } diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc index 2c95986809..aca7a0d47d 100644 --- a/libartbase/base/utils.cc +++ b/libartbase/base/utils.cc @@ -167,12 +167,17 @@ bool FlushCpuCaches(void* begin, void* end) { #if defined(__linux__) bool IsKernelVersionAtLeast(int reqd_major, int reqd_minor) { - struct utsname uts; - int major, minor; - CHECK_EQ(uname(&uts), 0); - CHECK_EQ(strcmp(uts.sysname, "Linux"), 0); - CHECK_EQ(sscanf(uts.release, "%d.%d:", &major, &minor), 2); - return major > reqd_major || (major == reqd_major && minor >= reqd_minor); + static auto version = []() -> std::pair<int, int> { + struct utsname uts; + int res, major, minor; + res = uname(&uts); + CHECK_EQ(res, 0); + CHECK_EQ(strcmp(uts.sysname, "Linux"), 0); + res = sscanf(uts.release, "%d.%d:", &major, &minor); + CHECK_EQ(res, 2); + return std::make_pair(major, minor); + }(); + return version >= std::make_pair(reqd_major, reqd_minor); } #endif |