blob: a0cda4c9b1e961263abeff59731e712ab5b04de4 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_
#include <cstdint>
#include "partition_alloc/address_pool_manager.h"
#include "partition_alloc/address_pool_manager_types.h"
#include "partition_alloc/partition_alloc_constants.h"
#include "partition_alloc/partition_alloc_forward.h"
#include "partition_alloc/partition_dcheck_helper.h"
#include "partition_alloc/reservation_offset_table.h"
// Should not include partition_root.h, partition_bucket.h, partition_page.h.
// For IsQuarantineAllowed(), use partition_dcheck_helper.h instead of
// partition_root.h.
namespace partition_alloc::internal {
// An "extent" is a span of consecutive superpages. We link the partition's next
// extent (if there is one) to the very start of a superpage's metadata area.
struct PartitionSuperPageExtentEntry {
PartitionRoot* root;
PartitionSuperPageExtentEntry* next;
uint16_t number_of_consecutive_super_pages;
uint16_t number_of_nonempty_slot_spans;
PA_ALWAYS_INLINE void IncrementNumberOfNonemptySlotSpans() {
DCheckNumberOfPartitionPagesInSuperPagePayload(
this, root, number_of_nonempty_slot_spans);
++number_of_nonempty_slot_spans;
}
PA_ALWAYS_INLINE void DecrementNumberOfNonemptySlotSpans() {
PA_DCHECK(number_of_nonempty_slot_spans);
--number_of_nonempty_slot_spans;
}
};
static_assert(
sizeof(PartitionSuperPageExtentEntry) <= kPageMetadataSize,
"PartitionSuperPageExtentEntry must be able to fit in a metadata slot");
static_assert(kMaxSuperPagesInPool / kSuperPageSize <=
std::numeric_limits<
decltype(PartitionSuperPageExtentEntry ::
number_of_consecutive_super_pages)>::max(),
"number_of_consecutive_super_pages must be big enough");
// Returns the base of the first super page in the range of consecutive super
// pages.
//
// CAUTION! |extent| must point to the extent of the first super page in the
// range of consecutive super pages.
PA_ALWAYS_INLINE uintptr_t
SuperPagesBeginFromExtent(const PartitionSuperPageExtentEntry* extent) {
PA_DCHECK(0 < extent->number_of_consecutive_super_pages);
uintptr_t extent_as_uintptr = reinterpret_cast<uintptr_t>(extent);
PA_DCHECK(IsManagedByNormalBuckets(extent_as_uintptr));
return base::bits::AlignDown(extent_as_uintptr, kSuperPageAlignment);
}
// Returns the end of the last super page in the range of consecutive super
// pages.
//
// CAUTION! |extent| must point to the extent of the first super page in the
// range of consecutive super pages.
PA_ALWAYS_INLINE uintptr_t
SuperPagesEndFromExtent(const PartitionSuperPageExtentEntry* extent) {
return SuperPagesBeginFromExtent(extent) +
(extent->number_of_consecutive_super_pages * kSuperPageSize);
}
} // namespace partition_alloc::internal
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_