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