• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
18 #define INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
19 
20 #include <memory>
21 
22 #include "perfetto/base/build_config.h"
23 #include "perfetto/ext/base/container_annotations.h"
24 
25 // We need to track the committed size on windows and when ASAN is enabled.
26 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || defined(ADDRESS_SANITIZER)
27 #define TRACK_COMMITTED_SIZE() 1
28 #else
29 #define TRACK_COMMITTED_SIZE() 0
30 #endif
31 
32 namespace perfetto {
33 namespace base {
34 
35 class PagedMemory {
36  public:
37   // Initializes an invalid PagedMemory pointing to nullptr.
38   PagedMemory();
39 
40   ~PagedMemory();
41 
42   PagedMemory(PagedMemory&& other) noexcept;
43   PagedMemory& operator=(PagedMemory&& other);
44 
45   enum AllocationFlags {
46     // By default, Allocate() crashes if the underlying mmap fails (e.g., if out
47     // of virtual address space). When this flag is provided, an invalid
48     // PagedMemory pointing to nullptr is returned in this case instead.
49     kMayFail = 1 << 0,
50 
51     // By default, Allocate() commits the allocated memory immediately. When
52     // this flag is provided, the memory virtual address space may only be
53     // reserved and the user should call EnsureCommitted() before writing to
54     // memory addresses.
55     kDontCommit = 1 << 1,
56   };
57 
58   // Allocates |size| bytes using mmap(MAP_ANONYMOUS). The returned memory is
59   // guaranteed to be page-aligned and guaranteed to be zeroed.
60   // For |flags|, see the AllocationFlags enum above.
61   static PagedMemory Allocate(size_t size, int flags = 0);
62 
63   // Hint to the OS that the memory range is not needed and can be discarded.
64   // The memory remains accessible and its contents may be retained, or they
65   // may be zeroed. This function may be a NOP on some platforms. Returns true
66   // if implemented.
67   bool AdviseDontNeed(void* p, size_t size);
68 
69   // Ensures that at least the first |committed_size| bytes of the allocated
70   // memory region are committed. The implementation may commit memory in larger
71   // chunks above |committed_size|. Crashes if the memory couldn't be committed.
72 #if TRACK_COMMITTED_SIZE()
73   void EnsureCommitted(size_t committed_size);
74 #else   // TRACK_COMMITTED_SIZE()
EnsureCommitted(size_t)75   void EnsureCommitted(size_t /*committed_size*/) {}
76 #endif  // TRACK_COMMITTED_SIZE()
77 
Get()78   inline void* Get() const noexcept { return p_; }
IsValid()79   inline bool IsValid() const noexcept { return !!p_; }
size()80   inline size_t size() const noexcept { return size_; }
81 
82  private:
83   PagedMemory(char* p, size_t size);
84 
85   PagedMemory(const PagedMemory&) = delete;
86   // Defaulted for implementation of move constructor + assignment.
87   PagedMemory& operator=(const PagedMemory&) = default;
88 
89   char* p_ = nullptr;
90 
91   // The size originally passed to Allocate(). The actual virtual memory
92   // reservation will be larger due to: (i) guard pages; (ii) rounding up to
93   // the system page size.
94   size_t size_ = 0;
95 
96 #if TRACK_COMMITTED_SIZE()
97   size_t committed_size_ = 0u;
98 #endif  // TRACK_COMMITTED_SIZE()
99 };
100 
101 }  // namespace base
102 }  // namespace perfetto
103 
104 #endif  // INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
105