MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbNuma.cpp
1 /*
2  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <NdbNuma.h>
19 #include <ndb_global.h>
20 
21 static int NDB_TRACE_NUMA = 0;
22 
23 #if defined HAVE_DLFCN_H && defined HAVE_DLOPEN
24 #include <dlfcn.h>
25 
31 struct bitmask;
32 extern "C"
33 {
34  typedef int (* fun0)(void);
35  typedef void (* fun1)(struct bitmask*);
36  typedef void (* fun2)(int);
37  typedef int (* fun3)(int node, unsigned long * bug, int buflen);
38  typedef bitmask * (* fun4)();
39  typedef void (* fun5)(struct bitmask*);
40  typedef bitmask * (* fun6)(struct bitmask*);
41 };
42 
43 class NdbNuma
44 {
45 public:
46  NdbNuma() { handle = 0;}
47  ~NdbNuma() { if (handle) dlclose(handle); }
48 
49  int open();
50  int build_cputonodemap();
51 
52  void * handle;
53  fun0 numa_available;
54 
55  fun0 numa_max_node;
56  fun0 numa_max_possible_node;
57  fun1 numa_set_interleave_mask;
58  fun2 numa_set_strict;
59  fun3 numa_node_to_cpus;
60  fun4 numa_allocate_nodemask;
61  fun5 numa_bitmask_free;
62  fun6 numa_bitmask_setall;
63 
64  struct bitmask * numa_all_nodes;
65  struct bitmask * numa_all_nodes_ptr;
66 };
67 
68 static
69 void*
70 my_dlopen(const char * name)
71 {
72  void * p = dlopen(name, RTLD_LAZY);
73  if (NDB_TRACE_NUMA)
74  {
75  if (p == 0)
76  printf("info: failed to load %s\n", name);
77  else
78  printf("info: loaded %s\n", name);
79  }
80  return p;
81 }
82 
83 static
84 void*
85 my_dlsym(void * handle, const char * name)
86 {
87  void * p = dlsym(handle, name);
88  if (NDB_TRACE_NUMA)
89  {
90  if (p != 0)
91  {
92  printf("info: %s OK\n", name);
93  }
94  else
95  {
96  printf("info: %s NOT FOUND\n", name);
97  }
98  }
99  return p;
100 }
101 
102 int
103 NdbNuma::open()
104 {
105  handle = my_dlopen("libnuma.so");
106  if (handle == 0)
107  {
108  handle = my_dlopen("libnuma.so.1");
109  }
110  if (handle == 0)
111  {
112  return -1;
113  }
114 
115  numa_available = (fun0)my_dlsym(handle, "numa_available");
116  if (numa_available == 0)
117  {
118  goto fail;
119  }
120 
121  if ((* numa_available)() == -1)
122  {
123  if (NDB_TRACE_NUMA)
124  {
125  printf("info: numa_available() returns -1 => no numa support\n");
126  }
127  goto fail;
128  }
129 
130  numa_max_node = (fun0)my_dlsym(handle, "numa_max_node");
131  numa_set_interleave_mask = (fun1)my_dlsym(handle, "numa_set_interleave_mask");
132  numa_set_strict = (fun2)my_dlsym(handle, "numa_set_strict");
133  numa_node_to_cpus = (fun3)my_dlsym(handle, "numa_node_to_cpus");
134  numa_all_nodes = (struct bitmask*)my_dlsym(handle, "numa_all_nodes");
135  numa_all_nodes_ptr = (struct bitmask*)my_dlsym(handle, "numa_all_nodes_ptr");
136  numa_allocate_nodemask = (fun4)my_dlsym(handle, "numa_allocate_nodemask");
137  numa_bitmask_free = (fun5)my_dlsym(handle, "numa_bitmask_free");
138  numa_bitmask_setall = (fun6)my_dlsym(handle, "numa_bitmask_setall");
139 
140 
141  return 0;
142 fail:
143  dlclose(handle);
144  handle = 0;
145  return -1;
146 }
147 
148 static
149 bool
150 bit_is_set(unsigned long * mask, int bit)
151 {
152  int n = bit / (8 * sizeof(unsigned long));
153  int b = bit % (8 * sizeof(unsigned long));
154  return (mask[n] & (1UL << b)) != 0;
155 }
156 
157 int
158 NdbNuma::build_cputonodemap()
159 {
160  int len = 512;
161  unsigned long * buf = (unsigned long*)malloc(len);
162  if (buf == 0)
163  return -1;
164 
165  int m = (* numa_max_node)();
166  for (int i = 0; i <= m; i++)
167  {
168 retry:
169  int r = (* numa_node_to_cpus)(i, buf, len);
170  if (r == -1)
171  {
172  if (errno != ERANGE)
173  goto fail;
174 
175  len = len + 512;
176  if (len > 4096)
177  goto fail;
178 
179  void * p = realloc(buf, len);
180  if (p == 0)
181  goto fail;
182 
183  buf = (unsigned long*)p;
184  goto retry;
185  }
186  printf("node %d cpu(s): ", i);
187  for (int j = 0; j<8*len;j++)
188  if (bit_is_set(buf, j))
189  printf("%d ", j);
190  printf("\n");
191  }
192  free(buf);
193  return 0;
194 fail:
195  free(buf);
196  return -1;
197 }
198 
199 extern "C"
200 int
201 NdbNuma_setInterleaved()
202 {
203  NdbNuma numa;
204  if (numa.open() == -1)
205  return -1;
206 
207  if (numa.numa_set_interleave_mask == 0)
208  return -1;
209 
210  if (numa.numa_all_nodes_ptr != 0)
211  {
215  if (numa.numa_allocate_nodemask != 0 &&
216  numa.numa_bitmask_setall != 0 &&
217  numa.numa_bitmask_free != 0)
218  {
219  struct bitmask * bm = (* numa.numa_allocate_nodemask)();
220  if (bm != 0)
221  {
222  (* numa.numa_bitmask_setall)(bm);
223  (* numa.numa_set_interleave_mask)(bm);
224  (* numa.numa_bitmask_free)(bm);
225  }
226  else
227  {
228  return -1;
229  }
230  }
231  else
232  {
233  return -1;
234  }
235  }
236  else if (numa.numa_all_nodes != 0)
237  {
241  (* numa.numa_set_interleave_mask)(numa.numa_all_nodes);
242  }
243  else
244  {
245  return -1;
246  }
247 
248  return 0;
249 }
250 
251 #else
252 extern "C"
253 int
254 NdbNuma_setInterleaved()
255 {
256  return -1;
257 }
258 
259 extern "C"
260 int
261 NdbNuma_setInterleavedOnCpus(unsigned cpu[], unsigned len)
262 {
263  return -1;
264 }
265 #endif
266 
267 #ifdef TEST_NDBNUMA
268 #include <NdbTap.hpp>
269 
270 TAPTEST(SetInterleaved)
271 {
272  NDB_TRACE_NUMA = 1;
273  NdbNuma_setInterleaved();
274  return 1; // OK
275 }
276 #endif