chromium/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.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/shim/allocator_shim_default_dispatch_to_partition_alloc.h"

#include <atomic>
#include <cstddef>
#include <map>
#include <string>
#include <tuple>

#include "partition_alloc/allocation_guard.h"
#include "partition_alloc/build_config.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/memory_reclaimer.h"
#include "partition_alloc/partition_alloc.h"
#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/no_destructor.h"
#include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
#include "partition_alloc/partition_alloc_base/numerics/safe_conversions.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_alloc_constants.h"
#include "partition_alloc/partition_root.h"
#include "partition_alloc/partition_stats.h"
#include "partition_alloc/shim/allocator_dispatch.h"
#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_internal.h"
#include "partition_alloc/shim/allocator_shim_internals.h"

#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
#include <malloc.h>
#endif

AllocatorDispatch;

namespace {

class SimpleScopedSpinLocker {};

// We can't use a "static local" or a base::LazyInstance, as:
// - static local variables call into the runtime on Windows, which is not
//   prepared to handle it, as the first allocation happens during CRT init.
// - We don't want to depend on base::LazyInstance, which may be converted to
//   static locals one day.
//
// Nevertheless, this provides essentially the same thing.
template <typename T, typename Constructor>
class LeakySingleton {};

template <typename T, typename Constructor>
T* LeakySingleton<T, Constructor>::GetSlowPath() {}

class MainPartitionConstructor {};

LeakySingleton<partition_alloc::PartitionRoot, MainPartitionConstructor> g_root
    PA_CONSTINIT =;
partition_alloc::PartitionRoot* Allocator() {}

// Original g_root_ if it was replaced by ConfigurePartitions().
std::atomic<partition_alloc::PartitionRoot*> g_original_root(nullptr);

std::atomic<bool> g_roots_finalized =;

partition_alloc::PartitionRoot* OriginalAllocator() {}

bool AllocatorConfigurationFinalized() {}

template <partition_alloc::AllocFlags flags>
void* AllocateAlignedMemory(size_t alignment, size_t size) {}

}  // namespace

namespace allocator_shim::internal {

void* PartitionMalloc(size_t size, void* context) {}

void* PartitionMallocUnchecked(size_t size, void* context) {}

void* PartitionCalloc(size_t n, size_t size, void* context) {}

void* PartitionMemalign(size_t alignment, size_t size, void* context) {}

void* PartitionAlignedAlloc(size_t size, size_t alignment, void* context) {}

void* PartitionAlignedAllocUnchecked(size_t size,
                                     size_t alignment,
                                     void* context) {}

// aligned_realloc documentation is
// https://docs.microsoft.com/ja-jp/cpp/c-runtime-library/reference/aligned-realloc
// TODO(tasak): Expand the given memory block to the given size if possible.
// This realloc always free the original memory block and allocates a new memory
// block.
// TODO(tasak): Implement PartitionRoot::AlignedRealloc and use it.
void* PartitionAlignedRealloc(void* address,
                              size_t size,
                              size_t alignment,
                              void* context) {}

void* PartitionAlignedReallocUnchecked(void* address,
                                       size_t size,
                                       size_t alignment,
                                       void* context) {}

void* PartitionRealloc(void* address, size_t size, void* context) {}

void* PartitionReallocUnchecked(void* address, size_t size, void* context) {}

#if PA_BUILDFLAG(IS_CAST_ANDROID)
extern "C" {
void __real_free(void*);
}       // extern "C"
#endif  // PA_BUILDFLAG(IS_CAST_ANDROID)

void PartitionFree(void* object, void* context) {}

#if PA_BUILDFLAG(IS_APPLE)
// Normal free() path on Apple OSes:
// 1. size = GetSizeEstimate(ptr);
// 2. if (size) FreeDefiniteSize(ptr, size)
//
// So we don't need to re-check that the pointer is owned in Free(), and we
// can use the size.
void PartitionFreeDefiniteSize(void* address, size_t size, void* context) {
  partition_alloc::ScopedDisallowAllocations guard{};
  // TODO(lizeb): Optimize PartitionAlloc to use the size information. This is
  // still useful though, as we avoid double-checking that the address is owned.
  partition_alloc::PartitionRoot::FreeInlineInUnknownRoot<
      partition_alloc::FreeFlags::kNoHooks>(address);
}
#endif  // PA_BUILDFLAG(IS_APPLE)

size_t PartitionGetSizeEstimate(void* address, void* context) {}

#if PA_BUILDFLAG(IS_APPLE)
size_t PartitionGoodSize(size_t size, void* context) {
  return Allocator()->AllocationCapacityFromRequestedSize(size);
}

bool PartitionClaimedAddress(void* address, void* context) {
  return partition_alloc::IsManagedByPartitionAlloc(
      reinterpret_cast<uintptr_t>(address));
}
#endif  // PA_BUILDFLAG(IS_APPLE)

unsigned PartitionBatchMalloc(size_t size,
                              void** results,
                              unsigned num_requested,
                              void* context) {}

void PartitionBatchFree(void** to_be_freed,
                        unsigned num_to_be_freed,
                        void* context) {}

#if PA_BUILDFLAG(IS_APPLE)
void PartitionTryFreeDefault(void* address, void* context) {
  partition_alloc::ScopedDisallowAllocations guard{};

  if (!partition_alloc::IsManagedByPartitionAlloc(
          reinterpret_cast<uintptr_t>(address))) [[unlikely]] {
    // The object pointed to by `address` is not allocated by the
    // PartitionAlloc. Call find_zone_and_free.
    return allocator_shim::TryFreeDefaultFallbackToFindZoneAndFree(address);
  }

  partition_alloc::PartitionRoot::FreeInlineInUnknownRoot<
      partition_alloc::FreeFlags::kNoHooks>(address);
}
#endif  // PA_BUILDFLAG(IS_APPLE)

// static
bool PartitionAllocMalloc::AllocatorConfigurationFinalized() {}

// static
partition_alloc::PartitionRoot* PartitionAllocMalloc::Allocator() {}

// static
partition_alloc::PartitionRoot* PartitionAllocMalloc::OriginalAllocator() {}

}  // namespace allocator_shim::internal

