File: region.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (133 lines) | stat: -rw-r--r-- 4,832 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#ifndef CHROMEOS_ASH_COMPONENTS_MEMORY_USERSPACE_SWAP_REGION_H_
#define CHROMEOS_ASH_COMPONENTS_MEMORY_USERSPACE_SWAP_REGION_H_

#include <sys/uio.h>

#include <cstdint>
#include <optional>
#include <ostream>
#include <string_view>
#include <vector>

#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/numerics/checked_math.h"

namespace ash {
namespace memory {
namespace userspace_swap {

struct RegionOverlap;

// A region describes a block of memory.
class Region {
 public:
  uintptr_t address = 0;
  uintptr_t length = 0;

  Region() = default;
  Region(Region&&) = default;
  Region(const Region&) = default;
  ~Region() = default;
  Region& operator=(const Region&) = default;
  Region& operator=(Region&&) = default;

  template <typename Address, typename Length>
  Region(Address* address, Length length)
      : address(reinterpret_cast<uintptr_t>(const_cast<Address*>(address))),
        length(length) {
    static_assert(std::is_integral<Length>::value,
                  "length must be an integral type");
    static_assert(sizeof(Length) <= sizeof(uintptr_t),
                  "Length cannot be longer than uint64_t");

    // Verify that the end of this region is valid and wouldn't overflow if we
    // added length to the address.
    CHECK((base::CheckedNumeric<uintptr_t>(this->address) + this->length)
              .IsValid());
  }

  template <typename Address, typename Length>
  Region(Address address, Length length)
      : Region(reinterpret_cast<void*>(address), length) {
    static_assert(sizeof(Address) <= sizeof(void*),
                  "Address cannot be longer than a pointer type");
  }

  template <typename Address>
  Region(Address address) : Region(address, 1) {
    static_assert(
        std::is_integral<Address>::value || std::is_pointer<Address>::value,
        "Adress must be integral or pointer type");
  }

  template <typename T>
  Region(const std::vector<T>& vec)
      : Region(vec.data(), vec.size() * sizeof(T)) {}

  template <typename T>
  base::span<T> AsSpan() const {
    return base::span<T>(reinterpret_cast<T*>(address), length);
  }

  struct iovec COMPONENT_EXPORT(USERSPACE_SWAP) AsIovec() const;
  std::string_view COMPONENT_EXPORT(USERSPACE_SWAP) AsStringPiece() const;

  bool operator<(const Region& other) const {
    // Because the standard library treats equality as !less(a,b) &&
    // !less(b,a) our definition of less than will be that this has to be
    // FULLY before other. Overlapping regions are not allowed and are
    // explicitly checked before inserting by using find() any overlap would
    // return equal, this also has the property that you can search for a
    // Region of length 1 to find the mapping for a fault.
    return ((address + length - 1) < other.address);
  }

  // CalculateRegionOverlap can be used to determine how a |range| overlaps with
  // this region. There are five possible outcomes:
  //  1. |range| does not overlap at all with this region, in this situation the
  //  returned RegionOverlap will have none of the members with values.
  //  2. |range| fully covers this region, in this situaton before and after in
  //  the RegionOverlap will be empty and intersection will be identical to this
  //  region.
  //  3. |range| overlaps from the start of of this region, in this case before
  //  will be empty and intersection will contain the overlapped portion and
  //  after will contain the piece that did not intersect.
  //  4. |range| overlaps from the end of this region, In this case before will
  //  contain the piece which does not intersect, intersection will contain the
  //  portion that overlaps and after will be empty.
  //  5. |range| is fully within this region, in this situation all fields will
  //  be set, before will contain the part before the intersection, intersection
  //  will contain an area equal to range, and after will contain the portion
  //  which doesn't intersect after range.
  COMPONENT_EXPORT(USERSPACE_SWAP)
  RegionOverlap CalculateRegionOverlap(const Region& range) const;

  friend std::ostream& operator<<(std::ostream& os, const Region& region);
};

struct COMPONENT_EXPORT(USERSPACE_SWAP) RegionOverlap {
  RegionOverlap();
  ~RegionOverlap();

  RegionOverlap(const RegionOverlap&);

  std::optional<Region> before;
  std::optional<Region> intersection;
  std::optional<Region> after;
};

}  // namespace userspace_swap
}  // namespace memory
}  // namespace ash

#endif  // CHROMEOS_ASH_COMPONENTS_MEMORY_USERSPACE_SWAP_REGION_H_