root/opal/mca/hwloc/hwloc201/hwloc/hwloc/topology-windows.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwloc_win_get_function_ptrs
  2. hwloc_bitmap_from_ULONG_PTR
  3. hwloc_bitmap_from_ith_ULONG_PTR
  4. hwloc_bitmap_set_ith_ULONG_PTR
  5. hwloc_bitmap_to_ULONG_PTR
  6. hwloc_bitmap_to_ith_ULONG_PTR
  7. hwloc_bitmap_to_single_ULONG_PTR
  8. hwloc_win_get_thisthread_last_cpu_location
  9. hwloc_win_set_thread_cpubind
  10. hwloc_win_set_thisthread_cpubind
  11. hwloc_win_set_thisthread_membind
  12. hwloc_win_get_thread_cpubind
  13. hwloc_win_get_thisthread_cpubind
  14. hwloc_win_get_thisthread_membind
  15. hwloc_win_set_proc_cpubind
  16. hwloc_win_set_thisproc_cpubind
  17. hwloc_win_set_proc_membind
  18. hwloc_win_set_thisproc_membind
  19. hwloc_win_get_proc_cpubind
  20. hwloc_win_get_proc_membind
  21. hwloc_win_get_thisproc_cpubind
  22. hwloc_win_get_thisproc_membind
  23. hwloc_win_alloc
  24. hwloc_win_alloc_membind
  25. hwloc_win_free_membind
  26. hwloc_win_get_area_memlocation
  27. hwloc_look_windows
  28. hwloc_set_windows_hooks
  29. hwloc_windows_component_init
  30. hwloc_windows_component_finalize
  31. hwloc_windows_component_instantiate
  32. hwloc_fallback_nbprocessors

   1 /*
   2  * Copyright © 2009 CNRS
   3  * Copyright © 2009-2018 Inria.  All rights reserved.
   4  * Copyright © 2009-2012 Université Bordeaux
   5  * Copyright © 2011 Cisco Systems, Inc.  All rights reserved.
   6  * See COPYING in top-level directory.
   7  */
   8 
   9 /* To try to get all declarations duplicated below.  */
  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 /* missing in MinGW */
  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; /* in bytes */
  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 /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
  60 #  ifndef HAVE_RELATIONPROCESSORPACKAGE
  61 #    define RelationProcessorPackage 3
  62 #    define RelationGroup 4
  63 #    define RelationAll 0xffff
  64 #  endif /* HAVE_RELATIONPROCESSORPACKAGE */
  65 #endif /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
  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 /* Extended interface, for group support */
  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     /* Odd: no member to tell the cpu mask of the package... */
 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 /* Function pointers */
 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  * ULONG_PTR and DWORD_PTR are 64/32bits depending on the arch
 277  * while bitmaps use unsigned long (always 32bits)
 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 /* convert set into index+mask if all set bits are in the same ULONG.
 335  * otherwise return -1.
 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  * hwloc PU numbering with respect to Windows processor groups
 353  *
 354  * Everywhere below we reserve 64 physical indexes per processor groups because that's
 355  * the maximum (MAXIMUM_PROC_PER_GROUP). Windows may actually use less bits than that
 356  * in some groups (either to avoid splitting NUMA nodes across groups, or because of OS
 357  * tweaks such as "bcdedit /set groupsize 8") but we keep some unused indexes for simplicity.
 358  * That means PU physical indexes and cpusets may be non-contigous.
 359  * That also means hwloc_fallback_nbprocessors() below must return the last PU index + 1
 360  * instead the actual number of processors.
 361  */
 362 
 363 /********************
 364  * last_cpu_location
 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 /* TODO: hwloc_win_get_thisproc_last_cpu_location() using
 384  * CreateToolhelp32Snapshot(), Thread32First/Next()
 385  * th.th32OwnerProcessID == GetCurrentProcessId() for filtering within process
 386  * OpenThread(THREAD_SET_INFORMATION|THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID) to get a handle.
 387  */
 388 
 389 
 390 /******************************
 391  * set cpu/membind for threads
 392  */
 393 
 394 /* TODO: SetThreadIdealProcessor{,Ex} */
 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)); /* we get Invalid Parameter error if Reserved field isn't cleared */
 417     aff.Group = group;
 418     aff.Mask = mask;
 419     if (!SetThreadGroupAffinityProc(thread, &aff, NULL))
 420       return -1;
 421 
 422   } else {
 423     /* SetThreadAffinityMask() only changes the mask inside the current processor group */
 424     /* The resulting binding is always strict */
 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  * get cpu/membind for threads
 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  * set cpu/membind for processes
 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   /* TODO: SetThreadGroupAffinity() for all threads doesn't enforce the whole process affinity,
 519    * maybe because of process-specific resource locality */
 520   /* TODO: if we are in a single group (check with GetProcessGroupAffinity()),
 521    * SetProcessAffinityMask() changes the binding within that same group.
 522    */
 523   /* TODO: NtSetInformationProcess() works very well for binding to any mask in a single group,
 524    * but it's an internal routine.
 525    */
 526   /* TODO: checks whether hwloc-bind.c needs to pass INHERIT_PARENT_AFFINITY to CreateProcess() instead of execvp(). */
 527 
 528   /* The resulting binding is always strict */
 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  * get cpu/membind for processes
 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   /* TODO: if we are in a single group (check with GetProcessGroupAffinity()),
 591    * GetProcessAffinityMask() gives the mask within that group.
 592    */
 593   /* TODO: if we are in multiple groups, GetProcessGroupAffinity() gives their IDs,
 594    * but we don't know their masks.
 595    */
 596   /* TODO: GetThreadGroupAffinity() for all threads can be smaller than the whole process affinity,
 597    * maybe because of process-specific resource locality.
 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  * membind alloc/free
 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     /* Not a single node, can't do this */
 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  * membind for areas
 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  * discovery
 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     /* somebody discovered things */
 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         /* Ignore unknown caches */
 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         /* ProcessorMask is a ULONG_PTR */
 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         /* Ignore unknown caches */
 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             /* So strange an interface... */
 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               /* KAFFINITY is ULONG_PTR */
 952               hwloc_bitmap_set_ith_ULONG_PTR(set, id, mask);
 953               /* FIXME: what if running 32bits on a 64bits windows with 64-processor groups?
 954                * ULONG_PTR is 32bits, so half the group is invisible?
 955                * maybe scale id to id*8/sizeof(ULONG_PTR) so that groups are 64-PU aligned?
 956                */
 957               hwloc_debug_2args_bitmap("group %u %d bitmap %s\n", id, procInfo->Group.GroupInfo[id].ActiveProcessorCount, set);
 958 
 959               /* save the set of PUs so that we can create them at the end */
 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             /* Don't know how to get the mask.  */
 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           /* GROUP_AFFINITY.Mask is KAFFINITY, which is ULONG_PTR */
 987           hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, GroupMask[i].Group, GroupMask[i].Mask);
 988           /* FIXME: scale id to id*8/sizeof(ULONG_PTR) as above? */
 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     /* the system supports multiple Groups.
1053      * PU indexes may be discontiguous, especially if Groups contain less than 64 procs.
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     /* no processor groups */
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 /* PSAPI_WORKING_SET_EX_BLOCK.Node is 6 bits only */)
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   /* by default, ignore groups (return only the number in the current group) */
1176   GetSystemInfo(&sysinfo);
1177   n = sysinfo.dwNumberOfProcessors; /* FIXME could be non-contigous, rather return a mask from dwActiveProcessorMask? */
1178 
1179   if (nr_processor_groups > 1) {
1180     /* assume n-1 groups are complete, since that's how we store things in cpusets */
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 }

/* [<][>][^][v][top][bottom][index][help] */