This source file includes following definitions.
- hwloc_win_get_function_ptrs
- hwloc_bitmap_from_ULONG_PTR
- hwloc_bitmap_from_ith_ULONG_PTR
- hwloc_bitmap_set_ith_ULONG_PTR
- hwloc_bitmap_to_ULONG_PTR
- hwloc_bitmap_to_ith_ULONG_PTR
- hwloc_bitmap_to_single_ULONG_PTR
- hwloc_win_get_thisthread_last_cpu_location
- hwloc_win_set_thread_cpubind
- hwloc_win_set_thisthread_cpubind
- hwloc_win_set_thisthread_membind
- hwloc_win_get_thread_cpubind
- hwloc_win_get_thisthread_cpubind
- hwloc_win_get_thisthread_membind
- hwloc_win_set_proc_cpubind
- hwloc_win_set_thisproc_cpubind
- hwloc_win_set_proc_membind
- hwloc_win_set_thisproc_membind
- hwloc_win_get_proc_cpubind
- hwloc_win_get_proc_membind
- hwloc_win_get_thisproc_cpubind
- hwloc_win_get_thisproc_membind
- hwloc_win_alloc
- hwloc_win_alloc_membind
- hwloc_win_free_membind
- hwloc_win_get_area_memlocation
- hwloc_look_windows
- hwloc_set_windows_hooks
- hwloc_windows_component_init
- hwloc_windows_component_finalize
- hwloc_windows_component_instantiate
- hwloc_fallback_nbprocessors
1
2
3
4
5
6
7
8
9
10 #define _WIN32_WINNT 0x0601
11
12 #include <private/autogen/config.h>
13 #include <hwloc.h>
14 #include <private/private.h>
15 #include <private/debug.h>
16
17 #include <windows.h>
18
19 #ifndef HAVE_KAFFINITY
20 typedef ULONG_PTR KAFFINITY, *PKAFFINITY;
21 #endif
22
23 #ifndef HAVE_PROCESSOR_CACHE_TYPE
24 typedef enum _PROCESSOR_CACHE_TYPE {
25 CacheUnified,
26 CacheInstruction,
27 CacheData,
28 CacheTrace
29 } PROCESSOR_CACHE_TYPE;
30 #endif
31
32 #ifndef CACHE_FULLY_ASSOCIATIVE
33 #define CACHE_FULLY_ASSOCIATIVE 0xFF
34 #endif
35
36 #ifndef MAXIMUM_PROC_PER_GROUP
37 #define MAXIMUM_PROC_PER_GROUP 64
38 #endif
39
40 #ifndef HAVE_CACHE_DESCRIPTOR
41 typedef struct _CACHE_DESCRIPTOR {
42 BYTE Level;
43 BYTE Associativity;
44 WORD LineSize;
45 DWORD Size;
46 PROCESSOR_CACHE_TYPE Type;
47 } CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR;
48 #endif
49
50 #ifndef HAVE_LOGICAL_PROCESSOR_RELATIONSHIP
51 typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
52 RelationProcessorCore,
53 RelationNumaNode,
54 RelationCache,
55 RelationProcessorPackage,
56 RelationGroup,
57 RelationAll = 0xffff
58 } LOGICAL_PROCESSOR_RELATIONSHIP;
59 #else
60 # ifndef HAVE_RELATIONPROCESSORPACKAGE
61 # define RelationProcessorPackage 3
62 # define RelationGroup 4
63 # define RelationAll 0xffff
64 # endif
65 #endif
66
67 #ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION
68 typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
69 ULONG_PTR ProcessorMask;
70 LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
71 _ANONYMOUS_UNION
72 union {
73 struct {
74 BYTE flags;
75 } ProcessorCore;
76 struct {
77 DWORD NodeNumber;
78 } NumaNode;
79 CACHE_DESCRIPTOR Cache;
80 ULONGLONG Reserved[2];
81 } DUMMYUNIONNAME;
82 } SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
83 #endif
84
85
86
87 #ifndef HAVE_GROUP_AFFINITY
88 typedef struct _GROUP_AFFINITY {
89 KAFFINITY Mask;
90 WORD Group;
91 WORD Reserved[3];
92 } GROUP_AFFINITY, *PGROUP_AFFINITY;
93 #endif
94
95 #ifndef HAVE_PROCESSOR_RELATIONSHIP
96 typedef struct _PROCESSOR_RELATIONSHIP {
97 BYTE Flags;
98 BYTE Reserved[21];
99 WORD GroupCount;
100 GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY];
101 } PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP;
102 #endif
103
104 #ifndef HAVE_NUMA_NODE_RELATIONSHIP
105 typedef struct _NUMA_NODE_RELATIONSHIP {
106 DWORD NodeNumber;
107 BYTE Reserved[20];
108 GROUP_AFFINITY GroupMask;
109 } NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP;
110 #endif
111
112 #ifndef HAVE_CACHE_RELATIONSHIP
113 typedef struct _CACHE_RELATIONSHIP {
114 BYTE Level;
115 BYTE Associativity;
116 WORD LineSize;
117 DWORD CacheSize;
118 PROCESSOR_CACHE_TYPE Type;
119 BYTE Reserved[20];
120 GROUP_AFFINITY GroupMask;
121 } CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP;
122 #endif
123
124 #ifndef HAVE_PROCESSOR_GROUP_INFO
125 typedef struct _PROCESSOR_GROUP_INFO {
126 BYTE MaximumProcessorCount;
127 BYTE ActiveProcessorCount;
128 BYTE Reserved[38];
129 KAFFINITY ActiveProcessorMask;
130 } PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO;
131 #endif
132
133 #ifndef HAVE_GROUP_RELATIONSHIP
134 typedef struct _GROUP_RELATIONSHIP {
135 WORD MaximumGroupCount;
136 WORD ActiveGroupCount;
137 ULONGLONG Reserved[2];
138 PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY];
139 } GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP;
140 #endif
141
142 #ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
143 typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
144 LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
145 DWORD Size;
146 _ANONYMOUS_UNION
147 union {
148 PROCESSOR_RELATIONSHIP Processor;
149 NUMA_NODE_RELATIONSHIP NumaNode;
150 CACHE_RELATIONSHIP Cache;
151 GROUP_RELATIONSHIP Group;
152
153 } DUMMYUNIONNAME;
154 } SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
155 #endif
156
157 #ifndef HAVE_PSAPI_WORKING_SET_EX_BLOCK
158 typedef union _PSAPI_WORKING_SET_EX_BLOCK {
159 ULONG_PTR Flags;
160 struct {
161 unsigned Valid :1;
162 unsigned ShareCount :3;
163 unsigned Win32Protection :11;
164 unsigned Shared :1;
165 unsigned Node :6;
166 unsigned Locked :1;
167 unsigned LargePage :1;
168 };
169 } PSAPI_WORKING_SET_EX_BLOCK;
170 #endif
171
172 #ifndef HAVE_PSAPI_WORKING_SET_EX_INFORMATION
173 typedef struct _PSAPI_WORKING_SET_EX_INFORMATION {
174 PVOID VirtualAddress;
175 PSAPI_WORKING_SET_EX_BLOCK VirtualAttributes;
176 } PSAPI_WORKING_SET_EX_INFORMATION;
177 #endif
178
179 #ifndef HAVE_PROCESSOR_NUMBER
180 typedef struct _PROCESSOR_NUMBER {
181 WORD Group;
182 BYTE Number;
183 BYTE Reserved;
184 } PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;
185 #endif
186
187
188
189 typedef WORD (WINAPI *PFN_GETACTIVEPROCESSORGROUPCOUNT)(void);
190 static PFN_GETACTIVEPROCESSORGROUPCOUNT GetActiveProcessorGroupCountProc;
191
192 static unsigned long nr_processor_groups = 1;
193 static unsigned long max_numanode_index = 0;
194
195 typedef WORD (WINAPI *PFN_GETACTIVEPROCESSORCOUNT)(WORD);
196 static PFN_GETACTIVEPROCESSORCOUNT GetActiveProcessorCountProc;
197
198 typedef DWORD (WINAPI *PFN_GETCURRENTPROCESSORNUMBER)(void);
199 static PFN_GETCURRENTPROCESSORNUMBER GetCurrentProcessorNumberProc;
200
201 typedef VOID (WINAPI *PFN_GETCURRENTPROCESSORNUMBEREX)(PPROCESSOR_NUMBER);
202 static PFN_GETCURRENTPROCESSORNUMBEREX GetCurrentProcessorNumberExProc;
203
204 typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATION)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength);
205 static PFN_GETLOGICALPROCESSORINFORMATION GetLogicalProcessorInformationProc;
206
207 typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATIONEX)(LOGICAL_PROCESSOR_RELATIONSHIP relationship, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, PDWORD ReturnLength);
208 static PFN_GETLOGICALPROCESSORINFORMATIONEX GetLogicalProcessorInformationExProc;
209
210 typedef BOOL (WINAPI *PFN_SETTHREADGROUPAFFINITY)(HANDLE hThread, const GROUP_AFFINITY *GroupAffinity, PGROUP_AFFINITY PreviousGroupAffinity);
211 static PFN_SETTHREADGROUPAFFINITY SetThreadGroupAffinityProc;
212
213 typedef BOOL (WINAPI *PFN_GETTHREADGROUPAFFINITY)(HANDLE hThread, PGROUP_AFFINITY GroupAffinity);
214 static PFN_GETTHREADGROUPAFFINITY GetThreadGroupAffinityProc;
215
216 typedef BOOL (WINAPI *PFN_GETNUMAAVAILABLEMEMORYNODE)(UCHAR Node, PULONGLONG AvailableBytes);
217 static PFN_GETNUMAAVAILABLEMEMORYNODE GetNumaAvailableMemoryNodeProc;
218
219 typedef BOOL (WINAPI *PFN_GETNUMAAVAILABLEMEMORYNODEEX)(USHORT Node, PULONGLONG AvailableBytes);
220 static PFN_GETNUMAAVAILABLEMEMORYNODEEX GetNumaAvailableMemoryNodeExProc;
221
222 typedef LPVOID (WINAPI *PFN_VIRTUALALLOCEXNUMA)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, DWORD nndPreferred);
223 static PFN_VIRTUALALLOCEXNUMA VirtualAllocExNumaProc;
224
225 typedef BOOL (WINAPI *PFN_VIRTUALFREEEX)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
226 static PFN_VIRTUALFREEEX VirtualFreeExProc;
227
228 typedef BOOL (WINAPI *PFN_QUERYWORKINGSETEX)(HANDLE hProcess, PVOID pv, DWORD cb);
229 static PFN_QUERYWORKINGSETEX QueryWorkingSetExProc;
230
231 static void hwloc_win_get_function_ptrs(void)
232 {
233 HMODULE kernel32;
234
235 kernel32 = LoadLibrary("kernel32.dll");
236 if (kernel32) {
237 GetActiveProcessorGroupCountProc =
238 (PFN_GETACTIVEPROCESSORGROUPCOUNT) GetProcAddress(kernel32, "GetActiveProcessorGroupCount");
239 GetActiveProcessorCountProc =
240 (PFN_GETACTIVEPROCESSORCOUNT) GetProcAddress(kernel32, "GetActiveProcessorCount");
241 GetLogicalProcessorInformationProc =
242 (PFN_GETLOGICALPROCESSORINFORMATION) GetProcAddress(kernel32, "GetLogicalProcessorInformation");
243 GetCurrentProcessorNumberProc =
244 (PFN_GETCURRENTPROCESSORNUMBER) GetProcAddress(kernel32, "GetCurrentProcessorNumber");
245 GetCurrentProcessorNumberExProc =
246 (PFN_GETCURRENTPROCESSORNUMBEREX) GetProcAddress(kernel32, "GetCurrentProcessorNumberEx");
247 SetThreadGroupAffinityProc =
248 (PFN_SETTHREADGROUPAFFINITY) GetProcAddress(kernel32, "SetThreadGroupAffinity");
249 GetThreadGroupAffinityProc =
250 (PFN_GETTHREADGROUPAFFINITY) GetProcAddress(kernel32, "GetThreadGroupAffinity");
251 GetNumaAvailableMemoryNodeProc =
252 (PFN_GETNUMAAVAILABLEMEMORYNODE) GetProcAddress(kernel32, "GetNumaAvailableMemoryNode");
253 GetNumaAvailableMemoryNodeExProc =
254 (PFN_GETNUMAAVAILABLEMEMORYNODEEX) GetProcAddress(kernel32, "GetNumaAvailableMemoryNodeEx");
255 GetLogicalProcessorInformationExProc =
256 (PFN_GETLOGICALPROCESSORINFORMATIONEX)GetProcAddress(kernel32, "GetLogicalProcessorInformationEx");
257 QueryWorkingSetExProc =
258 (PFN_QUERYWORKINGSETEX) GetProcAddress(kernel32, "K32QueryWorkingSetEx");
259 VirtualAllocExNumaProc =
260 (PFN_VIRTUALALLOCEXNUMA) GetProcAddress(kernel32, "VirtualAllocExNuma");
261 VirtualFreeExProc =
262 (PFN_VIRTUALFREEEX) GetProcAddress(kernel32, "VirtualFreeEx");
263 }
264
265 if (GetActiveProcessorGroupCountProc)
266 nr_processor_groups = GetActiveProcessorGroupCountProc();
267
268 if (!QueryWorkingSetExProc) {
269 HMODULE psapi = LoadLibrary("psapi.dll");
270 if (psapi)
271 QueryWorkingSetExProc = (PFN_QUERYWORKINGSETEX) GetProcAddress(psapi, "QueryWorkingSetEx");
272 }
273 }
274
275
276
277
278
279
280 static void hwloc_bitmap_from_ULONG_PTR(hwloc_bitmap_t set, ULONG_PTR mask)
281 {
282 #if SIZEOF_VOID_P == 8
283 hwloc_bitmap_from_ulong(set, mask & 0xffffffff);
284 hwloc_bitmap_set_ith_ulong(set, 1, mask >> 32);
285 #else
286 hwloc_bitmap_from_ulong(set, mask);
287 #endif
288 }
289
290 static void hwloc_bitmap_from_ith_ULONG_PTR(hwloc_bitmap_t set, unsigned i, ULONG_PTR mask)
291 {
292 #if SIZEOF_VOID_P == 8
293 hwloc_bitmap_from_ith_ulong(set, 2*i, mask & 0xffffffff);
294 hwloc_bitmap_set_ith_ulong(set, 2*i+1, mask >> 32);
295 #else
296 hwloc_bitmap_from_ith_ulong(set, i, mask);
297 #endif
298 }
299
300 static void hwloc_bitmap_set_ith_ULONG_PTR(hwloc_bitmap_t set, unsigned i, ULONG_PTR mask)
301 {
302 #if SIZEOF_VOID_P == 8
303 hwloc_bitmap_set_ith_ulong(set, 2*i, mask & 0xffffffff);
304 hwloc_bitmap_set_ith_ulong(set, 2*i+1, mask >> 32);
305 #else
306 hwloc_bitmap_set_ith_ulong(set, i, mask);
307 #endif
308 }
309
310 static ULONG_PTR hwloc_bitmap_to_ULONG_PTR(hwloc_const_bitmap_t set)
311 {
312 #if SIZEOF_VOID_P == 8
313 ULONG_PTR up = hwloc_bitmap_to_ith_ulong(set, 1);
314 up <<= 32;
315 up |= hwloc_bitmap_to_ulong(set);
316 return up;
317 #else
318 return hwloc_bitmap_to_ulong(set);
319 #endif
320 }
321
322 static ULONG_PTR hwloc_bitmap_to_ith_ULONG_PTR(hwloc_const_bitmap_t set, unsigned i)
323 {
324 #if SIZEOF_VOID_P == 8
325 ULONG_PTR up = hwloc_bitmap_to_ith_ulong(set, 2*i+1);
326 up <<= 32;
327 up |= hwloc_bitmap_to_ith_ulong(set, 2*i);
328 return up;
329 #else
330 return hwloc_bitmap_to_ith_ulong(set, i);
331 #endif
332 }
333
334
335
336
337 static int hwloc_bitmap_to_single_ULONG_PTR(hwloc_const_bitmap_t set, unsigned *index, ULONG_PTR *mask)
338 {
339 unsigned first_ulp, last_ulp;
340 if (hwloc_bitmap_weight(set) == -1)
341 return -1;
342 first_ulp = hwloc_bitmap_first(set) / (sizeof(ULONG_PTR)*8);
343 last_ulp = hwloc_bitmap_last(set) / (sizeof(ULONG_PTR)*8);
344 if (first_ulp != last_ulp)
345 return -1;
346 *mask = hwloc_bitmap_to_ith_ULONG_PTR(set, first_ulp);
347 *index = first_ulp;
348 return 0;
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367 static int
368 hwloc_win_get_thisthread_last_cpu_location(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_cpuset_t set, int flags __hwloc_attribute_unused)
369 {
370 assert(GetCurrentProcessorNumberExProc || (GetCurrentProcessorNumberProc && nr_processor_groups == 1));
371
372 if (nr_processor_groups > 1 || !GetCurrentProcessorNumberProc) {
373 PROCESSOR_NUMBER num;
374 GetCurrentProcessorNumberExProc(&num);
375 hwloc_bitmap_from_ith_ULONG_PTR(set, num.Group, ((ULONG_PTR)1) << num.Number);
376 return 0;
377 }
378
379 hwloc_bitmap_from_ith_ULONG_PTR(set, 0, ((ULONG_PTR)1) << GetCurrentProcessorNumberProc());
380 return 0;
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 static int
397 hwloc_win_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t thread, hwloc_const_bitmap_t hwloc_set, int flags)
398 {
399 DWORD_PTR mask;
400 unsigned group;
401
402 if (flags & HWLOC_CPUBIND_NOMEMBIND) {
403 errno = ENOSYS;
404 return -1;
405 }
406
407 if (hwloc_bitmap_to_single_ULONG_PTR(hwloc_set, &group, &mask) < 0) {
408 errno = ENOSYS;
409 return -1;
410 }
411
412 assert(nr_processor_groups == 1 || SetThreadGroupAffinityProc);
413
414 if (nr_processor_groups > 1) {
415 GROUP_AFFINITY aff;
416 memset(&aff, 0, sizeof(aff));
417 aff.Group = group;
418 aff.Mask = mask;
419 if (!SetThreadGroupAffinityProc(thread, &aff, NULL))
420 return -1;
421
422 } else {
423
424
425 if (!SetThreadAffinityMask(thread, mask))
426 return -1;
427 }
428 return 0;
429 }
430
431 static int
432 hwloc_win_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
433 {
434 return hwloc_win_set_thread_cpubind(topology, GetCurrentThread(), hwloc_set, flags);
435 }
436
437 static int
438 hwloc_win_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
439 {
440 int ret;
441 hwloc_const_cpuset_t cpuset;
442 hwloc_cpuset_t _cpuset = NULL;
443
444 if ((policy != HWLOC_MEMBIND_DEFAULT && policy != HWLOC_MEMBIND_BIND)
445 || flags & HWLOC_MEMBIND_NOCPUBIND) {
446 errno = ENOSYS;
447 return -1;
448 }
449
450 if (policy == HWLOC_MEMBIND_DEFAULT) {
451 cpuset = hwloc_topology_get_complete_cpuset(topology);
452 } else {
453 cpuset = _cpuset = hwloc_bitmap_alloc();
454 hwloc_cpuset_from_nodeset(topology, _cpuset, nodeset);
455 }
456
457 ret = hwloc_win_set_thisthread_cpubind(topology, cpuset,
458 (flags & HWLOC_MEMBIND_STRICT) ? HWLOC_CPUBIND_STRICT : 0);
459 hwloc_bitmap_free(_cpuset);
460 return ret;
461 }
462
463
464
465
466
467
468 static int
469 hwloc_win_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t thread, hwloc_cpuset_t set, int flags __hwloc_attribute_unused)
470 {
471 GROUP_AFFINITY aff;
472
473 assert(GetThreadGroupAffinityProc);
474
475 if (!GetThreadGroupAffinityProc(thread, &aff))
476 return -1;
477 hwloc_bitmap_from_ith_ULONG_PTR(set, aff.Group, aff.Mask);
478 return 0;
479 }
480
481 static int
482 hwloc_win_get_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_cpuset_t set, int flags __hwloc_attribute_unused)
483 {
484 return hwloc_win_get_thread_cpubind(topology, GetCurrentThread(), set, flags);
485 }
486
487 static int
488 hwloc_win_get_thisthread_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
489 {
490 int ret;
491 hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
492 ret = hwloc_win_get_thread_cpubind(topology, GetCurrentThread(), cpuset, flags);
493 if (!ret) {
494 *policy = HWLOC_MEMBIND_BIND;
495 hwloc_cpuset_to_nodeset(topology, cpuset, nodeset);
496 }
497 hwloc_bitmap_free(cpuset);
498 return ret;
499 }
500
501
502
503
504
505
506 static int
507 hwloc_win_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t proc, hwloc_const_bitmap_t hwloc_set, int flags)
508 {
509 DWORD_PTR mask;
510
511 assert(nr_processor_groups == 1);
512
513 if (flags & HWLOC_CPUBIND_NOMEMBIND) {
514 errno = ENOSYS;
515 return -1;
516 }
517
518
519
520
521
522
523
524
525
526
527
528
529 mask = hwloc_bitmap_to_ULONG_PTR(hwloc_set);
530 if (!SetProcessAffinityMask(proc, mask))
531 return -1;
532 return 0;
533 }
534
535 static int
536 hwloc_win_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
537 {
538 return hwloc_win_set_proc_cpubind(topology, GetCurrentProcess(), hwloc_set, flags);
539 }
540
541 static int
542 hwloc_win_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
543 {
544 int ret;
545 hwloc_const_cpuset_t cpuset;
546 hwloc_cpuset_t _cpuset = NULL;
547
548 if ((policy != HWLOC_MEMBIND_DEFAULT && policy != HWLOC_MEMBIND_BIND)
549 || flags & HWLOC_MEMBIND_NOCPUBIND) {
550 errno = ENOSYS;
551 return -1;
552 }
553
554 if (policy == HWLOC_MEMBIND_DEFAULT) {
555 cpuset = hwloc_topology_get_complete_cpuset(topology);
556 } else {
557 cpuset = _cpuset = hwloc_bitmap_alloc();
558 hwloc_cpuset_from_nodeset(topology, _cpuset, nodeset);
559 }
560
561 ret = hwloc_win_set_proc_cpubind(topology, pid, cpuset,
562 (flags & HWLOC_MEMBIND_STRICT) ? HWLOC_CPUBIND_STRICT : 0);
563 hwloc_bitmap_free(_cpuset);
564 return ret;
565 }
566
567 static int
568 hwloc_win_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
569 {
570 return hwloc_win_set_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags);
571 }
572
573
574
575
576
577
578 static int
579 hwloc_win_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t proc, hwloc_bitmap_t hwloc_set, int flags)
580 {
581 DWORD_PTR proc_mask, sys_mask;
582
583 assert(nr_processor_groups == 1);
584
585 if (flags & HWLOC_CPUBIND_NOMEMBIND) {
586 errno = ENOSYS;
587 return -1;
588 }
589
590
591
592
593
594
595
596
597
598
599
600 if (!GetProcessAffinityMask(proc, &proc_mask, &sys_mask))
601 return -1;
602 hwloc_bitmap_from_ULONG_PTR(hwloc_set, proc_mask);
603 return 0;
604 }
605
606 static int
607 hwloc_win_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
608 {
609 int ret;
610 hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
611 ret = hwloc_win_get_proc_cpubind(topology, pid, cpuset,
612 (flags & HWLOC_MEMBIND_STRICT) ? HWLOC_CPUBIND_STRICT : 0);
613 if (!ret) {
614 *policy = HWLOC_MEMBIND_BIND;
615 hwloc_cpuset_to_nodeset(topology, cpuset, nodeset);
616 }
617 hwloc_bitmap_free(cpuset);
618 return ret;
619 }
620
621 static int
622 hwloc_win_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
623 {
624 return hwloc_win_get_proc_cpubind(topology, GetCurrentProcess(), hwloc_cpuset, flags);
625 }
626
627 static int
628 hwloc_win_get_thisproc_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
629 {
630 return hwloc_win_get_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags);
631 }
632
633
634
635
636
637
638 static void *
639 hwloc_win_alloc(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) {
640 return VirtualAlloc(NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
641 }
642
643 static void *
644 hwloc_win_alloc_membind(hwloc_topology_t topology __hwloc_attribute_unused, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) {
645 int node;
646
647 switch (policy) {
648 case HWLOC_MEMBIND_DEFAULT:
649 case HWLOC_MEMBIND_BIND:
650 break;
651 default:
652 errno = ENOSYS;
653 return hwloc_alloc_or_fail(topology, len, flags);
654 }
655
656 if (flags & HWLOC_MEMBIND_STRICT) {
657 errno = ENOSYS;
658 return NULL;
659 }
660
661 if (policy == HWLOC_MEMBIND_DEFAULT
662 || hwloc_bitmap_isequal(nodeset, hwloc_topology_get_complete_nodeset(topology)))
663 return hwloc_win_alloc(topology, len);
664
665 if (hwloc_bitmap_weight(nodeset) != 1) {
666
667 errno = EXDEV;
668 return hwloc_alloc_or_fail(topology, len, flags);
669 }
670
671 node = hwloc_bitmap_first(nodeset);
672 return VirtualAllocExNumaProc(GetCurrentProcess(), NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE, node);
673 }
674
675 static int
676 hwloc_win_free_membind(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused) {
677 if (!addr)
678 return 0;
679 if (!VirtualFreeExProc(GetCurrentProcess(), addr, 0, MEM_RELEASE))
680 return -1;
681 return 0;
682 }
683
684
685
686
687
688
689 static int
690 hwloc_win_get_area_memlocation(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr, size_t len, hwloc_nodeset_t nodeset, int flags __hwloc_attribute_unused)
691 {
692 SYSTEM_INFO SystemInfo;
693 DWORD page_size;
694 uintptr_t start;
695 unsigned nb;
696 PSAPI_WORKING_SET_EX_INFORMATION *pv;
697 unsigned i;
698
699 GetSystemInfo(&SystemInfo);
700 page_size = SystemInfo.dwPageSize;
701
702 start = (((uintptr_t) addr) / page_size) * page_size;
703 nb = (unsigned)((((uintptr_t) addr + len - start) + page_size - 1) / page_size);
704
705 if (!nb)
706 nb = 1;
707
708 pv = calloc(nb, sizeof(*pv));
709 if (!pv)
710 return -1;
711
712 for (i = 0; i < nb; i++)
713 pv[i].VirtualAddress = (void*) (start + i * page_size);
714 if (!QueryWorkingSetExProc(GetCurrentProcess(), pv, nb * sizeof(*pv))) {
715 free(pv);
716 return -1;
717 }
718
719 for (i = 0; i < nb; i++) {
720 if (pv[i].VirtualAttributes.Valid)
721 hwloc_bitmap_set(nodeset, pv[i].VirtualAttributes.Node);
722 }
723
724 free(pv);
725 return 0;
726 }
727
728
729
730
731
732
733 static int
734 hwloc_look_windows(struct hwloc_backend *backend)
735 {
736 struct hwloc_topology *topology = backend->topology;
737 hwloc_bitmap_t groups_pu_set = NULL;
738 SYSTEM_INFO SystemInfo;
739 DWORD length;
740 int gotnuma = 0;
741 int gotnumamemory = 0;
742
743 if (topology->levels[0][0]->cpuset)
744
745 return -1;
746
747 hwloc_alloc_root_sets(topology->levels[0][0]);
748
749 GetSystemInfo(&SystemInfo);
750
751 if (!GetLogicalProcessorInformationExProc && GetLogicalProcessorInformationProc) {
752 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION procInfo, tmpprocInfo;
753 unsigned id;
754 unsigned i;
755 struct hwloc_obj *obj;
756 hwloc_obj_type_t type;
757
758 length = 0;
759 procInfo = NULL;
760
761 while (1) {
762 if (GetLogicalProcessorInformationProc(procInfo, &length))
763 break;
764 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
765 return -1;
766 tmpprocInfo = realloc(procInfo, length);
767 if (!tmpprocInfo) {
768 free(procInfo);
769 goto out;
770 }
771 procInfo = tmpprocInfo;
772 }
773
774 assert(!length || procInfo);
775
776 for (i = 0; i < length / sizeof(*procInfo); i++) {
777
778
779 if (procInfo->Relationship == RelationCache
780 && procInfo->Cache.Type != CacheUnified
781 && procInfo->Cache.Type != CacheData
782 && procInfo->Cache.Type != CacheInstruction)
783 continue;
784
785 id = HWLOC_UNKNOWN_INDEX;
786 switch (procInfo[i].Relationship) {
787 case RelationNumaNode:
788 type = HWLOC_OBJ_NUMANODE;
789 id = procInfo[i].NumaNode.NodeNumber;
790 gotnuma++;
791 if (id > max_numanode_index)
792 max_numanode_index = id;
793 break;
794 case RelationProcessorPackage:
795 type = HWLOC_OBJ_PACKAGE;
796 break;
797 case RelationCache:
798 type = (procInfo[i].Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo[i].Cache.Level - 1;
799 break;
800 case RelationProcessorCore:
801 type = HWLOC_OBJ_CORE;
802 break;
803 case RelationGroup:
804 default:
805 type = HWLOC_OBJ_GROUP;
806 break;
807 }
808
809 if (!hwloc_filter_check_keep_object_type(topology, type))
810 continue;
811
812 obj = hwloc_alloc_setup_object(topology, type, id);
813 obj->cpuset = hwloc_bitmap_alloc();
814 hwloc_debug("%s#%u mask %lx\n", hwloc_obj_type_string(type), id, procInfo[i].ProcessorMask);
815
816 hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, 0, procInfo[i].ProcessorMask);
817 hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset);
818
819 switch (type) {
820 case HWLOC_OBJ_NUMANODE:
821 {
822 ULONGLONG avail;
823 obj->nodeset = hwloc_bitmap_alloc();
824 hwloc_bitmap_set(obj->nodeset, id);
825 if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail))
826 || (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail))) {
827 obj->attr->numanode.local_memory = avail;
828 gotnumamemory++;
829 }
830 obj->attr->numanode.page_types_len = 2;
831 obj->attr->numanode.page_types = malloc(2 * sizeof(*obj->attr->numanode.page_types));
832 memset(obj->attr->numanode.page_types, 0, 2 * sizeof(*obj->attr->numanode.page_types));
833 obj->attr->numanode.page_types_len = 1;
834 obj->attr->numanode.page_types[0].size = SystemInfo.dwPageSize;
835 #if HAVE_DECL__SC_LARGE_PAGESIZE
836 obj->attr->numanode.page_types_len++;
837 obj->attr->numanode.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
838 #endif
839 break;
840 }
841 case HWLOC_OBJ_L1CACHE:
842 case HWLOC_OBJ_L2CACHE:
843 case HWLOC_OBJ_L3CACHE:
844 case HWLOC_OBJ_L4CACHE:
845 case HWLOC_OBJ_L5CACHE:
846 case HWLOC_OBJ_L1ICACHE:
847 case HWLOC_OBJ_L2ICACHE:
848 case HWLOC_OBJ_L3ICACHE:
849 obj->attr->cache.size = procInfo[i].Cache.Size;
850 obj->attr->cache.associativity = procInfo[i].Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo[i].Cache.Associativity ;
851 obj->attr->cache.linesize = procInfo[i].Cache.LineSize;
852 obj->attr->cache.depth = procInfo[i].Cache.Level;
853 switch (procInfo->Cache.Type) {
854 case CacheUnified:
855 obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
856 break;
857 case CacheData:
858 obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
859 break;
860 case CacheInstruction:
861 obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
862 break;
863 default:
864 hwloc_free_unlinked_object(obj);
865 continue;
866 }
867 break;
868 case HWLOC_OBJ_GROUP:
869 obj->attr->group.kind = procInfo[i].Relationship == RelationGroup ? HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP : HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN;
870 break;
871 default:
872 break;
873 }
874 hwloc_insert_object_by_cpuset(topology, obj);
875 }
876
877 free(procInfo);
878 }
879
880 if (GetLogicalProcessorInformationExProc) {
881 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX procInfoTotal, tmpprocInfoTotal, procInfo;
882 unsigned id;
883 struct hwloc_obj *obj;
884 hwloc_obj_type_t type;
885
886 length = 0;
887 procInfoTotal = NULL;
888
889 while (1) {
890 if (GetLogicalProcessorInformationExProc(RelationAll, procInfoTotal, &length))
891 break;
892 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
893 return -1;
894 tmpprocInfoTotal = realloc(procInfoTotal, length);
895 if (!tmpprocInfoTotal) {
896 free(procInfoTotal);
897 goto out;
898 }
899 procInfoTotal = tmpprocInfoTotal;
900 }
901
902 for (procInfo = procInfoTotal;
903 (void*) procInfo < (void*) ((uintptr_t) procInfoTotal + length);
904 procInfo = (void*) ((uintptr_t) procInfo + procInfo->Size)) {
905 unsigned num, i;
906 GROUP_AFFINITY *GroupMask;
907
908
909 if (procInfo->Relationship == RelationCache
910 && procInfo->Cache.Type != CacheUnified
911 && procInfo->Cache.Type != CacheData
912 && procInfo->Cache.Type != CacheInstruction)
913 continue;
914
915 id = HWLOC_UNKNOWN_INDEX;
916 switch (procInfo->Relationship) {
917 case RelationNumaNode:
918 type = HWLOC_OBJ_NUMANODE;
919 num = 1;
920 GroupMask = &procInfo->NumaNode.GroupMask;
921 id = procInfo->NumaNode.NodeNumber;
922 gotnuma++;
923 if (id > max_numanode_index)
924 max_numanode_index = id;
925 break;
926 case RelationProcessorPackage:
927 type = HWLOC_OBJ_PACKAGE;
928 num = procInfo->Processor.GroupCount;
929 GroupMask = procInfo->Processor.GroupMask;
930 break;
931 case RelationCache:
932 type = (procInfo->Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo->Cache.Level - 1;
933 num = 1;
934 GroupMask = &procInfo->Cache.GroupMask;
935 break;
936 case RelationProcessorCore:
937 type = HWLOC_OBJ_CORE;
938 num = procInfo->Processor.GroupCount;
939 GroupMask = procInfo->Processor.GroupMask;
940 break;
941 case RelationGroup:
942
943 for (id = 0; id < procInfo->Group.ActiveGroupCount; id++) {
944 KAFFINITY mask;
945 hwloc_bitmap_t set;
946
947 set = hwloc_bitmap_alloc();
948 mask = procInfo->Group.GroupInfo[id].ActiveProcessorMask;
949 hwloc_debug("group %u %d cpus mask %lx\n", id,
950 procInfo->Group.GroupInfo[id].ActiveProcessorCount, mask);
951
952 hwloc_bitmap_set_ith_ULONG_PTR(set, id, mask);
953
954
955
956
957 hwloc_debug_2args_bitmap("group %u %d bitmap %s\n", id, procInfo->Group.GroupInfo[id].ActiveProcessorCount, set);
958
959
960 if (!groups_pu_set)
961 groups_pu_set = hwloc_bitmap_alloc();
962 hwloc_bitmap_or(groups_pu_set, groups_pu_set, set);
963
964 if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_GROUP)) {
965 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_GROUP, id);
966 obj->cpuset = set;
967 obj->attr->group.kind = HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP;
968 hwloc_insert_object_by_cpuset(topology, obj);
969 } else
970 hwloc_bitmap_free(set);
971 }
972 continue;
973 default:
974
975 hwloc_debug("unknown relation %d\n", procInfo->Relationship);
976 continue;
977 }
978
979 if (!hwloc_filter_check_keep_object_type(topology, type))
980 continue;
981
982 obj = hwloc_alloc_setup_object(topology, type, id);
983 obj->cpuset = hwloc_bitmap_alloc();
984 for (i = 0; i < num; i++) {
985 hwloc_debug("%s#%u %d: mask %d:%lx\n", hwloc_obj_type_string(type), id, i, GroupMask[i].Group, GroupMask[i].Mask);
986
987 hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, GroupMask[i].Group, GroupMask[i].Mask);
988
989 }
990 hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset);
991 switch (type) {
992 case HWLOC_OBJ_NUMANODE:
993 {
994 ULONGLONG avail;
995 obj->nodeset = hwloc_bitmap_alloc();
996 hwloc_bitmap_set(obj->nodeset, id);
997 if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail))
998 || (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail))) {
999 obj->attr->numanode.local_memory = avail;
1000 gotnumamemory++;
1001 }
1002 obj->attr->numanode.page_types = malloc(2 * sizeof(*obj->attr->numanode.page_types));
1003 memset(obj->attr->numanode.page_types, 0, 2 * sizeof(*obj->attr->numanode.page_types));
1004 obj->attr->numanode.page_types_len = 1;
1005 obj->attr->numanode.page_types[0].size = SystemInfo.dwPageSize;
1006 #if HAVE_DECL__SC_LARGE_PAGESIZE
1007 obj->attr->numanode.page_types_len++;
1008 obj->attr->numanode.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
1009 #endif
1010 break;
1011 }
1012 case HWLOC_OBJ_L1CACHE:
1013 case HWLOC_OBJ_L2CACHE:
1014 case HWLOC_OBJ_L3CACHE:
1015 case HWLOC_OBJ_L4CACHE:
1016 case HWLOC_OBJ_L5CACHE:
1017 case HWLOC_OBJ_L1ICACHE:
1018 case HWLOC_OBJ_L2ICACHE:
1019 case HWLOC_OBJ_L3ICACHE:
1020 obj->attr->cache.size = procInfo->Cache.CacheSize;
1021 obj->attr->cache.associativity = procInfo->Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo->Cache.Associativity ;
1022 obj->attr->cache.linesize = procInfo->Cache.LineSize;
1023 obj->attr->cache.depth = procInfo->Cache.Level;
1024 switch (procInfo->Cache.Type) {
1025 case CacheUnified:
1026 obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
1027 break;
1028 case CacheData:
1029 obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
1030 break;
1031 case CacheInstruction:
1032 obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
1033 break;
1034 default:
1035 hwloc_free_unlinked_object(obj);
1036 continue;
1037 }
1038 break;
1039 default:
1040 break;
1041 }
1042 hwloc_insert_object_by_cpuset(topology, obj);
1043 }
1044 free(procInfoTotal);
1045 }
1046
1047 topology->support.discovery->pu = 1;
1048 topology->support.discovery->numa = gotnuma;
1049 topology->support.discovery->numa_memory = gotnumamemory;
1050
1051 if (groups_pu_set) {
1052
1053
1054
1055 hwloc_obj_t obj;
1056 unsigned idx;
1057 hwloc_bitmap_foreach_begin(idx, groups_pu_set) {
1058 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, idx);
1059 obj->cpuset = hwloc_bitmap_alloc();
1060 hwloc_bitmap_only(obj->cpuset, idx);
1061 hwloc_debug_1arg_bitmap("cpu %u has cpuset %s\n",
1062 idx, obj->cpuset);
1063 hwloc_insert_object_by_cpuset(topology, obj);
1064 } hwloc_bitmap_foreach_end();
1065 hwloc_bitmap_free(groups_pu_set);
1066 } else {
1067
1068 SYSTEM_INFO sysinfo;
1069 hwloc_obj_t obj;
1070 unsigned idx;
1071 GetSystemInfo(&sysinfo);
1072 for(idx=0; idx<32; idx++)
1073 if (sysinfo.dwActiveProcessorMask & (((DWORD_PTR)1)<<idx)) {
1074 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, idx);
1075 obj->cpuset = hwloc_bitmap_alloc();
1076 hwloc_bitmap_only(obj->cpuset, idx);
1077 hwloc_debug_1arg_bitmap("cpu %u has cpuset %s\n",
1078 idx, obj->cpuset);
1079 hwloc_insert_object_by_cpuset(topology, obj);
1080 }
1081 }
1082
1083 out:
1084 hwloc_obj_add_info(topology->levels[0][0], "Backend", "Windows");
1085 hwloc_add_uname_info(topology, NULL);
1086 return 0;
1087 }
1088
1089 void
1090 hwloc_set_windows_hooks(struct hwloc_binding_hooks *hooks,
1091 struct hwloc_topology_support *support)
1092 {
1093 if (GetCurrentProcessorNumberExProc || (GetCurrentProcessorNumberProc && nr_processor_groups == 1))
1094 hooks->get_thisthread_last_cpu_location = hwloc_win_get_thisthread_last_cpu_location;
1095
1096 if (nr_processor_groups == 1) {
1097 hooks->set_proc_cpubind = hwloc_win_set_proc_cpubind;
1098 hooks->get_proc_cpubind = hwloc_win_get_proc_cpubind;
1099 hooks->set_thisproc_cpubind = hwloc_win_set_thisproc_cpubind;
1100 hooks->get_thisproc_cpubind = hwloc_win_get_thisproc_cpubind;
1101 hooks->set_proc_membind = hwloc_win_set_proc_membind;
1102 hooks->get_proc_membind = hwloc_win_get_proc_membind;
1103 hooks->set_thisproc_membind = hwloc_win_set_thisproc_membind;
1104 hooks->get_thisproc_membind = hwloc_win_get_thisproc_membind;
1105 }
1106 if (nr_processor_groups == 1 || SetThreadGroupAffinityProc) {
1107 hooks->set_thread_cpubind = hwloc_win_set_thread_cpubind;
1108 hooks->set_thisthread_cpubind = hwloc_win_set_thisthread_cpubind;
1109 hooks->set_thisthread_membind = hwloc_win_set_thisthread_membind;
1110 }
1111 if (GetThreadGroupAffinityProc) {
1112 hooks->get_thread_cpubind = hwloc_win_get_thread_cpubind;
1113 hooks->get_thisthread_cpubind = hwloc_win_get_thisthread_cpubind;
1114 hooks->get_thisthread_membind = hwloc_win_get_thisthread_membind;
1115 }
1116
1117 if (VirtualAllocExNumaProc) {
1118 hooks->alloc_membind = hwloc_win_alloc_membind;
1119 hooks->alloc = hwloc_win_alloc;
1120 hooks->free_membind = hwloc_win_free_membind;
1121 support->membind->bind_membind = 1;
1122 }
1123
1124 if (QueryWorkingSetExProc && max_numanode_index <= 63 )
1125 hooks->get_area_memlocation = hwloc_win_get_area_memlocation;
1126 }
1127
1128 static int hwloc_windows_component_init(unsigned long flags __hwloc_attribute_unused)
1129 {
1130 hwloc_win_get_function_ptrs();
1131 return 0;
1132 }
1133
1134 static void hwloc_windows_component_finalize(unsigned long flags __hwloc_attribute_unused)
1135 {
1136 }
1137
1138 static struct hwloc_backend *
1139 hwloc_windows_component_instantiate(struct hwloc_disc_component *component,
1140 const void *_data1 __hwloc_attribute_unused,
1141 const void *_data2 __hwloc_attribute_unused,
1142 const void *_data3 __hwloc_attribute_unused)
1143 {
1144 struct hwloc_backend *backend;
1145 backend = hwloc_backend_alloc(component);
1146 if (!backend)
1147 return NULL;
1148 backend->discover = hwloc_look_windows;
1149 return backend;
1150 }
1151
1152 static struct hwloc_disc_component hwloc_windows_disc_component = {
1153 HWLOC_DISC_COMPONENT_TYPE_CPU,
1154 "windows",
1155 HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
1156 hwloc_windows_component_instantiate,
1157 50,
1158 1,
1159 NULL
1160 };
1161
1162 const struct hwloc_component hwloc_windows_component = {
1163 HWLOC_COMPONENT_ABI,
1164 hwloc_windows_component_init, hwloc_windows_component_finalize,
1165 HWLOC_COMPONENT_TYPE_DISC,
1166 0,
1167 &hwloc_windows_disc_component
1168 };
1169
1170 int
1171 hwloc_fallback_nbprocessors(struct hwloc_topology *topology __hwloc_attribute_unused) {
1172 int n;
1173 SYSTEM_INFO sysinfo;
1174
1175
1176 GetSystemInfo(&sysinfo);
1177 n = sysinfo.dwNumberOfProcessors;
1178
1179 if (nr_processor_groups > 1) {
1180
1181 if (GetActiveProcessorCountProc)
1182 n = MAXIMUM_PROC_PER_GROUP*(nr_processor_groups-1)
1183 + GetActiveProcessorCountProc((WORD)nr_processor_groups-1);
1184 else
1185 n = MAXIMUM_PROC_PER_GROUP*nr_processor_groups;
1186 }
1187
1188 return n;
1189 }