#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

namespace allocator_shim {

void EnablePartitionAllocMemoryReclaimer() {}

void ConfigurePartitions(
    EnableBrp enable_brp,
    EnableMemoryTagging enable_memory_tagging,
    partition_alloc::TagViolationReportingMode memory_tagging_reporting_mode,
    BucketDistribution distribution,
    SchedulerLoopQuarantine scheduler_loop_quarantine,
    size_t scheduler_loop_quarantine_branch_capacity_in_bytes,
    ZappingByFreeFlags zapping_by_free_flags,
    UsePoolOffsetFreelists use_pool_offset_freelists,
    UseSmallSingleSlotSpans use_small_single_slot_spans) {}

// No synchronization provided: `PartitionRoot.flags` is only written
// to in `PartitionRoot::Init()`.
uint32_t GetMainPartitionRootExtrasSize() {}

void AdjustDefaultAllocatorForForeground() {}

void AdjustDefaultAllocatorForBackground() {}

}  // namespace allocator_shim

#if !PA_BUILDFLAG( \
    ENABLE_ALLOCATOR_SHIM_PARTITION_ALLOC_DISPATCH_WITH_ADVANCED_CHECKS_SUPPORT)
const AllocatorDispatch AllocatorDispatch::default_dispatch =;
#endif  // !PA_BUILDFLAG(ENABLE_ALLOCATOR_SHIM_PARTITION_ALLOC_DISPATCH_WITH_ADVANCED_CHECKS_SUPPORT)

// Intercept diagnostics symbols as well, even though they are not part of the
// unified shim layer.
//
// TODO(lizeb): Implement the ones that doable.

extern "C" {

#if !PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(IS_ANDROID)

SHIM_ALWAYS_EXPORT void malloc_stats(void) __THROW {}

SHIM_ALWAYS_EXPORT int mallopt(int cmd, int value) __THROW {}

#endif  // !PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(IS_ANDROID)

#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW {}
#endif  // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)

}  // extern "C"

#if PA_BUILDFLAG(IS_APPLE)

namespace allocator_shim {

void InitializeDefaultAllocatorPartitionRoot() {
  // On OS_APPLE, the initialization of PartitionRoot uses memory allocations
  // internally, e.g. __builtin_available, and it's not easy to avoid it.
  // Thus, we initialize the PartitionRoot with using the system default
  // allocator before we intercept the system default allocator.
  std::ignore = Allocator();
}

}  // namespace allocator_shim

#endif  // PA_BUILDFLAG(IS_APPLE)

#endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)