Skip to content

Commit

Permalink
PA: Move NonScannableAllocatorImpl into partition_allocator/
Browse files Browse the repository at this point in the history
Moves base::internal::NonScannableAllocatorImpl to
allocator_shim::internal::NonScannableAllocatorImpl, and provides
allocator_shim::NonScannableAllocator and
allocator_shim::NonQuarantinableAllocator as new public APIs.

PS9 contains pure copies as:
base/memory/nonscannable_memory.* -> b/a/p/shim/nonscannable_allocator.*
(file names changed in order to avoid a conflict.)

Bug: 1337681
Change-Id: I39c859855404737f7412c62cb7e6fc11d8da9c5f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4578558
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Mikhail Khokhlov <khokhlov@google.com>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: Bartek Nowierski <bartekn@chromium.org>
Reviewed-by: Anton Bikineev <bikineev@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1153661}
  • Loading branch information
yuki3 authored and Chromium LUCI CQ committed Jun 6, 2023
1 parent a5a815a commit 8fb5059
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 164 deletions.
2 changes: 2 additions & 0 deletions base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,8 @@ component("base") {
sources += [
"allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.cc",
"allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.h",
"allocator/partition_allocator/shim/nonscannable_allocator.cc",
"allocator/partition_allocator/shim/nonscannable_allocator.h",
]
}
if (is_android) {
Expand Down
4 changes: 2 additions & 2 deletions base/allocator/partition_alloc_support.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@
#include "third_party/abseil-cpp/absl/types/optional.h"

#if BUILDFLAG(USE_STARSCAN)
#include "base/allocator/partition_allocator/shim/nonscannable_allocator.h"
#include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/allocator/partition_allocator/starscan/pcscan_scheduling.h"
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
#include "base/allocator/partition_allocator/starscan/stats_collector.h"
#include "base/allocator/partition_allocator/starscan/stats_reporter.h"
#include "base/memory/nonscannable_memory.h"
#endif // BUILDFLAG(USE_STARSCAN)

#if BUILDFLAG(IS_ANDROID)
Expand Down Expand Up @@ -1302,7 +1302,7 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
// partition. At the same time, thread cache on the main(malloc) partition
// must be disabled, because only one partition can have it on.
if (scan_enabled && process_type == switches::kRendererProcess) {
base::internal::NonQuarantinableAllocator::Instance()
allocator_shim::NonQuarantinableAllocator::Instance()
.root()
->EnableThreadCacheIfSupported();
} else
Expand Down
1 change: 0 additions & 1 deletion base/allocator/partition_allocator/shim/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ include_rules = [
"+base/base_export.h",
"+base/logging.h",
"+base/mac/mach_logging.h",
"+base/memory/nonscannable_memory.h",
"+base/synchronization/lock.h",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include "base/allocator/partition_allocator/partition_root.h"
#include "base/allocator/partition_allocator/partition_stats.h"
#include "base/allocator/partition_allocator/shim/allocator_shim_internals.h"
#include "base/memory/nonscannable_memory.h"
#include "base/allocator/partition_allocator/shim/nonscannable_allocator.h"
#include "build/build_config.h"

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Expand Down Expand Up @@ -703,8 +703,8 @@ void EnablePCScan(partition_alloc::internal::PCScan::InitConfig config) {
AlignedAllocator());
}

base::internal::NonScannableAllocator::Instance().NotifyPCScanEnabled();
base::internal::NonQuarantinableAllocator::Instance().NotifyPCScanEnabled();
allocator_shim::NonScannableAllocator::Instance().NotifyPCScanEnabled();
allocator_shim::NonQuarantinableAllocator::Instance().NotifyPCScanEnabled();
}
#endif // BUILDFLAG(USE_STARSCAN)
} // namespace allocator_shim
Expand Down Expand Up @@ -778,14 +778,14 @@ SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW {

// Dump stats for nonscannable and nonquarantinable allocators.
auto& nonscannable_allocator =
base::internal::NonScannableAllocator::Instance();
allocator_shim::NonScannableAllocator::Instance();
partition_alloc::SimplePartitionStatsDumper nonscannable_allocator_dumper;
if (auto* nonscannable_root = nonscannable_allocator.root()) {
nonscannable_root->DumpStats("malloc", true,
&nonscannable_allocator_dumper);
}
auto& nonquarantinable_allocator =
base::internal::NonQuarantinableAllocator::Instance();
allocator_shim::NonQuarantinableAllocator::Instance();
partition_alloc::SimplePartitionStatsDumper nonquarantinable_allocator_dumper;
if (auto* nonquarantinable_root = nonquarantinable_allocator.root()) {
nonquarantinable_root->DumpStats("malloc", true,
Expand Down
84 changes: 84 additions & 0 deletions base/allocator/partition_allocator/shim/nonscannable_allocator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/allocator/partition_allocator/shim/nonscannable_allocator.h"

#include "base/allocator/partition_allocator/partition_root.h"

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#include "base/allocator/partition_alloc_features.h"
#include "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.h"

#if BUILDFLAG(USE_STARSCAN)
#include "base/allocator/partition_allocator/starscan/metadata_allocator.h"
#include "base/allocator/partition_allocator/starscan/pcscan.h"
#endif
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

namespace allocator_shim::internal {

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
template <bool quarantinable>
NonScannableAllocatorImpl<quarantinable>::NonScannableAllocatorImpl() = default;
template <bool quarantinable>
NonScannableAllocatorImpl<quarantinable>::~NonScannableAllocatorImpl() =
default;

template <bool quarantinable>
NonScannableAllocatorImpl<quarantinable>&
NonScannableAllocatorImpl<quarantinable>::Instance() {
static partition_alloc::internal::base::NoDestructor<
NonScannableAllocatorImpl>
instance;
return *instance;
}

template <bool quarantinable>
void* NonScannableAllocatorImpl<quarantinable>::Alloc(size_t size) {
#if BUILDFLAG(USE_STARSCAN)
// TODO(bikineev): Change to LIKELY once PCScan is enabled by default.
if (PA_UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
PA_DCHECK(allocator_.get());
return allocator_->root()->AllocWithFlagsNoHooks(
0, size, partition_alloc::PartitionPageSize());
}
#endif // BUILDFLAG(USE_STARSCAN)
// Otherwise, dispatch to default partition.
return allocator_shim::internal::PartitionAllocMalloc::Allocator()
->AllocWithFlagsNoHooks(0, size, partition_alloc::PartitionPageSize());
}

template <bool quarantinable>
void NonScannableAllocatorImpl<quarantinable>::Free(void* ptr) {
partition_alloc::ThreadSafePartitionRoot::FreeNoHooks(ptr);
}

template <bool quarantinable>
void NonScannableAllocatorImpl<quarantinable>::NotifyPCScanEnabled() {
#if BUILDFLAG(USE_STARSCAN)
allocator_.reset(partition_alloc::internal::MakePCScanMetadata<
partition_alloc::PartitionAllocator>());
allocator_->init(partition_alloc::PartitionOptions{
.quarantine =
quarantinable
? partition_alloc::PartitionOptions::Quarantine::kAllowed
: partition_alloc::PartitionOptions::Quarantine::kDisallowed,
.cookie = partition_alloc::PartitionOptions::Cookie::kAllowed,
.backup_ref_ptr =
partition_alloc::PartitionOptions::BackupRefPtr::kDisabled,
});
if constexpr (quarantinable) {
partition_alloc::internal::PCScan::RegisterNonScannableRoot(
allocator_->root());
}
pcscan_enabled_.store(true, std::memory_order_release);
#endif // BUILDFLAG(USE_STARSCAN)
}

template class NonScannableAllocatorImpl<true>;
template class NonScannableAllocatorImpl<false>;

#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

} // namespace allocator_shim::internal
87 changes: 87 additions & 0 deletions base/allocator/partition_allocator/shim/nonscannable_allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SHIM_NONSCANNABLE_ALLOCATOR_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SHIM_NONSCANNABLE_ALLOCATOR_H_

#include <atomic>
#include <cstddef>
#include <memory>

#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
#include "base/allocator/partition_allocator/partition_alloc_base/no_destructor.h"
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#include "base/allocator/partition_allocator/partition_alloc.h"

#if BUILDFLAG(USE_STARSCAN)
#include "base/allocator/partition_allocator/starscan/metadata_allocator.h"
#endif
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

namespace allocator_shim {

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
namespace internal {

// Represents allocator that contains memory for data-like objects (that don't
// contain pointers/references) and therefore doesn't require scanning by
// PCScan. An example would be strings or socket/IPC/file buffers. Use with
// caution.
template <bool quarantinable>
class PA_COMPONENT_EXPORT(PARTITION_ALLOC) NonScannableAllocatorImpl final {
public:
static NonScannableAllocatorImpl& Instance();

NonScannableAllocatorImpl(const NonScannableAllocatorImpl&) = delete;
NonScannableAllocatorImpl& operator=(const NonScannableAllocatorImpl&) =
delete;

void* Alloc(size_t size);
static void Free(void*);

// Returns PartitionRoot corresponding to the allocator, or nullptr if the
// allocator is not enabled.
partition_alloc::ThreadSafePartitionRoot* root() {
#if BUILDFLAG(USE_STARSCAN)
if (!allocator_.get()) {
return nullptr;
}
return allocator_->root();
#else
return nullptr;
#endif // BUILDFLAG(USE_STARSCAN)
}

void NotifyPCScanEnabled();

private:
template <typename>
friend class partition_alloc::internal::base::NoDestructor;

NonScannableAllocatorImpl();
~NonScannableAllocatorImpl();

#if BUILDFLAG(USE_STARSCAN)
std::unique_ptr<partition_alloc::PartitionAllocator,
partition_alloc::internal::PCScanMetadataDeleter>
allocator_;
std::atomic_bool pcscan_enabled_{false};
#endif // BUILDFLAG(USE_STARSCAN)
};

extern template class NonScannableAllocatorImpl<true>;
extern template class NonScannableAllocatorImpl<false>;

} // namespace internal

using NonScannableAllocator = internal::NonScannableAllocatorImpl<true>;
using NonQuarantinableAllocator = internal::NonScannableAllocatorImpl<false>;

#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

} // namespace allocator_shim

#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SHIM_NONSCANNABLE_ALLOCATOR_H_
90 changes: 7 additions & 83 deletions base/memory/nonscannable_memory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,119 +4,43 @@

#include "base/memory/nonscannable_memory.h"

#include <stdlib.h>

#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
#include "base/allocator/partition_allocator/partition_root.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#include "base/allocator/partition_alloc_features.h"
#include "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.h"

#if BUILDFLAG(USE_STARSCAN)
#include "base/allocator/partition_allocator/starscan/metadata_allocator.h"
#include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/allocator/partition_allocator/shim/nonscannable_allocator.h"
#else
#include <stdlib.h>
#endif
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

namespace base {
namespace internal {

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
template <bool Quarantinable>
NonScannableAllocatorImpl<Quarantinable>::NonScannableAllocatorImpl() = default;
template <bool Quarantinable>
NonScannableAllocatorImpl<Quarantinable>::~NonScannableAllocatorImpl() =
default;

template <bool Quarantinable>
NonScannableAllocatorImpl<Quarantinable>&
NonScannableAllocatorImpl<Quarantinable>::Instance() {
static base::NoDestructor<NonScannableAllocatorImpl> instance;
return *instance;
}

template <bool Quarantinable>
void* NonScannableAllocatorImpl<Quarantinable>::Alloc(size_t size) {
#if BUILDFLAG(USE_STARSCAN)
// TODO(bikineev): Change to LIKELY once PCScan is enabled by default.
if (UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
PA_DCHECK(allocator_.get());
return allocator_->root()->AllocWithFlagsNoHooks(
0, size, partition_alloc::PartitionPageSize());
}
#endif // BUILDFLAG(USE_STARSCAN)
// Otherwise, dispatch to default partition.
return allocator_shim::internal::PartitionAllocMalloc::Allocator()
->AllocWithFlagsNoHooks(0, size, partition_alloc::PartitionPageSize());
}

template <bool Quarantinable>
void NonScannableAllocatorImpl<Quarantinable>::Free(void* ptr) {
partition_alloc::ThreadSafePartitionRoot::FreeNoHooks(ptr);
}

template <bool Quarantinable>
void NonScannableAllocatorImpl<Quarantinable>::NotifyPCScanEnabled() {
#if BUILDFLAG(USE_STARSCAN)
allocator_.reset(partition_alloc::internal::MakePCScanMetadata<
partition_alloc::PartitionAllocator>());
allocator_->init(partition_alloc::PartitionOptions{
.quarantine =
Quarantinable
? partition_alloc::PartitionOptions::Quarantine::kAllowed
: partition_alloc::PartitionOptions::Quarantine::kDisallowed,
.cookie = partition_alloc::PartitionOptions::Cookie::kAllowed,
.backup_ref_ptr =
partition_alloc::PartitionOptions::BackupRefPtr::kDisabled,
});
if (Quarantinable) {
partition_alloc::internal::PCScan::RegisterNonScannableRoot(
allocator_->root());
}
pcscan_enabled_.store(true, std::memory_order_release);
#endif // BUILDFLAG(USE_STARSCAN)
}

template class NonScannableAllocatorImpl<true>;
template class NonScannableAllocatorImpl<false>;

#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

} // namespace internal

void* AllocNonScannable(size_t size) {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
return internal::NonScannableAllocatorImpl</*Quarantinable=*/true>::Instance()
.Alloc(size);
return allocator_shim::NonScannableAllocator::Instance().Alloc(size);
#else
return ::malloc(size);
#endif
}

void FreeNonScannable(void* ptr) {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
internal::NonScannableAllocatorImpl</*Quarantinable=*/true>::Free(ptr);
allocator_shim::NonScannableAllocator::Free(ptr);
#else
return ::free(ptr);
#endif
}

void* AllocNonQuarantinable(size_t size) {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
return internal::NonScannableAllocatorImpl<
/*Quarantinable=*/false>::Instance()
.Alloc(size);
return allocator_shim::NonQuarantinableAllocator::Instance().Alloc(size);
#else
return ::malloc(size);
#endif
}

void FreeNonQuarantinable(void* ptr) {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
internal::NonScannableAllocatorImpl</*Quarantinable=*/false>::Free(ptr);
allocator_shim::NonQuarantinableAllocator::Free(ptr);
#else
return ::free(ptr);
#endif
Expand Down

0 comments on commit 8fb5059

Please sign in to comment.