diff options
-rw-r--r-- | build/art.go | 9 | ||||
-rw-r--r-- | runtime/gc/collector/mark_compact.cc | 62 | ||||
-rw-r--r-- | runtime/read_barrier_config.h | 12 |
3 files changed, 65 insertions, 18 deletions
diff --git a/build/art.go b/build/art.go index 970af8ab75..cc5371989f 100644 --- a/build/art.go +++ b/build/art.go @@ -70,10 +70,11 @@ func globalFlags(ctx android.LoadHookContext) ([]string, []string) { if !ctx.Config().IsEnvFalse("ART_USE_GENERATIONAL_CC") { cflags = append(cflags, "-DART_USE_GENERATIONAL_CC=1") } - // For now force CC as we don't want to make userfaultfd GC the default. - // Eventually, make it such that we force CC only if ART_USE_READ_BARRIER - // was set to true explicitly during build time. - cflags = append(cflags, "-DART_FORCE_USE_READ_BARRIER=1") + // Force CC only if ART_USE_READ_BARRIER was set to true explicitly during + // build time. + if ctx.Config().IsEnvTrue("ART_USE_READ_BARRIER") { + cflags = append(cflags, "-DART_FORCE_USE_READ_BARRIER=1") + } tlab = true } else if gcType == "CMC" { tlab = true diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc index d73418b8b3..71e5a13638 100644 --- a/runtime/gc/collector/mark_compact.cc +++ b/runtime/gc/collector/mark_compact.cc @@ -16,10 +16,13 @@ #include "mark_compact-inl.h" +#include "android-base/file.h" +#include "android-base/properties.h" #include "base/quasi_atomic.h" #include "base/systrace.h" #include "base/utils.h" #include "gc/accounting/mod_union_table-inl.h" +#include "gc/collector_type.h" #include "gc/reference_processor.h" #include "gc/space/bump_pointer_space.h" #include "gc/task_processor.h" @@ -36,6 +39,7 @@ #include <sys/ioctl.h> #include <sys/mman.h> #include <unistd.h> + #include <fstream> #include <numeric> @@ -58,6 +62,12 @@ #endif // __NR_userfaultfd #endif // __BIONIC__ +namespace { + +using ::android::base::GetBoolProperty; + +} + namespace art { // We require MREMAP_DONTUNMAP functionality of the mremap syscall, which was @@ -82,11 +92,28 @@ static bool gHaveMremapDontunmap = IsKernelVersionAtLeast(5, 13) || HaveMremapDo // userfaultfd is enabled. static const bool gKernelHasFaultRetry = kIsTargetAndroid || IsKernelVersionAtLeast(5, 7); -#ifndef ART_FORCE_USE_READ_BARRIER -static bool ShouldUseUserfaultfd() { -#if !defined(__linux__) - return false; -#endif +// The other cases are defined as constexpr in runtime/read_barrier_config.h +#if !defined(ART_FORCE_USE_READ_BARRIER) && defined(ART_USE_READ_BARRIER) +// Returns collector type asked to be used on the cmdline. +static gc::CollectorType FetchCmdlineGcType() { + std::string argv; + gc::CollectorType gc_type = gc::CollectorType::kCollectorTypeNone; + if (android::base::ReadFileToString("/proc/self/cmdline", &argv)) { + if (argv.find("-Xgc:CMC") != std::string::npos) { + gc_type = gc::CollectorType::kCollectorTypeCMC; + } else if (argv.find("-Xgc:CC") != std::string::npos) { + gc_type = gc::CollectorType::kCollectorTypeCC; + } + } + return gc_type; +} + +static bool SysPropSaysUffdGc() { + return GetBoolProperty("persist.device_config.runtime_native_boot.enable_uffd_gc", + GetBoolProperty("ro.dalvik.vm.enable_uffd_gc", false)); +} + +static bool KernelSupportsUffd() { int fd = syscall(__NR_userfaultfd, O_CLOEXEC | UFFD_USER_MODE_ONLY); // On non-android devices we may not have the kernel patches that restrict // userfaultfd to user mode. But that is not a security concern as we are @@ -101,15 +128,26 @@ static bool ShouldUseUserfaultfd() { return false; } } -#endif -// The other cases are defined as a constexpr in runtime/read_barrier_config.h -#ifndef ART_FORCE_USE_READ_BARRIER -const bool gUseReadBarrier = (kUseBakerReadBarrier || kUseTableLookupReadBarrier) - && !ShouldUseUserfaultfd(); -#ifdef ART_DEFAULT_GC_TYPE_IS_CMC -const bool gUseUserfaultfd = !gUseReadBarrier; +static bool ShouldUseUserfaultfd() { + static_assert(kUseBakerReadBarrier || kUseTableLookupReadBarrier); +#ifdef __linux__ + // Use CMC/CC if that is being explicitly asked for on cmdline. Otherwise, + // always use CC on host. On target, use CMC only if system properties says so + // and the kernel supports it. + gc::CollectorType gc_type = FetchCmdlineGcType(); + return gc_type == gc::CollectorType::kCollectorTypeCMC || + (gc_type == gc::CollectorType::kCollectorTypeNone && + kIsTargetAndroid && + SysPropSaysUffdGc() && + KernelSupportsUffd()); +#else + return false; #endif +} + +const bool gUseUserfaultfd = ShouldUseUserfaultfd(); +const bool gUseReadBarrier = !gUseUserfaultfd; #endif namespace gc { diff --git a/runtime/read_barrier_config.h b/runtime/read_barrier_config.h index 53274eacf0..876e3d7d15 100644 --- a/runtime/read_barrier_config.h +++ b/runtime/read_barrier_config.h @@ -71,16 +71,24 @@ static constexpr bool kUseTableLookupReadBarrier = true; static constexpr bool kUseTableLookupReadBarrier = false; #endif +// Only if read-barrier isn't forced (see build/art.go) but is selected, that we need +// to see if we support userfaultfd GC. All the other cases can be constexpr here. #ifdef ART_FORCE_USE_READ_BARRIER constexpr bool gUseReadBarrier = kUseBakerReadBarrier || kUseTableLookupReadBarrier; constexpr bool gUseUserfaultfd = !gUseReadBarrier; +static_assert(!gUseUserfaultfd); #else -extern const bool gUseReadBarrier; +#ifndef ART_USE_READ_BARRIER +constexpr bool gUseReadBarrier = false; #ifdef ART_DEFAULT_GC_TYPE_IS_CMC -extern const bool gUseUserfaultfd; +constexpr bool gUseUserfaultfd = true; #else constexpr bool gUseUserfaultfd = false; #endif +#else +extern const bool gUseReadBarrier; +extern const bool gUseUserfaultfd; +#endif #endif // Disabled for performance reasons. |