Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) Meta Platforms, Inc. and affiliates. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | |
6 | | #pragma once |
7 | | |
8 | | #ifdef OS_WIN |
9 | | #include "port/win/port_win.h" |
10 | | // ^^^ For proper/safe inclusion of windows.h. Must come first. |
11 | | #include <memoryapi.h> |
12 | | #else |
13 | | #include <sys/mman.h> |
14 | | #endif // OS_WIN |
15 | | |
16 | | #include <cstdint> |
17 | | #include <utility> |
18 | | |
19 | | #include "rocksdb/rocksdb_namespace.h" |
20 | | |
21 | | namespace ROCKSDB_NAMESPACE { |
22 | | |
23 | | // An RAII wrapper for mmaped memory |
24 | | class MemMapping { |
25 | | public: |
26 | | static constexpr bool kHugePageSupported = |
27 | | #if defined(MAP_HUGETLB) || defined(FILE_MAP_LARGE_PAGES) |
28 | | true; |
29 | | #else |
30 | | false; |
31 | | #endif |
32 | | |
33 | | // Allocate memory requesting to be backed by huge pages |
34 | | static MemMapping AllocateHuge(size_t length); |
35 | | |
36 | | // Allocate memory that is only lazily mapped to resident memory and |
37 | | // guaranteed to be zero-initialized. Note that some platforms like |
38 | | // Linux allow memory over-commit, where only the used portion of memory |
39 | | // matters, while other platforms require enough swap space (page file) to |
40 | | // back the full mapping. |
41 | | static MemMapping AllocateLazyZeroed(size_t length); |
42 | | |
43 | | // No copies |
44 | | MemMapping(const MemMapping&) = delete; |
45 | | MemMapping& operator=(const MemMapping&) = delete; |
46 | | // Move |
47 | | MemMapping(MemMapping&&) noexcept; |
48 | | MemMapping& operator=(MemMapping&&) noexcept; |
49 | | |
50 | | // Releases the mapping |
51 | | ~MemMapping(); |
52 | | |
53 | 0 | inline void* Get() const { return addr_; } |
54 | 0 | inline size_t Length() const { return length_; } |
55 | | |
56 | | private: |
57 | 0 | MemMapping() {} |
58 | | |
59 | | // The mapped memory, or nullptr on failure / not supported |
60 | | void* addr_ = nullptr; |
61 | | // The known usable number of bytes starting at that address |
62 | | size_t length_ = 0; |
63 | | |
64 | | #ifdef OS_WIN |
65 | | HANDLE page_file_handle_ = NULL; |
66 | | #endif // OS_WIN |
67 | | |
68 | | static MemMapping AllocateAnonymous(size_t length, bool huge); |
69 | | }; |
70 | | |
71 | | // Simple MemMapping wrapper that presents the memory as an array of T. |
72 | | // For example, |
73 | | // TypedMemMapping<uint64_t> arr = MemMapping::AllocateLazyZeroed(num_bytes); |
74 | | template <typename T> |
75 | | class TypedMemMapping : public MemMapping { |
76 | | public: |
77 | | /*implicit*/ TypedMemMapping(MemMapping&& v) noexcept |
78 | 0 | : MemMapping(std::move(v)) {} |
79 | | TypedMemMapping& operator=(MemMapping&& v) noexcept { |
80 | | MemMapping& base = *this; |
81 | | base = std::move(v); |
82 | | } |
83 | | |
84 | 0 | inline T* Get() const { return static_cast<T*>(MemMapping::Get()); } |
85 | 0 | inline size_t Count() const { return MemMapping::Length() / sizeof(T); } |
86 | | |
87 | 0 | inline T& operator[](size_t index) const { return Get()[index]; } |
88 | | }; |
89 | | |
90 | | } // namespace ROCKSDB_NAMESPACE |