0

Reland "partition_alloc: Move pa tests into pa."

This reverts commit 5d5831911b.

The diff is fixing an issue on Android.

On Android the 'open' function has two versions:
- int open(const char *pathname, int flags);
- int open(const char *pathname, int flags, mode_t mode);

This doesn't play well with WrapEINTR template. So an alias
was created 

Original change's description:
> Revert "partition_alloc: Move pa tests into pa."
>
> This reverts commit 17884376ce.
>
> Reason for revert: Fails to compile on `android-archive-rel`
> https://ci.chromium.org/ui/p/chromium/builders/ci/android-archive-rel/42067/overview
>
> NOTRY=true
> NOTREECHECKS=true
>
> Original change's description:
> > partition_alloc: Move pa tests into pa.
> >
> > This addresses a TODO about moving partition_alloc's tests into
> > partition_alloc.
> >
> > Bug: 40158212
> > Change-Id: Ia4b2017e2da38bd3fed904558126076b2deafc51
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5659601
> > Auto-Submit: Arthur Sonzogni <arthursonzogni@chromium.org>
> > Reviewed-by: Kentaro Hara <haraken@chromium.org>
> > Reviewed-by: danakj <danakj@chromium.org>
> > Reviewed-by: Colin Blundell <blundell@chromium.org>
> > Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
> > Cr-Commit-Position: refs/heads/main@{#1323243}
>
> Bug: 40158212
> Change-Id: I8831dbcffd8c328a0722fe1f53e382c68a6056a9
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5676232
> Commit-Queue: Titouan Rigoudy <titouan@chromium.org>
> Auto-Submit: Titouan Rigoudy <titouan@chromium.org>
> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
> Owners-Override: Titouan Rigoudy <titouan@chromium.org>
> Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Cr-Commit-Position: refs/heads/main@{#1323249}

Bug: 40158212
Change-Id: Ie60a85c296224ef3cfdcc17371db100cf2ce0db1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5675456
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1323319}
This commit is contained in:
Arthur Sonzogni
2024-07-04 13:41:17 +00:00
committed by Chromium LUCI CQ
parent 8e776b2fa5
commit 2ecbb28535
14 changed files with 686 additions and 200 deletions
base
components/heap_profiling/multi_process
gin

@ -2830,12 +2830,13 @@ test("base_perftests") {
"//third_party/google_benchmark",
]
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
if (use_partition_alloc) {
sources += [
"allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_lock_perftest.cc",
]
deps += [ ":partition_alloc_test_support" ]
deps += [ "allocator/partition_allocator/src/partition_alloc:test_support" ]
}
data_deps = [
@ -3146,19 +3147,6 @@ if (is_fuchsia) {
}
}
source_set("arm_bti_testfunctions") {
testonly = true
sources = []
if (target_cpu == "arm64" && (is_linux || is_android)) {
sources = [
"allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.S",
"allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.h",
]
}
}
source_set("path_service_unittest") {
testonly = true
@ -3187,9 +3175,6 @@ test("base_unittests") {
"allocator/dispatcher/testing/observer_mock.h",
"allocator/dispatcher/testing/tools.h",
"allocator/dispatcher/tls_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h",
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc",
"at_exit_unittest.cc",
"atomicops_unittest.cc",
"auto_reset_unittest.cc",
@ -3557,6 +3542,11 @@ test("base_unittests") {
"values_unittest.cc",
"version_unittest.cc",
"vlog_unittest.cc",
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h",
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc",
]
if (!is_cronet_build) {
@ -3580,13 +3570,11 @@ test("base_unittests") {
defines = []
deps = [
":arm_bti_testfunctions",
":base",
":base_stack_sampling_profiler_test_util",
":check_version_internal",
":feature_list_buildflags",
":i18n",
":partition_alloc_test_support",
":path_service_unittest",
":sanitizer_buildflags",
"//base/allocator:buildflags",
@ -3597,6 +3585,7 @@ test("base_unittests") {
"//base/test:test_proto",
"//base/test:test_support",
"//build:blink_buildflags",
"//build:branding_buildflags",
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
"//testing/gmock",
@ -3604,6 +3593,9 @@ test("base_unittests") {
"//third_party/abseil-cpp:absl",
"//third_party/icu",
"//third_party/modp_b64",
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
"allocator/partition_allocator/src/partition_alloc:test_support",
]
data_deps = [
@ -3636,8 +3628,10 @@ test("base_unittests") {
if (use_blink) {
sources += [
"allocator/partition_allocator/src/partition_alloc/tagging_unittest.cc",
"metrics/histogram_shared_memory_unittest.cc",
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
"allocator/partition_allocator/src/partition_alloc/tagging_unittest.cc",
]
if (!is_ios) {
@ -3929,57 +3923,9 @@ test("base_unittests") {
"immediate_crash_unittest.cc",
]
if (use_allocator_shim) {
sources += [
"allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple_unittest.mm",
"allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple_unittest.cc",
]
}
if (use_blink) {
sources += [ "files/file_path_watcher_unittest.cc" ]
}
}
if (use_partition_alloc) {
sources += [
"allocator/partition_allocator/src/partition_alloc/address_pool_manager_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/address_space_randomization_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/compressed_pointer_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/freeslot_bitmap_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/hardening_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/lightweight_quarantine_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/memory_reclaimer_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/page_allocator_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_lock_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/reverse_bytes_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/slot_start_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/use_death_tests.h",
]
if (use_starscan) {
sources += [
"allocator/partition_allocator/src/partition_alloc/stack/stack_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/starscan/pcscan_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/starscan/scan_loop_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap_unittest.cc",
]
}
if ((is_android || is_linux) && target_cpu == "arm64") {
cflags = [
@ -3990,19 +3936,11 @@ test("base_unittests") {
]
}
if (is_android) {
sources += [
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path_pa_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library_pa_unittest.cc",
]
} else if (is_fuchsia) {
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging_pa_unittest.cc" ]
}
if (enable_pkeys && is_debug && !is_component_build) {
# This test requires RELRO, which is not enabled in component builds.
# Also, require a debug build, since we only disable stack protectors in
# debug builds in PartitionAlloc (see below why it's needed).
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
sources += [ "allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey_unittest.cc" ]
# We want to test the pkey code without access to memory that is not
@ -4013,7 +3951,7 @@ test("base_unittests") {
configs += [ ":no_stack_protector" ]
}
deps += [ ":partition_alloc_test_support" ]
deps += [ "allocator/partition_allocator/src/partition_alloc:test_support" ]
}
if (is_mac) {
@ -4021,7 +3959,6 @@ test("base_unittests") {
frameworks = [
"CoreFoundation.framework",
"Foundation.framework",
"OpenCL.framework",
]
if (current_cpu == "x64") {
deps += [ ":base_profiler_test_support_library" ]
@ -4159,18 +4096,12 @@ test("base_unittests") {
if (use_allocator_shim) {
sources += [
"allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_unittest.cc",
"sampling_heap_profiler/poisson_allocation_sampler_unittest.cc",
"sampling_heap_profiler/sampling_heap_profiler_unittest.cc",
]
if (is_win) {
sources += [ "allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win_unittest.cc" ]
}
sources += [
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
"allocator/partition_alloc_support_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_unittest.cc",
"allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_unittest.cc",
]
}
@ -5544,67 +5475,6 @@ fuzzer_test("pickle_fuzzer") {
]
}
# TODO(crbug.com/40158212): Temporarily move test_support from
# //base/allocator/partition_allocator/src/partition_alloc/BUILD.gn to //base/BUILD.gn. After
# fixing partition_allocator tests issue, we will move test_support to
# //base/allocator/partition_allocator/src/partition_alloc/BUILD.gn again.
source_set("partition_alloc_test_support") {
testonly = true
sources = [
"allocator/partition_allocator/src/partition_alloc/extended_api.cc",
"allocator/partition_allocator/src/partition_alloc/extended_api.h",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_for_testing.h",
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_counting_impl_for_test.h",
]
if (is_posix) {
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc" ]
}
if (is_fuchsia) {
sources += [
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc",
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc",
]
}
if (is_win) {
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win_for_testing.cc" ]
}
if (is_apple) {
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_apple_for_testing.mm" ]
}
if (is_linux || is_chromeos) {
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_linux_for_testing.cc" ]
}
if (is_android) {
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_android_for_testing.cc" ]
}
public_deps = [
"allocator/partition_allocator:buildflags",
"//build:branding_buildflags",
"//build/config/compiler:compiler_buildflags",
]
public_configs = []
if (is_fuchsia) {
public_deps += [
"//third_party/fuchsia-sdk/sdk/pkg/fit",
"//third_party/fuchsia-sdk/sdk/pkg/sync",
"//third_party/fuchsia-sdk/sdk/pkg/zx",
]
# Needed for users of spinning_mutex.h, which for performance reasons,
# contains inlined calls to `libsync` inside the header file.
# It appends an entry to the "libs" section of the dependent target.
public_configs += [ ":fuchsia_sync_lib" ]
}
deps = [ ":base" ]
if (!is_debug) {
configs -= [ "//build/config/compiler:default_optimization" ]
configs += [ "//build/config/compiler:optimize_speed" ]
}
}
if (enable_base_tracing) {
# This group makes visible those targets in subdirectories that are not
# explicitly depended on.

@ -18,24 +18,20 @@ specific_include_rules = {
"+testing/gtest/include/gtest/gtest.h",
"+testing/perf/perf_result_reporter.h",
],
"gtest_util.h": [
"+testing/gtest/include/gtest/gtest.h",
],
# Dependencies on //base:
"extended_api\.cc": [
"+base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h",
],
"page_allocator_unittest\.cc": [
"+base/debug/proc_maps_linux.h",
],
"partition_alloc_perftest\.cc": [
"+base/allocator/dispatcher/dispatcher.h",
"+base/debug/allocation_trace.h",
"+base/debug/debugging_buildflags.h",
"+base/timer/lap_timer.h",
],
"partition_alloc_unittest\.cc": [
"+base/system/sys_info.h",
"+base/test/gtest_util.h",
],
"partition_lock_perftest\.cc": [
"+base/timer/lap_timer.h",
],

@ -117,6 +117,9 @@ def CheckNoExternalImportInGn(input_api, output_api):
continue;
if not import_path.startswith('//'):
continue;
# Allow //testing, but only within `build_with_chromium`.
if import_path.startswith('//testing'):
continue;
errors.append(output_api.PresubmitError(
'%s:%d\nPartitionAlloc disallow external import: %s' %
(f.LocalPath(), line_number + 1, import_path)))

@ -1,9 +0,0 @@
# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This file will be used to check out PartitionAlloc and to build it as
# standalone library. In this case, PartitionAlloc needs to define
# build_with_chromium. If building PartitionAlloc as a part of chromium,
# chromium will provide build_with_chromium=true.
build_with_chromium = false

@ -2,7 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build_overrides/build.gni")
# By definition, PartitionAlloc standalone builds outside of chromium.
build_with_chromium = false
# This is the default build configuration when building PartitionAlloc
# as a standalone library.

@ -8,7 +8,6 @@
# - skia: //gn/BUILDCONFIG.gn
# - chromium: //build/config/BUILDCONFIG.gn
is_partition_alloc_standalone = true
build_with_chromium = false
is_asan = false

@ -634,7 +634,9 @@ if (is_clang_or_gcc) {
"partition_alloc_base/threading/platform_thread_win.cc",
"partition_alloc_base/time/time_win.cc",
]
} else if (is_posix) {
}
if (is_posix) {
sources += [
"partition_alloc_base/debug/stack_trace_posix.cc",
"partition_alloc_base/files/file_util.h",
@ -665,7 +667,9 @@ if (is_clang_or_gcc) {
} else {
sources += [ "partition_alloc_base/time/time_now_posix.cc" ]
}
} else if (is_fuchsia) {
}
if (is_fuchsia) {
sources += [
"partition_alloc_base/fuchsia/fuchsia_logging.cc",
"partition_alloc_base/fuchsia/fuchsia_logging.h",
@ -679,6 +683,7 @@ if (is_clang_or_gcc) {
"partition_alloc_base/time/time_fuchsia.cc",
]
}
if (is_android) {
# Only android build requires native_library, and native_library depends
# on file_path. So file_path is added if is_android = true.
@ -691,6 +696,7 @@ if (is_clang_or_gcc) {
"partition_alloc_base/native_library_posix.cc",
]
}
if (is_apple) {
# Apple-specific utilities
sources += [
@ -888,6 +894,204 @@ if (is_clang_or_gcc) {
]
}
} # if (is_clang_or_gcc)
# TODO(crbug.com/40158212): After making partition_alloc a standalone library,
# move test code here. i.e. test("partition_alloc_tests") { ... } and
# test("partition_alloc_perftests").
# TODO(crbug.com/40158212): Consider supporting building tests outside of
# chromium.
if (build_with_chromium) {
import("//testing/test.gni")
test("partition_alloc_tests") {
testonly = true
sources = [ "partition_alloc_base/test/gtest_util.h" ]
if (is_linux || is_chromeos || is_android) {
sources += [
"partition_alloc_base/debug/proc_maps_linux.cc",
"partition_alloc_base/debug/proc_maps_linux.h",
]
}
if (is_android) {
sources += [
"partition_alloc_base/files/file_path_pa_unittest.cc",
"partition_alloc_base/native_library_pa_unittest.cc",
]
}
if (use_partition_alloc) {
sources += [
"address_pool_manager_unittest.cc",
"address_space_randomization_unittest.cc",
"compressed_pointer_unittest.cc",
"freeslot_bitmap_unittest.cc",
"hardening_unittest.cc",
"lightweight_quarantine_unittest.cc",
"memory_reclaimer_unittest.cc",
"page_allocator_unittest.cc",
"partition_alloc_base/bits_pa_unittest.cc",
"partition_alloc_base/component_export_pa_unittest.cc",
"partition_alloc_base/cpu_pa_unittest.cc",
"partition_alloc_base/logging_pa_unittest.cc",
"partition_alloc_base/no_destructor_pa_unittest.cc",
"partition_alloc_base/rand_util_pa_unittest.cc",
"partition_alloc_base/scoped_clear_last_error_pa_unittest.cc",
"partition_alloc_base/strings/cstring_builder_pa_unittest.cc",
"partition_alloc_base/strings/safe_sprintf_pa_unittest.cc",
"partition_alloc_base/strings/string_util_pa_unittest.cc",
"partition_alloc_base/strings/stringprintf_pa_unittest.cc",
"partition_alloc_base/thread_annotations_pa_unittest.cc",
"partition_alloc_unittest.cc",
"partition_lock_unittest.cc",
"reverse_bytes_unittest.cc",
"slot_start_unittest.cc",
"thread_cache_unittest.cc",
"use_death_tests.h",
]
if (use_starscan) {
sources += [
"stack/stack_unittest.cc",
"starscan/pcscan_scheduling_unittest.cc",
"starscan/pcscan_unittest.cc",
"starscan/scan_loop_unittest.cc",
"starscan/state_bitmap_unittest.cc",
]
}
}
if (is_fuchsia) {
sources +=
[ "partition_alloc_base/fuchsia/fuchsia_logging_pa_unittest.cc" ]
}
if (use_allocator_shim) {
sources += [
"shim/allocator_shim_default_dispatch_to_partition_alloc_unittest.cc",
]
if (is_win) {
sources += [ "shim/winheap_stubs_win_unittest.cc" ]
}
if (is_ios) {
sources += [
"shim/allocator_interception_apple_unittest.mm",
"shim/malloc_zone_functions_apple_unittest.cc",
]
}
}
if ((is_android || is_linux) && target_cpu == "arm64") {
cflags = [
"-Xclang",
"-target-feature",
"-Xclang",
"+mte",
]
}
frameworks = []
if (is_mac) {
frameworks += [
"Foundation.framework",
"OpenCL.framework",
]
}
deps = [
# GTest
"//testing/gtest:gtest",
"//testing/gtest:gtest_main",
# GMock
"//testing/gmock:gmock",
# PartitionAlloc
":partition_alloc",
":test_support",
]
configs -= partition_alloc_remove_configs
configs += partition_alloc_add_configs
}
source_set("test_support") {
testonly = true
sources = [
"extended_api.cc",
"extended_api.h",
"partition_alloc_base/threading/platform_thread_for_testing.h",
"partition_alloc_for_testing.h",
"pointers/raw_ptr_counting_impl_for_test.h",
]
if (is_posix) {
sources += [
"partition_alloc_base/threading/platform_thread_posix_for_testing.cc",
]
}
if (is_fuchsia) {
sources += [
"partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc",
"partition_alloc_base/threading/platform_thread_posix_for_testing.cc",
]
}
if (is_win) {
sources += [
"partition_alloc_base/threading/platform_thread_win_for_testing.cc",
]
}
if (is_apple) {
sources += [
"partition_alloc_base/threading/platform_thread_apple_for_testing.mm",
]
}
if (is_linux || is_chromeos) {
sources += [
"partition_alloc_base/threading/platform_thread_linux_for_testing.cc",
]
}
if (is_android) {
sources += [
"partition_alloc_base/threading/platform_thread_android_for_testing.cc",
]
}
public_deps = [
":arm_bti_testfunctions",
":buildflags",
":partition_alloc",
":raw_ptr",
]
public_configs = []
if (is_fuchsia) {
public_deps += [
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger:fuchsia.logger_hlcpp",
"//third_party/fuchsia-sdk/sdk/pkg/fit",
"//third_party/fuchsia-sdk/sdk/pkg/sync",
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
"//third_party/fuchsia-sdk/sdk/pkg/zx",
]
# Needed for users of spinning_mutex.h, which for performance reasons,
# contains inlined calls to `libsync` inside the header file.
# It appends an entry to the "libs" section of the dependent target.
public_configs += [ ":fuchsia_sync_lib" ]
}
configs -= partition_alloc_remove_configs
configs += partition_alloc_add_configs
}
source_set("arm_bti_testfunctions") {
testonly = true
sources = []
if (target_cpu == "arm64" && (is_linux || is_android)) {
sources = [
"arm_bti_test_functions.S",
"arm_bti_test_functions.h",
]
}
}
}

@ -22,7 +22,7 @@
#include "partition_alloc/tagging.h"
#if defined(LINUX_NAME_REGION)
#include "base/debug/proc_maps_linux.h"
#include "partition_alloc/partition_alloc_base/debug/proc_maps_linux.h"
#endif
#include "testing/gtest/include/gtest/gtest.h"
@ -499,9 +499,9 @@ TEST(PartitionAllocPageAllocatorTest, PageTagging) {
auto is_region_named = [](uintptr_t start_address) {
std::string proc_maps;
EXPECT_TRUE(::base::debug::ReadProcMaps(&proc_maps));
std::vector<::base::debug::MappedMemoryRegion> regions;
EXPECT_TRUE(::base::debug::ParseProcMaps(proc_maps, &regions));
EXPECT_TRUE(base::debug::ReadProcMaps(&proc_maps));
std::vector<base::debug::MappedMemoryRegion> regions;
EXPECT_TRUE(base::debug::ParseProcMaps(proc_maps, &regions));
bool found = false;
for (const auto& region : regions) {

@ -0,0 +1,193 @@
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif
#include "partition_alloc/partition_alloc_base/debug/proc_maps_linux.h"
#include <fcntl.h>
#include <stddef.h>
#include "partition_alloc/build_config.h"
#include "partition_alloc/partition_alloc_base/files/file_util.h"
#include "partition_alloc/partition_alloc_base/logging.h"
#include "partition_alloc/partition_alloc_base/posix/eintr_wrapper.h"
#include "partition_alloc/partition_alloc_check.h"
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) || \
PA_BUILDFLAG(IS_ANDROID)
#include <inttypes.h>
#endif
namespace partition_alloc::internal::base::debug {
namespace {
// On Android the 'open' function may have two versions:
// int open(const char *pathname, int flags);
// int open(const char *pathname, int flags, mode_t mode);
//
// This doesn't play well with WrapEINTR template. This alias helps the compiler
// to make a decision.
int OpenFile(const char* pathname, int flags) {
return open(pathname, flags);
}
} // namespace
// Scans |proc_maps| starting from |pos| returning true if the gate VMA was
// found, otherwise returns false.
static bool ContainsGateVMA(std::string* proc_maps, size_t pos) {
#if PA_BUILDFLAG(PA_ARCH_CPU_ARM_FAMILY)
// The gate VMA on ARM kernels is the interrupt vectors page.
return proc_maps->find(" [vectors]\n", pos) != std::string::npos;
#elif PA_BUILDFLAG(PA_ARCH_CPU_X86_64)
// The gate VMA on x86 64-bit kernels is the virtual system call page.
return proc_maps->find(" [vsyscall]\n", pos) != std::string::npos;
#else
// Otherwise assume there is no gate VMA in which case we shouldn't
// get duplicate entries.
return false;
#endif
}
bool ReadProcMaps(std::string* proc_maps) {
// seq_file only writes out a page-sized amount on each call. Refer to header
// file for details.
const size_t read_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
int fd = WrapEINTR(OpenFile)("/proc/self/maps", O_RDONLY);
if (fd == -1) {
PA_LOG(ERROR) << "Couldn't open /proc/self/maps";
WrapEINTR(close)(fd);
return false;
}
proc_maps->clear();
while (true) {
// To avoid a copy, resize |proc_maps| so read() can write directly into it.
// Compute |buffer| afterwards since resize() may reallocate.
size_t pos = proc_maps->size();
proc_maps->resize(pos + read_size);
void* buffer = &(*proc_maps)[pos];
ssize_t bytes_read = WrapEINTR(read)(fd, buffer, read_size);
if (bytes_read < 0) {
PA_DPLOG(ERROR) << "Couldn't read /proc/self/maps";
proc_maps->clear();
WrapEINTR(close)(fd);
return false;
}
// ... and don't forget to trim off excess bytes.
proc_maps->resize(pos + static_cast<size_t>(bytes_read));
if (bytes_read == 0) {
break;
}
// The gate VMA is handled as a special case after seq_file has finished
// iterating through all entries in the virtual memory table.
//
// Unfortunately, if additional entries are added at this point in time
// seq_file gets confused and the next call to read() will return duplicate
// entries including the gate VMA again.
//
// Avoid this by searching for the gate VMA and breaking early.
if (ContainsGateVMA(proc_maps, pos)) {
break;
}
}
WrapEINTR(close)(fd);
return true;
}
bool ParseProcMaps(const std::string& input,
std::vector<MappedMemoryRegion>* regions_out) {
PA_CHECK(regions_out);
std::vector<MappedMemoryRegion> regions;
// This isn't async safe nor terribly efficient, but it doesn't need to be at
// this point in time.
std::vector<std::string> lines;
int start = 0;
for (size_t i = 0; i < input.size(); ++i) {
if (input[i] == '\n') {
lines.push_back(input.substr(start, i - start));
start = i + 1;
}
}
for (size_t i = 0; i < lines.size(); ++i) {
// Due to splitting on '\n' the last line should be empty.
if (i == lines.size() - 1) {
if (!lines[i].empty()) {
PA_DLOG(WARNING) << "Last line not empty";
return false;
}
break;
}
MappedMemoryRegion region;
const char* line = lines[i].c_str();
char permissions[5] = {'\0'}; // Ensure NUL-terminated string.
uint8_t dev_major = 0;
uint8_t dev_minor = 0;
long inode = 0;
int path_index = 0;
// Sample format from man 5 proc:
//
// address perms offset dev inode pathname
// 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
//
// The final %n term captures the offset in the input string, which is used
// to determine the path name. It *does not* increment the return value.
// Refer to man 3 sscanf for details.
if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4c %llx %hhx:%hhx %ld %n",
&region.start, &region.end, permissions, &region.offset,
&dev_major, &dev_minor, &inode, &path_index) < 7) {
PA_LOG(WARNING) << "sscanf failed for line: " << line;
return false;
}
region.permissions = 0;
if (permissions[0] == 'r') {
region.permissions |= MappedMemoryRegion::READ;
} else if (permissions[0] != '-') {
return false;
}
if (permissions[1] == 'w') {
region.permissions |= MappedMemoryRegion::WRITE;
} else if (permissions[1] != '-') {
return false;
}
if (permissions[2] == 'x') {
region.permissions |= MappedMemoryRegion::EXECUTE;
} else if (permissions[2] != '-') {
return false;
}
if (permissions[3] == 'p') {
region.permissions |= MappedMemoryRegion::PRIVATE;
} else if (permissions[3] != 's' &&
permissions[3] != 'S') { // Shared memory.
return false;
}
// Pushing then assigning saves us a string copy.
regions.push_back(region);
regions.back().path.assign(line + path_index);
}
regions_out->swap(regions);
return true;
}
} // namespace partition_alloc::internal::base::debug

@ -0,0 +1,93 @@
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_
#include <stdint.h>
#include <string>
#include <vector>
#include "partition_alloc/partition_alloc_base/component_export.h"
namespace partition_alloc::internal::base::debug {
// Describes a region of mapped memory and the path of the file mapped.
struct MappedMemoryRegion {
enum Permission {
READ = 1 << 0,
WRITE = 1 << 1,
EXECUTE = 1 << 2,
PRIVATE = 1 << 3, // If set, region is private, otherwise it is shared.
};
// The address range [start,end) of mapped memory.
uintptr_t start;
uintptr_t end;
// Byte offset into |path| of the range mapped into memory.
unsigned long long offset;
// Image base, if this mapping corresponds to an ELF image.
uintptr_t base;
// Bitmask of read/write/execute/private/shared permissions.
uint8_t permissions;
// Name of the file mapped into memory.
//
// NOTE: path names aren't guaranteed to point at valid files. For example,
// "[heap]" and "[stack]" are used to represent the location of the process'
// heap and stack, respectively.
std::string path;
};
// Reads the data from /proc/self/maps and stores the result in |proc_maps|.
// Returns true if successful, false otherwise.
//
// There is *NO* guarantee that the resulting contents will be free of
// duplicates or even contain valid entries by time the method returns.
//
//
// THE GORY DETAILS
//
// Did you know it's next-to-impossible to atomically read the whole contents
// of /proc/<pid>/maps? You would think that if we passed in a large-enough
// buffer to read() that It Should Just Work(tm), but sadly that's not the case.
//
// Linux's procfs uses seq_file [1] for handling iteration, text formatting,
// and dealing with resulting data that is larger than the size of a page. That
// last bit is especially important because it means that seq_file will never
// return more than the size of a page in a single call to read().
//
// Unfortunately for a program like Chrome the size of /proc/self/maps is
// larger than the size of page so we're forced to call read() multiple times.
// If the virtual memory table changed in any way between calls to read() (e.g.,
// a different thread calling mprotect()), it can make seq_file generate
// duplicate entries or skip entries.
//
// Even if seq_file was changed to keep flushing the contents of its page-sized
// buffer to the usermode buffer inside a single call to read(), it has to
// release its lock on the virtual memory table to handle page faults while
// copying data to usermode. This puts us in the same situation where the table
// can change while we're copying data.
//
// Alternatives such as fork()-and-suspend-the-parent-while-child-reads were
// attempted, but they present more subtle problems than it's worth. Depending
// on your use case your best bet may be to read /proc/<pid>/maps prior to
// starting other threads.
//
// [1] http://kernelnewbies.org/Documents/SeqFileHowTo
PA_COMPONENT_EXPORT(PARTITION_ALLOC) bool ReadProcMaps(std::string* proc_maps);
// Parses /proc/<pid>/maps input data and stores in |regions|. Returns true
// and updates |regions| if and only if all of |input| was successfully parsed.
PA_COMPONENT_EXPORT(PARTITION_ALLOC)
bool ParseProcMaps(const std::string& input,
std::vector<MappedMemoryRegion>* regions);
} // namespace partition_alloc::internal::base::debug
#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_

@ -0,0 +1,87 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_base/check.h"
#include "testing/gtest/include/gtest/gtest.h"
// EXPECT/ASSERT_DCHECK_DEATH is intended to replace EXPECT/ASSERT_DEBUG_DEATH
// when the death is expected to be caused by a DCHECK. Contrary to
// EXPECT/ASSERT_DEBUG_DEATH however, it doesn't execute the statement in non-
// dcheck builds as DCHECKs are intended to catch things that should never
// happen and as such executing the statement results in undefined behavior
// (|statement| is compiled in unsupported configurations nonetheless).
// DCHECK_IS_CONFIGURABLE is excluded from DCHECK_DEATH because it's non-FATAL
// by default and there are no known tests that configure a FATAL level. If this
// gets used from FATAL contexts under DCHECK_IS_CONFIGURABLE this may need to
// be updated to look at LOGGING_DCHECK's current severity level.
// Death tests misbehave on Android.
#if PA_BUILDFLAG(DCHECKS_ARE_ON) && defined(GTEST_HAS_DEATH_TEST) && \
!PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) && !PA_BUILDFLAG(IS_ANDROID)
// EXPECT/ASSERT_DCHECK_DEATH tests verify that a DCHECK is hit ("Check failed"
// is part of the error message). Optionally you may specify part of the message
// to verify which DCHECK (or LOG(DFATAL)) is being hit.
#define PA_EXPECT_DCHECK_DEATH(statement) \
EXPECT_DEATH(statement, "Check failed")
#define PA_EXPECT_DCHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, msg)
#define PA_ASSERT_DCHECK_DEATH(statement) \
ASSERT_DEATH(statement, "Check failed")
#define PA_ASSERT_DCHECK_DEATH_WITH(statement, msg) ASSERT_DEATH(statement, msg)
#else
#define PA_EXPECT_DCHECK_DEATH(statement) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "Check failed", )
#define PA_EXPECT_DCHECK_DEATH_WITH(statement, msg) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, msg, )
#define PA_ASSERT_DCHECK_DEATH(statement) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "Check failed", return)
#define PA_ASSERT_DCHECK_DEATH_WITH(statement, msg) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, msg, return)
#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) && defined(GTEST_HAS_DEATH_TEST) &&
// !PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) && !PA_BUILDFLAG(IS_ANDROID)
// As above, but for CHECK().
#if defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID)
#if PA_BASE_CHECK_WILL_STREAM()
#define PA_EXPECT_CHECK_DEATH(statement) EXPECT_DEATH(statement, "Check failed")
#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, msg)
#define PA_ASSERT_CHECK_DEATH(statement) ASSERT_DEATH(statement, "Check failed")
#define PA_EXPECT_NOTREACHED_DEATH(statement) \
EXPECT_DEATH(statement, "NOTREACHED hit")
#define PA_ASSERT_NOTREACHED_DEATH(statement) \
ASSERT_DEATH(statement, "NOTREACHED hit")
#else
#define PA_EXPECT_CHECK_DEATH(statement) EXPECT_DEATH(statement, "")
#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, "")
#define PA_ASSERT_CHECK_DEATH(statement) ASSERT_DEATH(statement, "")
#define PA_EXPECT_NOTREACHED_DEATH(statement) EXPECT_DEATH(statement, "")
#define PA_ASSERT_NOTREACHED_DEATH(statement) ASSERT_DEATH(statement, "")
#endif // PA_BASE_CHECK_WILL_STREAM()
#else // defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID)
// Note GTEST_UNSUPPORTED_DEATH_TEST takes a |regex| only to see whether it is a
// valid regex. It is never evaluated.
#define PA_EXPECT_CHECK_DEATH(statement) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", )
#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", )
#define PA_ASSERT_CHECK_DEATH(statement) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", return)
#define PA_EXPECT_NOTREACHED_DEATH(statement) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", )
#define PA_ASSERT_NOTREACHED_DEATH(statement) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", return)
#endif // defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID)
#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
#include <algorithm>
#include <bit>
#include <cstddef>
@ -16,8 +18,6 @@
#include <tuple>
#include <vector>
#include "base/system/sys_info.h"
#include "base/test/gtest_util.h"
#include "partition_alloc/address_space_randomization.h"
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
@ -34,6 +34,8 @@
#include "partition_alloc/partition_alloc_base/logging.h"
#include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
#include "partition_alloc/partition_alloc_base/rand_util.h"
#include "partition_alloc/partition_alloc_base/system/sys_info.h"
#include "partition_alloc/partition_alloc_base/test/gtest_util.h"
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
#include "partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h"
#include "partition_alloc/partition_alloc_config.h"
@ -80,6 +82,18 @@
#include <sys/syscall.h>
#endif
// Headers for the AmountOfPhysicalMemory() function.
#if PA_BUILDFLAG(IS_FUCHSIA)
#include <zircon/syscalls.h>
#elif PA_BUILDFLAG(IS_WIN)
#include <windows.h>
#elif PA_BUILDFLAG(IS_APPLE)
#include <mach/host_info.h>
#include <mach/mach.h>
#elif PA_BUILDFLAG(IS_POSIX)
#include <unistd.h>
#endif
// In the MTE world, the upper bits of a pointer can be decorated with a tag,
// thus allowing many versions of the same pointer to exist. These macros take
// that into account when comparing.
@ -88,10 +102,40 @@
#define PA_EXPECT_PTR_NE(ptr1, ptr2) \
{ EXPECT_NE(UntagPtr(ptr1), UntagPtr(ptr2)); }
#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
namespace {
// Best effort to get the amount of physical memory available to the system.
// Returns 0 on failure.
uint64_t AmountOfPhysicalMemory() {
#if PA_BUILDFLAG(IS_FUCHSIA)
return zx_system_get_physmem();
#elif PA_BUILDFLAG(IS_WIN)
MEMORYSTATUSEX mem_status = {.dwLength = sizeof(mem_status)};
if (GlobalMemoryStatusEx(&mem_status)) {
return mem_status.ullTotalPhys;
}
return 0;
#elif PA_BUILDFLAG(IS_APPLE)
struct host_basic_info host_basic_info;
mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
if (host_info(mach_host_self(), HOST_BASIC_INFO,
reinterpret_cast<host_info_t>(&host_basic_info),
&count) == KERN_SUCCESS) {
return host_basic_info.max_mem;
}
return 0;
#elif PA_BUILDFLAG(IS_POSIX)
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGESIZE);
if (pages >= 0 && page_size >= 0) {
return static_cast<uint64_t>(pages) * static_cast<uint64_t>(page_size);
}
return 0;
#else
return 0;
#endif
}
bool IsLargeMemoryDevice() {
// Treat any device with 4GiB or more of physical memory as a "large memory
// device". We check for slightly less than GiB so that devices with a small
@ -99,7 +143,7 @@ bool IsLargeMemoryDevice() {
//
// Set to 4GiB, since we have 2GiB Android devices where tests flakily fail
// (e.g. Nexus 5X, crbug.com/1191195).
return base::SysInfo::AmountOfPhysicalMemory() >= 4000ULL * 1024 * 1024;
return AmountOfPhysicalMemory() >= 4000ULL * 1024 * 1024;
}
bool SetAddressSpaceLimit() {
@ -4805,7 +4849,7 @@ TEST_P(PartitionAllocDeathTest, ReleaseUnderflowRawPtr) {
allocator.root()->InSlotMetadataPointerFromObjectForTesting(ptr);
in_slot_metadata->Acquire();
EXPECT_FALSE(in_slot_metadata->Release());
EXPECT_DCHECK_DEATH(in_slot_metadata->Release());
PA_EXPECT_DCHECK_DEATH(in_slot_metadata->Release());
allocator.root()->Free(ptr);
}
@ -4821,7 +4865,7 @@ TEST_P(PartitionAllocDeathTest, ReleaseUnderflowDanglingPtr) {
allocator.root()->InSlotMetadataPointerFromObjectForTesting(ptr);
in_slot_metadata->AcquireFromUnprotectedPtr();
EXPECT_FALSE(in_slot_metadata->ReleaseFromUnprotectedPtr());
EXPECT_DCHECK_DEATH(in_slot_metadata->ReleaseFromUnprotectedPtr());
PA_EXPECT_DCHECK_DEATH(in_slot_metadata->ReleaseFromUnprotectedPtr());
allocator.root()->Free(ptr);
}
@ -5038,7 +5082,7 @@ TEST_P(PartitionAllocTest, FastPathOrReturnNull) {
#if !defined(OFFICIAL_BUILD) || !defined(NDEBUG)
TEST_P(PartitionAllocDeathTest, CheckTriggered) {
EXPECT_DCHECK_DEATH_WITH(PA_CHECK(5 == 7), "Check failed.*5 == 7");
PA_EXPECT_DCHECK_DEATH_WITH(PA_CHECK(5 == 7), "Check failed.*5 == 7");
EXPECT_DEATH(PA_CHECK(5 == 7), "Check failed.*5 == 7");
}
@ -5689,28 +5733,30 @@ TEST_P(PartitionAllocTest, FastReclaim) {
PurgeFlags::kDiscardUnusedSystemPages;
allocator.root()->PurgeMemory(kFlags);
ASSERT_GT(now, base::TimeTicks());
// Here and below, using TS_UNCHECKED_READ since the root is not used
// Here and below, using PA_TS_UNCHECKED_READ since the root is not used
// conccurently.
//
// Went around all buckets.
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
0u);
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
// Ran out of time.
unsigned int next_bucket =
TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
EXPECT_NE(next_bucket, 0u);
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
// Make some progress, but not through all buckets yet.
EXPECT_GT(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
EXPECT_GT(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
next_bucket);
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
// Ran out of time.
EXPECT_NE(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
EXPECT_NE(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
0u);
// But eventually we make it through all buckets.
while (TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index) != 0) {
while (PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index) != 0) {
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
}
// No expectation, test will time out if it's incorrect.
@ -5730,33 +5776,36 @@ TEST_P(PartitionAllocTest, FastReclaimEventuallyLooksAtAllBuckets) {
PurgeFlags::kDiscardUnusedSystemPages;
allocator.root()->PurgeMemory(kFlags);
ASSERT_GT(now, base::TimeTicks());
// Here and below, using TS_UNCHECKED_READ since the root is not used
// Here and below, using PA_TS_UNCHECKED_READ since the root is not used
// conccurently.
//
// Went around all buckets, generation is incremented.
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
0u);
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
// Ran out of time.
unsigned int next_bucket =
TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
EXPECT_NE(next_bucket, 0u);
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
// Make some progress, but not through all buckets yet.
EXPECT_GT(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
EXPECT_GT(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
next_bucket);
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
// Ran out of time.
EXPECT_NE(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
EXPECT_NE(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
0u);
// But eventually we make it through all generations.
while (TS_UNCHECKED_READ(allocator.root()->purge_generation) != 0) {
while (PA_TS_UNCHECKED_READ(allocator.root()->purge_generation) != 0) {
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
}
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
0u);
allocator.root()->now_maybe_overridden_for_testing = base::TimeTicks::Now;
}

@ -54,7 +54,7 @@ source_set("test_support") {
deps = [
":multi_process",
"//base",
"//base:partition_alloc_test_support",
"//base/allocator/partition_allocator/src/partition_alloc:test_support",
"//base/test:test_support",
"//components/services/heap_profiling/public/cpp",
"//content/public/browser",

@ -233,7 +233,7 @@ test("gin_unittests") {
if (use_partition_alloc) {
sources += [ "v8_platform_page_allocator_unittest.cc" ]
if (target_cpu == "arm64" && (is_linux || is_android)) {
deps += [ "//base:arm_bti_testfunctions" ]
deps += [ "//base/allocator/partition_allocator/src/partition_alloc:arm_bti_testfunctions" ]
}
}