| // Copyright 2021 The Chromium Authors. All rights reserved. |
| // 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/extended_api.h" |
| |
| #include "base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h" |
| #include "base/allocator/buildflags.h" |
| #include "base/allocator/partition_allocator/thread_cache.h" |
| |
| namespace partition_alloc::internal { |
| |
| #if defined(PA_THREAD_CACHE_SUPPORTED) |
| |
| namespace { |
| |
| void DisableThreadCacheForRootIfEnabled(ThreadSafePartitionRoot* root) { |
| // Some platforms don't have a thread cache, or it could already have been |
| // disabled. |
| if (!root || !root->flags.with_thread_cache) |
| return; |
| |
| ThreadCacheRegistry::Instance().PurgeAll(); |
| root->flags.with_thread_cache = false; |
| // Doesn't destroy the thread cache object(s). For background threads, they |
| // will be collected (and free cached memory) at thread destruction |
| // time. For the main thread, we leak it. |
| } |
| |
| 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 = ::base::internal::PartitionAllocMalloc::Allocator(); |
| auto* aligned_allocator = |
| ::base::internal::PartitionAllocMalloc::AlignedAllocator(); |
| DisableThreadCacheForRootIfEnabled(regular_allocator); |
| if (aligned_allocator != regular_allocator) |
| DisableThreadCacheForRootIfEnabled(aligned_allocator); |
| DisableThreadCacheForRootIfEnabled( |
| ::base::internal::PartitionAllocMalloc::OriginalAllocator()); |
| } |
| #endif // defined(USE_PARTITION_ALLOC_AS_MALLOC) |
| |
| } // namespace |
| |
| #endif // defined(PA_THREAD_CACHE_SUPPORTED) |
| |
| void SwapOutProcessThreadCacheForTesting(ThreadSafePartitionRoot* root) { |
| #if defined(PA_THREAD_CACHE_SUPPORTED) |
| |
| #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) |
| DisablePartitionAllocThreadCacheForProcess(); |
| #else |
| PA_CHECK(!ThreadCache::IsValid(ThreadCache::Get())); |
| #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) |
| |
| ThreadCache::SwapForTesting(root); |
| EnablePartitionAllocThreadCacheForRootIfDisabled(root); |
| |
| #endif // defined(PA_THREAD_CACHE_SUPPORTED) |
| } |
| |
| void SwapInProcessThreadCacheForTesting(ThreadSafePartitionRoot* root) { |
| #if defined(PA_THREAD_CACHE_SUPPORTED) |
| |
| // First, disable the test thread cache we have. |
| DisableThreadCacheForRootIfEnabled(root); |
| |
| #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) |
| auto* regular_allocator = ::base::internal::PartitionAllocMalloc::Allocator(); |
| EnablePartitionAllocThreadCacheForRootIfDisabled(regular_allocator); |
| |
| ThreadCache::SwapForTesting(regular_allocator); |
| #else |
| ThreadCache::SwapForTesting(nullptr); |
| #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) |
| |
| #endif // defined(PA_THREAD_CACHE_SUPPORTED) |
| } |
| |
| } // namespace partition_alloc::internal |