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