chromium/base/allocator/partition_allocator/src/partition_alloc/thread_cache.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "partition_alloc/thread_cache.h"

#include <sys/types.h>

#include <algorithm>
#include <atomic>
#include <cstdint>

#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/internal_allocator.h"
#include "partition_alloc/partition_alloc-inl.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#include "partition_alloc/partition_alloc_base/immediate_crash.h"
#include "partition_alloc/partition_alloc_base/time/time.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/partition_alloc_constants.h"
#include "partition_alloc/partition_freelist_entry.h"
#include "partition_alloc/partition_root.h"

namespace partition_alloc {

namespace {
ThreadCacheRegistry g_instance;
}  // namespace

namespace tools {
uintptr_t kThreadCacheNeedleArray[kThreadCacheNeedleArraySize] =;
}  // namespace tools

namespace internal {

PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionTlsKey g_thread_cache_key;
#if PA_CONFIG(THREAD_CACHE_FAST_TLS)
PA_COMPONENT_EXPORT(PARTITION_ALLOC)
thread_local ThreadCache* g_thread_cache;
#endif

}  // namespace internal

namespace {
// Since |g_thread_cache_key| is shared, make sure that no more than one
// PartitionRoot can use it.
static std::atomic<PartitionRoot*> g_thread_cache_root;

#if PA_BUILDFLAG(IS_WIN)
void OnDllProcessDetach() {
  // Very late allocations do occur (see crbug.com/1159411#c7 for instance),
  // including during CRT teardown. This is problematic for the thread cache
  // which relies on the CRT for TLS access for instance. This cannot be
  // mitigated inside the thread cache (since getting to it requires querying
  // TLS), but the PartitionRoot associated wih the thread cache can be made to
  // not use the thread cache anymore.
  g_thread_cache_root.load(std::memory_order_relaxed)
      ->settings.with_thread_cache = false;
}
#endif

static bool g_thread_cache_key_created =;
}  // namespace

uint8_t ThreadCache::global_limits_[ThreadCache::kBucketCount];

// Start with the normal size, not the maximum one.
uint16_t ThreadCache::largest_active_bucket_index_ =;

// static
ThreadCacheRegistry& ThreadCacheRegistry::Instance() {}

const internal::PartitionFreelistDispatcher*
ThreadCache::get_freelist_dispatcher_from_root() {}

void ThreadCacheRegistry::RegisterThreadCache(ThreadCache* cache) {}

void ThreadCacheRegistry::UnregisterThreadCache(ThreadCache* cache) {}

void ThreadCacheRegistry::DumpStats(bool my_thread_only,
                                    ThreadCacheStats* stats) {}

void ThreadCacheRegistry::PurgeAll() {}

void ThreadCacheRegistry::ForcePurgeAllThreadAfterForkUnsafe() {}

void ThreadCacheRegistry::SetLargestActiveBucketIndex(
    uint16_t largest_active_bucket_index) {}

void ThreadCacheRegistry::SetThreadCacheMultiplier(float multiplier) {}

void ThreadCacheRegistry::SetPurgingConfiguration(
    const internal::base::TimeDelta min_purge_interval,
    const internal::base::TimeDelta max_purge_interval,
    const internal::base::TimeDelta default_purge_interval,
    size_t min_cached_memory_for_purging_bytes) {}

void ThreadCacheRegistry::RunPeriodicPurge() {}

int64_t ThreadCacheRegistry::GetPeriodicPurgeNextIntervalInMicroseconds()
    const {}

void ThreadCacheRegistry::ResetForTesting() {}

// static
void ThreadCache::EnsureThreadSpecificDataInitialized() {}

// static
void ThreadCache::DeleteForTesting(ThreadCache* tcache) {}

// static
void ThreadCache::SwapForTesting(PartitionRoot* root) {}

// static
void ThreadCache::RemoveTombstoneForTesting() {}

// static
void ThreadCache::Init(PartitionRoot* root) {}

// static
void ThreadCache::SetGlobalLimits(PartitionRoot* root, float multiplier) {}

// static
void ThreadCache::SetLargestCachedSize(size_t size) {}

// static
ThreadCache* ThreadCache::Create(PartitionRoot* root) {}

ThreadCache::ThreadCache(PartitionRoot* root)
    :{}

ThreadCache::~ThreadCache() {}

// static
void ThreadCache::Delete(void* tcache_ptr) {}

// static
void* ThreadCache::operator new(size_t count) {}
// static
void ThreadCache::operator delete(void* ptr) {}

ThreadCache::Bucket::Bucket() {}

void ThreadCache::FillBucket(size_t bucket_index) {}

void ThreadCache::ClearBucket(Bucket& bucket, size_t limit) {}

template <bool crash_on_corruption>
void ThreadCache::ClearBucketHelper(Bucket& bucket, size_t limit) {}

template <bool crash_on_corruption>
void ThreadCache::FreeAfter(internal::PartitionFreelistEntry* head,
                            size_t slot_size) {}

void ThreadCache::ResetForTesting() {}

size_t ThreadCache::CachedMemory() const {}

void ThreadCache::AccumulateStats(ThreadCacheStats* stats) const {}

void ThreadCache::SetShouldPurge() {}

void ThreadCache::Purge() {}

void ThreadCache::TryPurge() {}

// static
void ThreadCache::PurgeCurrentThread() {}

void ThreadCache::PurgeInternal() {}

void ThreadCache::ResetPerThreadAllocationStatsForTesting() {}

template <bool crash_on_corruption>
void ThreadCache::PurgeInternalHelper() {}

}  // namespace partition_alloc