Line | Count | Source |
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 | | #include "rocksdb/slice.h" |
21 | | |
22 | | namespace ROCKSDB_NAMESPACE { |
23 | | |
24 | | // An RAII wrapper for mmaped memory |
25 | | class MemMapping { |
26 | | public: |
27 | | static constexpr bool kHugePageSupported = |
28 | | #if defined(MAP_HUGETLB) || defined(FILE_MAP_LARGE_PAGES) |
29 | | true; |
30 | | #else |
31 | | false; |
32 | | #endif |
33 | | |
34 | | // Allocate memory requesting to be backed by huge pages |
35 | | static MemMapping AllocateHuge(size_t length); |
36 | | |
37 | | // Allocate memory that is only lazily mapped to resident memory and |
38 | | // guaranteed to be zero-initialized. Note that some platforms like |
39 | | // Linux allow memory over-commit, where only the used portion of memory |
40 | | // matters, while other platforms require enough swap space (page file) to |
41 | | // back the full mapping. |
42 | | static MemMapping AllocateLazyZeroed(size_t length); |
43 | | |
44 | | // No copies |
45 | | MemMapping(const MemMapping&) = delete; |
46 | | MemMapping& operator=(const MemMapping&) = delete; |
47 | | // Move |
48 | | MemMapping(MemMapping&&) noexcept; |
49 | | MemMapping& operator=(MemMapping&&) noexcept; |
50 | | |
51 | | // Releases the mapping |
52 | | ~MemMapping(); |
53 | | |
54 | 79.3M | inline void* Get() const { return addr_; } |
55 | | // The requested length of the mapping, which may be smaller than the |
56 | | // actual usable length |
57 | 607k | inline size_t Length() const { return length_; } |
58 | | |
59 | | // Return the mapping as a Slice (zero-copy view of the mapped memory) |
60 | 0 | inline Slice AsSlice() const { |
61 | 0 | return Slice(static_cast<const char*>(addr_), length_); |
62 | 0 | } |
63 | | |
64 | | private: |
65 | 1.21M | MemMapping() {} |
66 | | |
67 | | // The mapped memory, or nullptr on failure / not supported |
68 | | void* addr_ = nullptr; |
69 | | // The known usable number of bytes starting at that address |
70 | | size_t length_ = 0; |
71 | | |
72 | | #ifdef OS_WIN |
73 | | HANDLE page_file_handle_ = NULL; |
74 | | #endif // OS_WIN |
75 | | |
76 | | static MemMapping AllocateAnonymous(size_t length, bool huge); |
77 | | }; |
78 | | |
79 | | // Simple MemMapping wrapper that presents the memory as an array of T. |
80 | | // For example, |
81 | | // TypedMemMapping<uint64_t> arr = MemMapping::AllocateLazyZeroed(num_bytes); |
82 | | template <typename T> |
83 | | class TypedMemMapping : public MemMapping { |
84 | | public: |
85 | | /*implicit*/ TypedMemMapping(MemMapping&& v) noexcept |
86 | 607k | : MemMapping(std::move(v)) {} |
87 | | TypedMemMapping& operator=(MemMapping&& v) noexcept { |
88 | | MemMapping& base = *this; |
89 | | base = std::move(v); |
90 | | } |
91 | | |
92 | 79.3M | inline T* Get() const { return static_cast<T*>(MemMapping::Get()); } |
93 | 607k | inline size_t Count() const { return MemMapping::Length() / sizeof(T); } |
94 | | |
95 | 78.4M | inline T& operator[](size_t index) const { return Get()[index]; } |
96 | | }; |
97 | | |
98 | | } // namespace ROCKSDB_NAMESPACE |