#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 { … };
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() { … }
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 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) { … }
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*);
}
#endif
void PartitionFree(void* object, void* context) { … }
#if PA_BUILDFLAG(IS_APPLE)
void PartitionFreeDefiniteSize(void* address, size_t size, void* context) {
partition_alloc::ScopedDisallowAllocations guard{};
partition_alloc::PartitionRoot::FreeInlineInUnknownRoot<
partition_alloc::FreeFlags::kNoHooks>(address);
}
#endif
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
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]] {
return allocator_shim::TryFreeDefaultFallbackToFindZoneAndFree(address);
}
partition_alloc::PartitionRoot::FreeInlineInUnknownRoot<
partition_alloc::FreeFlags::kNoHooks>(address);
}
#endif
bool PartitionAllocMalloc::AllocatorConfigurationFinalized() { … }
partition_alloc::PartitionRoot* PartitionAllocMalloc::Allocator() { … }
partition_alloc::PartitionRoot* PartitionAllocMalloc::OriginalAllocator() { … }
}
#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) { … }
uint32_t GetMainPartitionRootExtrasSize() { … }
void AdjustDefaultAllocatorForForeground() { … }
void AdjustDefaultAllocatorForBackground() { … }
}
#if !PA_BUILDFLAG( \
ENABLE_ALLOCATOR_SHIM_PARTITION_ALLOC_DISPATCH_WITH_ADVANCED_CHECKS_SUPPORT)
const AllocatorDispatch AllocatorDispatch::default_dispatch = …;
#endif
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
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS)
SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW { … }
#endif
}
#if PA_BUILDFLAG(IS_APPLE)
namespace allocator_shim {
void InitializeDefaultAllocatorPartitionRoot() {
std::ignore = Allocator();
}
}
#endif
#endif