1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_ 6 #define PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_ 7 8 #include <cstdint> 9 10 #include "partition_alloc/address_pool_manager.h" 11 #include "partition_alloc/address_pool_manager_types.h" 12 #include "partition_alloc/partition_alloc_constants.h" 13 #include "partition_alloc/partition_alloc_forward.h" 14 #include "partition_alloc/partition_dcheck_helper.h" 15 #include "partition_alloc/reservation_offset_table.h" 16 17 // Should not include partition_root.h, partition_bucket.h, partition_page.h. 18 // For IsQuarantineAllowed(), use partition_dcheck_helper.h instead of 19 // partition_root.h. 20 21 namespace partition_alloc::internal { 22 23 // An "extent" is a span of consecutive superpages. We link the partition's next 24 // extent (if there is one) to the very start of a superpage's metadata area. 25 struct PartitionSuperPageExtentEntry { 26 PartitionRoot* root; 27 PartitionSuperPageExtentEntry* next; 28 uint16_t number_of_consecutive_super_pages; 29 uint16_t number_of_nonempty_slot_spans; 30 IncrementNumberOfNonemptySlotSpansPartitionSuperPageExtentEntry31 PA_ALWAYS_INLINE void IncrementNumberOfNonemptySlotSpans() { 32 DCheckNumberOfPartitionPagesInSuperPagePayload( 33 this, root, number_of_nonempty_slot_spans); 34 ++number_of_nonempty_slot_spans; 35 } 36 DecrementNumberOfNonemptySlotSpansPartitionSuperPageExtentEntry37 PA_ALWAYS_INLINE void DecrementNumberOfNonemptySlotSpans() { 38 PA_DCHECK(number_of_nonempty_slot_spans); 39 --number_of_nonempty_slot_spans; 40 } 41 }; 42 43 static_assert( 44 sizeof(PartitionSuperPageExtentEntry) <= kPageMetadataSize, 45 "PartitionSuperPageExtentEntry must be able to fit in a metadata slot"); 46 static_assert(kMaxSuperPagesInPool / kSuperPageSize <= 47 std::numeric_limits< 48 decltype(PartitionSuperPageExtentEntry :: 49 number_of_consecutive_super_pages)>::max(), 50 "number_of_consecutive_super_pages must be big enough"); 51 52 // Returns the base of the first super page in the range of consecutive super 53 // pages. 54 // 55 // CAUTION! |extent| must point to the extent of the first super page in the 56 // range of consecutive super pages. 57 PA_ALWAYS_INLINE uintptr_t SuperPagesBeginFromExtent(const PartitionSuperPageExtentEntry * extent)58SuperPagesBeginFromExtent(const PartitionSuperPageExtentEntry* extent) { 59 PA_DCHECK(0 < extent->number_of_consecutive_super_pages); 60 uintptr_t extent_as_uintptr = reinterpret_cast<uintptr_t>(extent); 61 PA_DCHECK(IsManagedByNormalBuckets(extent_as_uintptr)); 62 return base::bits::AlignDown(extent_as_uintptr, kSuperPageAlignment); 63 } 64 65 // Returns the end of the last super page in the range of consecutive super 66 // pages. 67 // 68 // CAUTION! |extent| must point to the extent of the first super page in the 69 // range of consecutive super pages. 70 PA_ALWAYS_INLINE uintptr_t SuperPagesEndFromExtent(const PartitionSuperPageExtentEntry * extent)71SuperPagesEndFromExtent(const PartitionSuperPageExtentEntry* extent) { 72 return SuperPagesBeginFromExtent(extent) + 73 (extent->number_of_consecutive_super_pages * kSuperPageSize); 74 } 75 76 } // namespace partition_alloc::internal 77 78 #endif // PARTITION_ALLOC_PARTITION_SUPERPAGE_EXTENT_ENTRY_H_ 79