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