MySQL 9.3.0
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
os0numa.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2015, 2025, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28/** @file include/os0numa.h
29 NUMA API wrapper over various operating system specific APIs.
30
31 The os_numa*() functions in this file mimic the numa*() Linux API that is
32 documented in numa(3). They take the same arguments, have the same return
33 type and behave in the same way. There are two purposes behind this:
34 1. Have zero learning curve for developers already familiar with the Linux API.
35 2. Linux's numa*() functions are documented in more detail than ours
36 os_numa*(). Should any doubt arise about the behavior, the Linux docs should
37 be referred.
38
39 Created Jul 16, 2015 Vasil Dimov
40 *******************************************************/
41
42#ifndef os0numa_h
43#define os0numa_h
44
45#include "mysql/components/library_mysys/my_system.h" // my_num_vcpus
46#include "univ.i"
47
48#ifdef HAVE_LIBNUMA
49#include <numa.h>
50#endif /* HAVE_LIBNUMA */
51
52#ifdef HAVE_SCHED_GETCPU
53#include <utmpx.h>
54#endif /* HAVE_SCHED_GETCPU */
55
56#ifdef _WIN32
57
58/* https://msdn.microsoft.com/en-us/library/windows/desktop/dd405494(v=vs.85).aspx
59 */
60#define _WIN32_WINNT 0x0601
61#include <WinBase.h>
62
63#define HAVE_WINNUMA
64
65#endif
66
67/** Check if NUMA is available. This function must be called before any
68other os_numa_*() functions and it must return != -1, otherwise the behavior
69of the rest of the functions is undefined.
70@return != -1 if available. */
71inline int os_numa_available() {
72#if defined(HAVE_LIBNUMA)
73 return (numa_available());
74#elif defined(HAVE_WINNUMA)
75 /* See this page for a description of the NUMA Windows API:
76 "NUMA Support"
77 https://msdn.microsoft.com/en-us/library/windows/desktop/aa363804(v=vs.85).aspx
78 */
79 ULONG highest_node;
80
81 if (!GetNumaHighestNodeNumber(&highest_node)) {
82 return (-1);
83 }
84
85 if (highest_node > 0) {
86 return (1);
87 } else {
88 return (-1);
89 }
90#else
91 return (-1);
92#endif /* HAVE_LIBNUMA */
93}
94
95/** Get the number of CPUs in the system, including disabled ones.
96@return number of CPUs */
98#if defined(HAVE_LIBNUMA)
99 return (numa_num_configured_cpus());
100#elif defined(HAVE_WINNUMA)
101 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buf;
102 DWORD buf_bytes = 0;
103
104 if (GetLogicalProcessorInformationEx(RelationGroup, nullptr, &buf_bytes)) {
105 /* GetLogicalProcessorInformationEx() unexpectedly succeeded. */
106 return (1);
107 }
108
109 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
110 /* GetLogicalProcessorInformationEx() failed with unexpected
111 error code. */
112 return (1);
113 }
114
115 /* Now 'buf_bytes' contains the necessary size of buf (in bytes!). */
116
117 buf = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *>(
118 LocalAlloc(LMEM_FIXED, buf_bytes));
119
120 if (buf == nullptr) {
121 return (1);
122 }
123
124 if (!GetLogicalProcessorInformationEx(RelationGroup, buf, &buf_bytes)) {
125 /* GetLogicalProcessorInformationEx() unexpectedly failed. */
126 LocalFree(buf);
127 return (1);
128 }
129
130 int n_cpus = 0;
131 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buf_orig = buf;
132
133 /* Maybe this loop will iterate just once, but this is not mentioned
134 explicitly anywhere in the GetLogicalProcessorInformationEx()
135 documentation (when the first argument is RelationGroup). If we are
136 sure that it will iterate just once, then this code could be
137 simplified. */
138 for (DWORD offset = 0; offset < buf_bytes;) {
139 for (WORD i = 0; i < buf->Group.ActiveGroupCount; i++) {
140 n_cpus += buf->Group.GroupInfo[i].ActiveProcessorCount;
141 }
142
143 offset += buf->Size;
144 buf = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *>(
145 reinterpret_cast<char *>(buf) + buf->Size);
146 }
147
148 LocalFree(buf_orig);
149
150 return (n_cpus);
151#else
152 return my_num_vcpus();
153#endif
154}
155
156/** Get the NUMA node of a given CPU.
157@param[in] cpu CPU whose NUMA node to return, must be obtained
158using os_getcpu().
159@return NUMA node id */
160inline int os_numa_node_of_cpu(int cpu) {
161#if defined(HAVE_LIBNUMA)
162 return (numa_node_of_cpu(cpu));
163#elif defined(HAVE_WINNUMA)
164 PROCESSOR_NUMBER p;
165 USHORT node;
166
167 p.Group = cpu >> 6;
168 p.Number = cpu & 63;
169
170 if (GetNumaProcessorNodeEx(&p, &node)) {
171 return (static_cast<int>(node));
172 } else {
173 return (0);
174 }
175#else
176 ut_error;
177 return (-1);
178#endif
179}
180
181/** Allocate a memory on a given NUMA node.
182@param[in] size number of bytes to allocate
183@param[in] node NUMA node on which to allocate the memory
184@return pointer to allocated memory or nullptr if allocation failed */
185inline void *os_numa_alloc_onnode(size_t size, int node) {
186#if defined(HAVE_LIBNUMA)
187 return (numa_alloc_onnode(size, node));
188#elif defined(HAVE_WINNUMA)
189 return (VirtualAllocExNuma(GetCurrentProcess(), nullptr, size,
190 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, node));
191#else
192 ut_error;
193 return (nullptr);
194#endif
195}
196
197/** Free a memory allocated by os_numa_alloc_onnode().
198@param[in] ptr pointer to memory to free
199@param[in] size size of the memory */
200inline void os_numa_free(void *ptr, size_t size [[maybe_unused]]) {
201#if defined(HAVE_LIBNUMA)
202 numa_free(ptr, size);
203#elif defined(HAVE_WINNUMA)
204 VirtualFreeEx(GetCurrentProcess(), ptr, 0, MEM_DECOMMIT | MEM_RELEASE);
205#else
206 ut_error;
207#endif
208}
209
210#if defined(HAVE_SCHED_GETCPU) || defined(HAVE_WINNUMA)
211
212#define HAVE_OS_GETCPU
213
214/** Get the number of the CPU that executes the current thread now.
215@return CPU number */
216inline int os_getcpu() {
217#if defined(HAVE_SCHED_GETCPU)
218 return (sched_getcpu());
219#elif defined(HAVE_WINNUMA)
220 PROCESSOR_NUMBER p;
221
222 GetCurrentProcessorNumberEx(&p);
223
224 return (static_cast<int>(p.Group << 6 | p.Number));
225#endif
226}
227#endif /* HAVE_SCHED_GETCPU || HAVE_WINNUMA */
228
229#endif /* os0numa_h */
static char buf[MAX_BUF]
Definition: conf_to_src.cc:74
const char * p
Definition: ctype-mb.cc:1227
uint32_t my_num_vcpus() noexcept
Determine the total number of logical CPUs available.
Definition: my_system.cc:80
Definition: buf0block_hint.cc:30
size_t size(const char *const c)
Definition: base64.h:46
int os_numa_num_configured_cpus()
Get the number of CPUs in the system, including disabled ones.
Definition: os0numa.h:97
void os_numa_free(void *ptr, size_t size)
Free a memory allocated by os_numa_alloc_onnode().
Definition: os0numa.h:200
int os_numa_available()
Check if NUMA is available.
Definition: os0numa.h:71
void * os_numa_alloc_onnode(size_t size, int node)
Allocate a memory on a given NUMA node.
Definition: os0numa.h:185
int os_numa_node_of_cpu(int cpu)
Get the NUMA node of a given CPU.
Definition: os0numa.h:160
Version control for database, common definitions, and include files.
#define ut_error
Abort execution.
Definition: ut0dbg.h:101