• 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_BASE_PAGED_MEMORY_H_
18 #define INCLUDE_PERFETTO_BASE_PAGED_MEMORY_H_
19 
20 #include <memory>
21 
22 #include "perfetto/base/build_config.h"
23 #include "perfetto/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. |size| must be a
60   // multiple of 4KB (a page size). For |flags|, see the AllocationFlags enum
61   // above.
62   static PagedMemory Allocate(size_t size, int flags = 0);
63 
64   // Hint to the OS that the memory range is not needed and can be discarded.
65   // The memory remains accessible and its contents may be retained, or they
66   // may be zeroed. This function may be a NOP on some platforms. Returns true
67   // if implemented.
68   bool AdviseDontNeed(void* p, size_t size);
69 
70   // Ensures that at least the first |committed_size| bytes of the allocated
71   // memory region are committed. The implementation may commit memory in larger
72   // chunks above |committed_size|. Crashes if the memory couldn't be committed.
73 #if TRACK_COMMITTED_SIZE()
74   void EnsureCommitted(size_t committed_size);
75 #else  // TRACK_COMMITTED_SIZE()
EnsureCommitted(size_t)76   void EnsureCommitted(size_t /*committed_size*/) {}
77 #endif  // TRACK_COMMITTED_SIZE()
78 
Get()79   inline void* Get() const noexcept { return p_; }
IsValid()80   inline bool IsValid() const noexcept { return !!p_; }
size()81   inline size_t size() const noexcept { return size_; }
82 
83  private:
84   PagedMemory(char* p, size_t size);
85 
86   PagedMemory(const PagedMemory&) = delete;
87   // Defaulted for implementation of move constructor + assignment.
88   PagedMemory& operator=(const PagedMemory&) = default;
89 
90   char* p_ = nullptr;
91   size_t size_ = 0;
92 
93 #if TRACK_COMMITTED_SIZE()
94   size_t committed_size_ = 0u;
95 #endif  // TRACK_COMMITTED_SIZE()
96 };
97 
98 }  // namespace base
99 }  // namespace perfetto
100 
101 #endif  // INCLUDE_PERFETTO_BASE_PAGED_MEMORY_H_
102