MySQL 8.0.40
Source Code Documentation
memutils.h
Go to the documentation of this file.
1/* Copyright (c) 2019, 2024, Oracle and/or its affiliates.
2
3This program is free software; you can redistribute it and/or modify it under
4the terms of the GNU General Public License, version 2.0, as published by the
5Free Software Foundation.
6
7This program is designed to work with certain software (including
8but not limited to OpenSSL) that is licensed under separate terms,
9as designated in a particular file or component or in included license
10documentation. The authors of MySQL hereby grant you an additional
11permission to link the program and your derivative works with the
12separately licensed software that they have either included with
13the program or referenced in the documentation.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
18for more details.
19
20You should have received a copy of the GNU General Public License along with
21this program; if not, write to the Free Software Foundation, Inc.,
2251 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24/** @file storage/temptable/include/temptable/memutils.h
25Memory utilities for temptable-allocator. */
26
27#ifndef TEMPTABLE_MEM_H
28#define TEMPTABLE_MEM_H
29
30#include "my_config.h"
31
32#include <fcntl.h> // MAP_FAILED, etc.
33#include <cstddef> // size_t
34#include <cstdlib> // malloc(), free()
35
36// clang-format off
37#ifdef _WIN32
38/*
39https://msdn.microsoft.com/en-us/library/windows/desktop/dd405487(v=vs.85).aspx
40https://msdn.microsoft.com/en-us/library/windows/desktop/dd405494(v=vs.85).aspx
41https://msdn.microsoft.com/en-us/library/windows/desktop/aa366891(v=vs.85).aspx
42 */
43#define _WIN32_WINNT 0x0601
44#include <Windows.h>
45
46#define HAVE_WINNUMA
47#endif /* _WIN32 */
48// clang-format on
49
50#ifdef HAVE_LIBNUMA
51#define TEMPTABLE_USE_LINUX_NUMA
52#include <numa.h> /* numa_*() */
53#endif /* HAVE_LIBNUMA */
54
55#include "my_dbug.h"
56#include "my_io.h" // FN_REFLEN
57#include "my_sys.h" // my_xyz(), create_temp_file(), ...
58#include "sql/mysqld.h" // temptable_use_mmap
60
61namespace temptable {
62
63#if defined(HAVE_WINNUMA)
64extern DWORD win_page_size;
65#endif /* HAVE_WINNUMA */
66
67/** Type of memory allocated. */
68enum class Source {
69 /** Memory is allocated on disk, using mmap()'ed file. */
71 /** Memory is allocated from RAM, using malloc() for example. */
72 RAM,
73};
74
75/** Primary-template (functor) class for memory-utils. */
76template <Source>
77struct Memory {
78 static void *allocate(size_t bytes);
79 static void deallocate(void *ptr, size_t bytes);
80};
81
82/** Template specialization for RAM-based allocation/deallocation. */
83template <>
84struct Memory<Source::RAM> {
85 /** Allocates memory from RAM.
86 *
87 * Linux:
88 * - If support for NUMA is compiled in, and NUMA is available on the
89 * platform, NUMA allocation will be used.
90 * - If support for NUMA is compiled in, but NUMA is NOT available on the
91 * platform, non-NUMA allocation will be used (fallback to e.g. malloc).
92 * Windows:
93 * - If support for NUMA is compiled in, NUMA allocation will be used.
94 *
95 * Throws Result::OUT_OF_MEM if allocation was unsuccessful.
96 *
97 * [in] Size of the memory to be allocated.
98 * @return Pointer to allocated memory. */
99 static void *allocate(size_t bytes) {
100 void *memory = fetch(bytes);
101 if (memory == nullptr) {
102 throw Result::OUT_OF_MEM;
103 }
104 return memory;
105 }
106
107 /** Deallocates memory from RAM.
108 *
109 * [in] Pointer to the memory to be deallocated..
110 * [in] Size of the memory to be deallocated. */
111 static void deallocate(void *ptr, size_t bytes) { drop(ptr, bytes); }
112
113 private:
114 static void *fetch(size_t bytes);
115 static void drop(void *ptr, size_t bytes);
116
117 private:
118#ifdef TEMPTABLE_USE_LINUX_NUMA
119 /** Set to true if Linux's numa_available() reports "available" (!= -1). */
120 static const bool linux_numa_available;
121#endif /* TEMPTABLE_USE_LINUX_NUMA */
122};
123
124/** Template specialization for MMAP-based allocation/deallocation. */
125template <>
127 /** Allocates memory from MMAP-ed file. Throws Result::RECORD_FILE_FULL
128 * if temptable_use_map is not enabled or if allocation was unsuccessful.
129 *
130 * [in] Size of the memory to be allocated.
131 * @return Pointer to allocated memory. */
132 static void *allocate(size_t bytes) {
133 void *memory = fetch(bytes);
134 if (memory == nullptr) {
136 }
137 return memory;
138 }
139
140 /** Deallocates memory from MMAP-ed file.
141 *
142 * [in] Pointer to the memory to be deallocated..
143 * [in] Size of the memory to be deallocated. */
144 static void deallocate(void *ptr, size_t bytes) { drop(ptr, bytes); }
145
146 private:
147 static void *fetch(size_t bytes);
148 static void drop(void *ptr, size_t bytes);
149};
150
151inline void *Memory<Source::RAM>::fetch(size_t bytes) {
152#if defined(TEMPTABLE_USE_LINUX_NUMA)
153 if (linux_numa_available) {
154 return numa_alloc_local(bytes);
155 } else {
156 return malloc(bytes);
157 }
158#elif defined(HAVE_WINNUMA)
159 PROCESSOR_NUMBER processorNumber;
160 USHORT numaNodeId;
161 GetCurrentProcessorNumberEx(&processorNumber);
162 GetNumaProcessorNodeEx(&processorNumber, &numaNodeId);
163 bytes =
164 (bytes + win_page_size - 1) & ~(static_cast<size_t>(win_page_size) - 1);
165 return VirtualAllocExNuma(GetCurrentProcess(), nullptr, bytes,
166 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE,
167 numaNodeId);
168#else
169 return malloc(bytes);
170#endif
171}
172
173inline void Memory<Source::RAM>::drop(void *ptr, size_t bytes) {
174 (void)bytes;
175#if defined(TEMPTABLE_USE_LINUX_NUMA)
176 if (linux_numa_available) {
177 numa_free(ptr, bytes);
178 } else {
179 free(ptr);
180 }
181#elif defined(HAVE_WINNUMA)
182 BOOL ret [[maybe_unused]] = VirtualFree(ptr, 0, MEM_RELEASE);
183 assert(ret != 0);
184#else
185 free(ptr);
186#endif
187}
188
189inline void *Memory<Source::MMAP_FILE>::fetch(size_t bytes) {
190 DBUG_EXECUTE_IF("temptable_fetch_from_disk_return_null", return nullptr;);
191
192#ifdef _WIN32
193 const int mode = _O_RDWR;
194#else
195 const int mode = O_RDWR;
196#endif /* _WIN32 */
197
198 char file_path[FN_REFLEN];
199 File f = create_temp_file(file_path, mysql_tmpdir, "mysql_temptable.", mode,
201 if (f < 0) {
202 return nullptr;
203 }
204
205 /* This will write `bytes` 0xa bytes to the file on disk. */
206 if (my_fallocator(f, bytes, 0xa, MYF(MY_WME)) != 0 ||
208 my_close(f, MYF(MY_WME));
209 return nullptr;
210 }
211
212 void *ptr = my_mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
213
214 // NOTE: Closing the file-descriptor __immediately__ after MMAP-ing it does
215 // not impact the MMAP functionality at all. Both POSIX and Microsoft
216 // implementations keep the reference to the file-descriptor in their internal
217 // structures so we are free to get rid of it.
218 //
219 // What does it mean to us? We don't have to keep the file-descriptor
220 // ourselves in memory and that results with much more simplified
221 // implementation of fetch/drop.
222 //
223 // References:
224 // POSIX (http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html)
225 // The mmap() function adds an extra reference to the file
226 // associated with the file descriptor fildes which is not removed
227 // by a subsequent close() on that file descriptor. This reference
228 // is removed when there are no more mappings to the file.
229 //
230 // From MSDN
231 // (https://docs.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-unmapviewoffile)
232 // Although an application may close the file handle used to create
233 // a file mapping object, the system holds the corresponding file
234 // open until the last view of the file is unmapped.
235 my_close(f, MYF(MY_WME));
236
237 return (ptr == MAP_FAILED) ? nullptr : ptr;
238}
239
240inline void Memory<Source::MMAP_FILE>::drop(void *ptr, size_t bytes) {
241 my_munmap(ptr, bytes);
242}
243
244} /* namespace temptable */
245
246#endif /* TEMPTABLE_MEM_H */
Fido Client Authentication nullptr
Definition: fido_client_plugin.cc:222
int my_fallocator(File fd, my_off_t newlength, int filler, myf MyFlags)
Change size of the specified file.
Definition: my_fallocator.cc:71
my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags)
Seek to a position in a file.
Definition: my_seek.cc:69
File create_temp_file(char *to, const char *dir, const char *pfx, int mode, UnlinkOrKeepFile unlink_or_keep, myf MyFlags)
Definition: mf_tempfile.cc:219
#define my_mmap(a, b, c, d, e, f)
Definition: my_sys.h:841
#define MY_SEEK_SET
Definition: my_sys.h:166
#define MY_WME
Definition: my_sys.h:123
int my_close(File fd, myf MyFlags)
Close a file.
Definition: my_open.cc:99
#define my_munmap(a, b)
Definition: my_sys.h:845
@ UNLINK_FILE
Definition: my_sys.h:774
bool drop(THD *thd, const Table *tp)
Remove SDI for a table.
Definition: sdi.cc:639
#define malloc(A)
Definition: lexyy.cc:914
#define free(A)
Definition: lexyy.cc:915
#define DBUG_EXECUTE_IF(keyword, a1)
Definition: my_dbug.h:171
#define MY_FILEPOS_ERROR
Definition: my_inttypes.h:73
#define MYF(v)
Definition: my_inttypes.h:97
Common #defines and includes for file and socket I/O.
#define FN_REFLEN
Definition: my_io.h:83
int File
Definition: my_io_bits.h:51
Common header for many mysys elements.
#define mysql_tmpdir
Definition: mysqld.h:701
Definition: aligned_atomic.h:44
static mysql_service_status_t fetch(const char *service_name, reference_caching_channel *out_channel) noexcept
Definition: component.cc:77
mode
Definition: file_handle.h:60
Definition: allocator.h:45
Source
Type of memory allocated.
Definition: memutils.h:68
@ MMAP_FILE
Memory is allocated on disk, using mmap()'ed file.
@ RAM
Memory is allocated from RAM, using malloc() for example.
TempTable auxiliary Result enum.
static void deallocate(void *ptr, size_t bytes)
Deallocates memory from MMAP-ed file.
Definition: memutils.h:144
static void * allocate(size_t bytes)
Allocates memory from MMAP-ed file.
Definition: memutils.h:132
static void * allocate(size_t bytes)
Allocates memory from RAM.
Definition: memutils.h:99
static void deallocate(void *ptr, size_t bytes)
Deallocates memory from RAM.
Definition: memutils.h:111
static const bool linux_numa_available
Set to true if Linux's numa_available() reports "available" (!= -1).
Definition: memutils.h:120
Primary-template (functor) class for memory-utils.
Definition: memutils.h:77
static void deallocate(void *ptr, size_t bytes)
static void * allocate(size_t bytes)