#include "base/allocator/partition_allocator/extended_api.h"
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
#include "base/allocator/partition_allocator/partition_alloc_config.h"
#include "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
#include "base/allocator/partition_allocator/thread_cache.h"
namespace partition_alloc::internal {
#if PA_CONFIG(THREAD_CACHE_SUPPORTED)
namespace {
void DisableThreadCacheForRootIfEnabled(ThreadSafePartitionRoot* root) {
if (!root || !root->flags.with_thread_cache) {
return;
}
ThreadCacheRegistry::Instance().PurgeAll();
root->flags.with_thread_cache = false;
}
void EnablePartitionAllocThreadCacheForRootIfDisabled(
ThreadSafePartitionRoot* root) {
if (!root) {
return;
}
root->flags.with_thread_cache = true;
}
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
void DisablePartitionAllocThreadCacheForProcess() {
auto* regular_allocator =
allocator_shim::internal::PartitionAllocMalloc::Allocator();
auto* aligned_allocator =
allocator_shim::internal::PartitionAllocMalloc::AlignedAllocator();
DisableThreadCacheForRootIfEnabled(regular_allocator);
if (aligned_allocator != regular_allocator) {
DisableThreadCacheForRootIfEnabled(aligned_allocator);
}
DisableThreadCacheForRootIfEnabled(
allocator_shim::internal::PartitionAllocMalloc::OriginalAllocator());
}
#endif
}
#endif
ThreadAllocStats GetAllocStatsForCurrentThread() {
ThreadCache* thread_cache = ThreadCache::Get();
if (ThreadCache::IsValid(thread_cache)) {
return thread_cache->thread_alloc_stats();
}
return {};
}
#if PA_CONFIG(THREAD_CACHE_SUPPORTED)
ThreadCacheProcessScopeForTesting::ThreadCacheProcessScopeForTesting(
ThreadSafePartitionRoot* root)
: root_(root) {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
auto* regular_allocator =
allocator_shim::internal::PartitionAllocMalloc::Allocator();
regular_was_enabled_ =
regular_allocator && regular_allocator->flags.with_thread_cache;
if (root_ != regular_allocator) {
DisablePartitionAllocThreadCacheForProcess();
EnablePartitionAllocThreadCacheForRootIfDisabled(root_);
ThreadCache::SwapForTesting(root_);
} else {
if (!regular_was_enabled_) {
EnablePartitionAllocThreadCacheForRootIfDisabled(root_);
ThreadCache::SwapForTesting(root_);
}
}
#else
PA_CHECK(!ThreadCache::IsValid(ThreadCache::Get()));
EnablePartitionAllocThreadCacheForRootIfDisabled(root_);
ThreadCache::SwapForTesting(root_);
#endif
PA_CHECK(ThreadCache::Get());
}
ThreadCacheProcessScopeForTesting::~ThreadCacheProcessScopeForTesting() {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
auto* regular_allocator =
allocator_shim::internal::PartitionAllocMalloc::Allocator();
bool regular_enabled =
regular_allocator && regular_allocator->flags.with_thread_cache;
if (regular_was_enabled_) {
if (!regular_enabled) {
EnablePartitionAllocThreadCacheForRootIfDisabled(regular_allocator);
ThreadCache::SwapForTesting(regular_allocator);
} else {
if (regular_allocator != root_) {
ThreadCache::SwapForTesting(regular_allocator);
}
}
} else {
DisableThreadCacheForRootIfEnabled(regular_allocator);
ThreadCache::SwapForTesting(nullptr);
}
#else
DisableThreadCacheForRootIfEnabled(root_);
ThreadCache::SwapForTesting(nullptr);
#endif
}
#endif
}