1 // Copyright 2018 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_DIRECT_MAP_EXTENT_H_
6 #define PARTITION_ALLOC_PARTITION_DIRECT_MAP_EXTENT_H_
7 
8 #include "partition_alloc/partition_alloc_base/compiler_specific.h"
9 #include "partition_alloc/partition_alloc_check.h"
10 #include "partition_alloc/partition_bucket.h"
11 #include "partition_alloc/partition_page.h"
12 
13 namespace partition_alloc::internal {
14 
15 struct PartitionDirectMapExtent {
16   PartitionDirectMapExtent* next_extent;
17   PartitionDirectMapExtent* prev_extent;
18   PartitionBucket* bucket;
19   // Size of the entire reservation, including guard pages, meta-data,
20   // padding for alignment before allocation, and padding for granularity at the
21   // end of the allocation.
22   size_t reservation_size;
23   // Padding between the first partition page (guard pages + meta-data) and
24   // the allocation.
25   size_t padding_for_alignment;
26 
27   PA_ALWAYS_INLINE static PartitionDirectMapExtent* FromSlotSpanMetadata(
28       SlotSpanMetadata* slot_span);
29 };
30 
31 // Metadata page for direct-mapped allocations.
32 struct PartitionDirectMapMetadata {
33   // |page_metadata| and |second_page_metadata| are needed to match the
34   // layout of normal buckets (specifically, of single-slot slot spans), with
35   // the caveat that only the first subsequent page is needed (for
36   // SubsequentPageMetadata) and others aren't used for direct map.
37   PartitionPageMetadata page_metadata;
38   PartitionPageMetadata second_page_metadata;
39   // The following fields are metadata specific to direct map allocations. All
40   // these fields will easily fit into the precalculated metadata region,
41   // because a direct map allocation starts no further than half way through the
42   // super page.
43   PartitionBucket bucket;
44   PartitionDirectMapExtent direct_map_extent;
45 
46   PA_ALWAYS_INLINE static PartitionDirectMapMetadata* FromSlotSpanMetadata(
47       SlotSpanMetadata* slot_span);
48 };
49 
50 PA_ALWAYS_INLINE PartitionDirectMapMetadata*
FromSlotSpanMetadata(SlotSpanMetadata * slot_span)51 PartitionDirectMapMetadata::FromSlotSpanMetadata(SlotSpanMetadata* slot_span) {
52   PA_DCHECK(slot_span->bucket->is_direct_mapped());
53   // |*slot_span| is the first field of |PartitionDirectMapMetadata|, just cast.
54   auto* metadata = reinterpret_cast<PartitionDirectMapMetadata*>(slot_span);
55   PA_DCHECK(&metadata->page_metadata.slot_span_metadata == slot_span);
56   return metadata;
57 }
58 
59 PA_ALWAYS_INLINE PartitionDirectMapExtent*
FromSlotSpanMetadata(SlotSpanMetadata * slot_span)60 PartitionDirectMapExtent::FromSlotSpanMetadata(SlotSpanMetadata* slot_span) {
61   PA_DCHECK(slot_span->bucket->is_direct_mapped());
62   return &PartitionDirectMapMetadata::FromSlotSpanMetadata(slot_span)
63               ->direct_map_extent;
64 }
65 
66 }  // namespace partition_alloc::internal
67 
68 #endif  // PARTITION_ALLOC_PARTITION_DIRECT_MAP_EXTENT_H_
69