partition_alloc.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/allocator/partition_allocator/partition_alloc.h"
  5. #include <string.h>
  6. #include <cstdint>
  7. #include <memory>
  8. #include "base/allocator/partition_allocator/address_pool_manager.h"
  9. #include "base/allocator/partition_allocator/memory_reclaimer.h"
  10. #include "base/allocator/partition_allocator/partition_address_space.h"
  11. #include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
  12. #include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
  13. #include "base/allocator/partition_allocator/partition_alloc_hooks.h"
  14. #include "base/allocator/partition_allocator/partition_direct_map_extent.h"
  15. #include "base/allocator/partition_allocator/partition_oom.h"
  16. #include "base/allocator/partition_allocator/partition_page.h"
  17. #include "base/allocator/partition_allocator/partition_root.h"
  18. #include "base/allocator/partition_allocator/partition_stats.h"
  19. #include "base/allocator/partition_allocator/starscan/pcscan.h"
  20. namespace partition_alloc {
  21. void PartitionAllocGlobalInit(OomFunction on_out_of_memory) {
  22. // This is from page_allocator_constants.h and doesn't really fit here, but
  23. // there isn't a centralized initialization function in page_allocator.cc, so
  24. // there's no good place in that file to do a STATIC_ASSERT_OR_PA_CHECK.
  25. STATIC_ASSERT_OR_PA_CHECK(
  26. (internal::SystemPageSize() & internal::SystemPageOffsetMask()) == 0,
  27. "SystemPageSize() must be power of 2");
  28. // Two partition pages are used as guard / metadata page so make sure the
  29. // super page size is bigger.
  30. STATIC_ASSERT_OR_PA_CHECK(
  31. internal::PartitionPageSize() * 4 <= internal::kSuperPageSize,
  32. "ok super page size");
  33. STATIC_ASSERT_OR_PA_CHECK(
  34. (internal::kSuperPageSize & internal::SystemPageOffsetMask()) == 0,
  35. "ok super page multiple");
  36. // Four system pages gives us room to hack out a still-guard-paged piece
  37. // of metadata in the middle of a guard partition page.
  38. STATIC_ASSERT_OR_PA_CHECK(
  39. internal::SystemPageSize() * 4 <= internal::PartitionPageSize(),
  40. "ok partition page size");
  41. STATIC_ASSERT_OR_PA_CHECK(
  42. (internal::PartitionPageSize() & internal::SystemPageOffsetMask()) == 0,
  43. "ok partition page multiple");
  44. static_assert(sizeof(internal::PartitionPage<internal::ThreadSafe>) <=
  45. internal::kPageMetadataSize,
  46. "PartitionPage should not be too big");
  47. STATIC_ASSERT_OR_PA_CHECK(
  48. internal::kPageMetadataSize * internal::NumPartitionPagesPerSuperPage() <=
  49. internal::SystemPageSize(),
  50. "page metadata fits in hole");
  51. // Limit to prevent callers accidentally overflowing an int size.
  52. STATIC_ASSERT_OR_PA_CHECK(
  53. internal::MaxDirectMapped() <=
  54. (1UL << 31) + internal::DirectMapAllocationGranularity(),
  55. "maximum direct mapped allocation");
  56. // Check that some of our zanier calculations worked out as expected.
  57. static_assert(internal::kSmallestBucket == internal::kAlignment,
  58. "generic smallest bucket");
  59. static_assert(internal::kMaxBucketed == 917504, "generic max bucketed");
  60. STATIC_ASSERT_OR_PA_CHECK(
  61. internal::MaxSystemPagesPerRegularSlotSpan() <= 16,
  62. "System pages per slot span must be no greater than 16.");
  63. #if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
  64. STATIC_ASSERT_OR_PA_CHECK(
  65. internal::GetPartitionRefCountIndexMultiplierShift() <
  66. std::numeric_limits<size_t>::max() / 2,
  67. "Calculation in GetPartitionRefCountIndexMultiplierShift() must not "
  68. "underflow.");
  69. // Check that the GetPartitionRefCountIndexMultiplierShift() calculation is
  70. // correct.
  71. STATIC_ASSERT_OR_PA_CHECK(
  72. (1 << internal::GetPartitionRefCountIndexMultiplierShift()) ==
  73. (internal::SystemPageSize() /
  74. (sizeof(internal::PartitionRefCount) *
  75. (internal::kSuperPageSize / internal::SystemPageSize()))),
  76. "Bitshift must match the intended multiplication.");
  77. STATIC_ASSERT_OR_PA_CHECK(
  78. ((sizeof(internal::PartitionRefCount) *
  79. (internal::kSuperPageSize / internal::SystemPageSize()))
  80. << internal::GetPartitionRefCountIndexMultiplierShift()) <=
  81. internal::SystemPageSize(),
  82. "PartitionRefCount Bitmap size must be smaller than or equal to "
  83. "<= SystemPageSize().");
  84. #endif // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
  85. PA_DCHECK(on_out_of_memory);
  86. internal::g_oom_handling_function = on_out_of_memory;
  87. }
  88. void PartitionAllocGlobalUninitForTesting() {
  89. internal::PCScan::UninitForTesting(); // IN-TEST
  90. #if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  91. #if defined(PA_HAS_64_BITS_POINTERS)
  92. internal::PartitionAddressSpace::UninitForTesting();
  93. #else
  94. internal::AddressPoolManager::GetInstance().ResetForTesting();
  95. #endif // defined(PA_HAS_64_BITS_POINTERS)
  96. #endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  97. internal::g_oom_handling_function = nullptr;
  98. }
  99. namespace internal {
  100. template <bool thread_safe>
  101. PartitionAllocator<thread_safe>::~PartitionAllocator() {
  102. MemoryReclaimer::Instance()->UnregisterPartition(&partition_root_);
  103. }
  104. template <bool thread_safe>
  105. void PartitionAllocator<thread_safe>::init(PartitionOptions opts) {
  106. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  107. PA_CHECK(opts.thread_cache == PartitionOptions::ThreadCache::kDisabled)
  108. << "Cannot use a thread cache when PartitionAlloc is malloc().";
  109. #endif
  110. partition_root_.Init(opts);
  111. MemoryReclaimer::Instance()->RegisterPartition(&partition_root_);
  112. }
  113. template PartitionAllocator<internal::ThreadSafe>::~PartitionAllocator();
  114. template void PartitionAllocator<internal::ThreadSafe>::init(PartitionOptions);
  115. #if (BUILDFLAG(PA_DCHECK_IS_ON) || \
  116. BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)) && \
  117. BUILDFLAG(USE_BACKUP_REF_PTR)
  118. void CheckThatSlotOffsetIsZero(uintptr_t address) {
  119. // Add kPartitionPastAllocationAdjustment, because
  120. // PartitionAllocGetSlotStartInBRPPool will subtract it.
  121. PA_CHECK(PartitionAllocGetSlotStartInBRPPool(
  122. address + kPartitionPastAllocationAdjustment) == address);
  123. }
  124. #endif
  125. } // namespace internal
  126. } // namespace partition_alloc