summaryrefslogtreecommitdiffstats
path: root/hwloc-1.2.1/src/topology-windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'hwloc-1.2.1/src/topology-windows.c')
-rw-r--r--hwloc-1.2.1/src/topology-windows.c706
1 files changed, 706 insertions, 0 deletions
diff --git a/hwloc-1.2.1/src/topology-windows.c b/hwloc-1.2.1/src/topology-windows.c
new file mode 100644
index 00000000..5c4c26a8
--- /dev/null
+++ b/hwloc-1.2.1/src/topology-windows.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright © 2009 CNRS
+ * Copyright © 2009-2010 INRIA. All rights reserved.
+ * Copyright © 2009-2011 Université Bordeaux 1
+ * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
+ * See COPYING in top-level directory.
+ */
+
+/* To try to get all declarations duplicated below. */
+#define _WIN32_WINNT 0x0601
+
+#include <private/autogen/config.h>
+#include <hwloc.h>
+#include <private/private.h>
+#include <private/debug.h>
+
+#include <windows.h>
+
+#ifndef HAVE_KAFFINITY
+typedef ULONG_PTR KAFFINITY, *PKAFFINITY;
+#endif
+
+#ifndef HAVE_PROCESSOR_CACHE_TYPE
+typedef enum _PROCESSOR_CACHE_TYPE {
+ CacheUnified,
+ CacheInstruction,
+ CacheData,
+ CacheTrace
+} PROCESSOR_CACHE_TYPE;
+#endif
+
+#ifndef CACHE_FULLY_ASSOCIATIVE
+#define CACHE_FULLY_ASSOCIATIVE 0xFF
+#endif
+
+#ifndef HAVE_CACHE_DESCRIPTOR
+typedef struct _CACHE_DESCRIPTOR {
+ BYTE Level;
+ BYTE Associativity;
+ WORD LineSize;
+ DWORD Size; /* in bytes */
+ PROCESSOR_CACHE_TYPE Type;
+} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR;
+#endif
+
+#ifndef HAVE_LOGICAL_PROCESSOR_RELATIONSHIP
+typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
+ RelationProcessorCore,
+ RelationNumaNode,
+ RelationCache,
+ RelationProcessorPackage,
+ RelationGroup,
+ RelationAll = 0xffff
+} LOGICAL_PROCESSOR_RELATIONSHIP;
+#else /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
+# ifndef HAVE_RELATIONPROCESSORPACKAGE
+# define RelationProcessorPackage 3
+# define RelationGroup 4
+# define RelationAll 0xffff
+# endif /* HAVE_RELATIONPROCESSORPACKAGE */
+#endif /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */
+
+#ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION
+typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
+ ULONG_PTR ProcessorMask;
+ LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
+ _ANONYMOUS_UNION
+ union {
+ struct {
+ BYTE flags;
+ } ProcessorCore;
+ struct {
+ DWORD NodeNumber;
+ } NumaNode;
+ CACHE_DESCRIPTOR Cache;
+ ULONGLONG Reserved[2];
+ } DUMMYUNIONNAME;
+} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
+#endif
+
+/* Extended interface, for group support */
+
+#ifndef HAVE_GROUP_AFFINITY
+typedef struct _GROUP_AFFINITY {
+ KAFFINITY Mask;
+ WORD Group;
+ WORD Reserved[3];
+} GROUP_AFFINITY, *PGROUP_AFFINITY;
+#endif
+
+#ifndef HAVE_PROCESSOR_RELATIONSHIP
+typedef struct _PROCESSOR_RELATIONSHIP {
+ BYTE Flags;
+ BYTE Reserved[21];
+ WORD GroupCount;
+ GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY];
+} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP;
+#endif
+
+#ifndef HAVE_NUMA_NODE_RELATIONSHIP
+typedef struct _NUMA_NODE_RELATIONSHIP {
+ DWORD NodeNumber;
+ BYTE Reserved[20];
+ GROUP_AFFINITY GroupMask;
+} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP;
+#endif
+
+#ifndef HAVE_CACHE_RELATIONSHIP
+typedef struct _CACHE_RELATIONSHIP {
+ BYTE Level;
+ BYTE Associativity;
+ WORD LineSize;
+ DWORD CacheSize;
+ PROCESSOR_CACHE_TYPE Type;
+ BYTE Reserved[20];
+ GROUP_AFFINITY GroupMask;
+} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP;
+#endif
+
+#ifndef HAVE_PROCESSOR_GROUP_INFO
+typedef struct _PROCESSOR_GROUP_INFO {
+ BYTE MaximumProcessorCount;
+ BYTE ActiveProcessorCount;
+ BYTE Reserved[38];
+ KAFFINITY ActiveProcessorMask;
+} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO;
+#endif
+
+#ifndef HAVE_GROUP_RELATIONSHIP
+typedef struct _GROUP_RELATIONSHIP {
+ WORD MaximumGroupCount;
+ WORD ActiveGroupCount;
+ ULONGLONG Reserved[2];
+ PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY];
+} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP;
+#endif
+
+#ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
+typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
+ LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
+ DWORD Size;
+ _ANONYMOUS_UNION
+ union {
+ PROCESSOR_RELATIONSHIP Processor;
+ NUMA_NODE_RELATIONSHIP NumaNode;
+ CACHE_RELATIONSHIP Cache;
+ GROUP_RELATIONSHIP Group;
+ /* Odd: no member to tell the cpu mask of the package... */
+ } DUMMYUNIONNAME;
+} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
+#endif
+
+#ifndef HAVE_PSAPI_WORKING_SET_EX_BLOCK
+typedef union _PSAPI_WORKING_SET_EX_BLOCK {
+ ULONG_PTR Flags;
+ struct {
+ unsigned Valid :1;
+ unsigned ShareCount :3;
+ unsigned Win32Protection :11;
+ unsigned Shared :1;
+ unsigned Node :6;
+ unsigned Locked :1;
+ unsigned LargePage :1;
+ };
+} PSAPI_WORKING_SET_EX_BLOCK;
+#endif
+
+#ifndef HAVE_PSAPI_WORKING_SET_EX_INFORMATION
+typedef struct _PSAPI_WORKING_SET_EX_INFORMATION {
+ PVOID VirtualAddress;
+ PSAPI_WORKING_SET_EX_BLOCK VirtualAttributes;
+} PSAPI_WORKING_SET_EX_INFORMATION;
+#endif
+
+/* TODO: SetThreadIdealProcessor */
+
+static int
+hwloc_win_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t thread, hwloc_const_bitmap_t hwloc_set, int flags)
+{
+ if (flags & HWLOC_CPUBIND_NOMEMBIND) {
+ errno = ENOSYS;
+ return -1;
+ }
+ /* TODO: groups SetThreadGroupAffinity */
+ /* The resulting binding is always strict */
+ DWORD mask = hwloc_bitmap_to_ulong(hwloc_set);
+ if (!SetThreadAffinityMask(thread, mask))
+ return -1;
+ return 0;
+}
+
+/* TODO: SetThreadGroupAffinity to get affinity */
+
+static int
+hwloc_win_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
+{
+ return hwloc_win_set_thread_cpubind(topology, GetCurrentThread(), hwloc_set, flags);
+}
+
+static int
+hwloc_win_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
+{
+ int ret;
+ hwloc_cpuset_t cpuset;
+
+ if ((policy != HWLOC_MEMBIND_DEFAULT && policy != HWLOC_MEMBIND_BIND)
+ || flags & HWLOC_MEMBIND_NOCPUBIND) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ cpuset = hwloc_bitmap_alloc();
+ hwloc_cpuset_from_nodeset(topology, cpuset, nodeset);
+ ret = hwloc_win_set_thisthread_cpubind(topology, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0);
+ hwloc_bitmap_free(cpuset);
+ return ret;
+}
+
+static int
+hwloc_win_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t proc, hwloc_const_bitmap_t hwloc_set, int flags)
+{
+ if (flags & HWLOC_CPUBIND_NOMEMBIND) {
+ errno = ENOSYS;
+ return -1;
+ }
+ /* TODO: groups, hard: has to manually bind all threads into the other group,
+ * and the bind the process inside the group */
+ /* The resulting binding is always strict */
+ DWORD mask = hwloc_bitmap_to_ulong(hwloc_set);
+ if (!SetProcessAffinityMask(proc, mask))
+ return -1;
+ return 0;
+}
+
+static int
+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)
+{
+ int ret;
+ hwloc_cpuset_t cpuset;
+
+ if ((policy != HWLOC_MEMBIND_DEFAULT && policy != HWLOC_MEMBIND_BIND)
+ || flags & HWLOC_MEMBIND_NOCPUBIND) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ cpuset = hwloc_bitmap_alloc();
+ hwloc_cpuset_from_nodeset(topology, cpuset, nodeset);
+ ret = hwloc_win_set_proc_cpubind(topology, pid, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0);
+ hwloc_bitmap_free(cpuset);
+ return ret;
+}
+
+static int
+hwloc_win_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t proc, hwloc_bitmap_t hwloc_set, int flags)
+{
+ DWORD_PTR proc_mask, sys_mask;
+ if (flags & HWLOC_CPUBIND_NOMEMBIND) {
+ errno = ENOSYS;
+ return -1;
+ }
+ /* TODO: groups, GetProcessGroupAffinity, or merge SetThreadGroupAffinity for all threads */
+ if (!GetProcessAffinityMask(proc, &proc_mask, &sys_mask))
+ return -1;
+ hwloc_bitmap_from_ulong(hwloc_set, proc_mask);
+ return 0;
+}
+
+static int
+hwloc_win_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
+{
+ int ret;
+ hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
+ ret = hwloc_win_get_proc_cpubind(topology, pid, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0);
+ if (!ret) {
+ *policy = HWLOC_MEMBIND_BIND;
+ hwloc_cpuset_to_nodeset(topology, cpuset, nodeset);
+ }
+ hwloc_bitmap_free(cpuset);
+ return ret;
+}
+
+static int
+hwloc_win_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
+{
+ return hwloc_win_set_proc_cpubind(topology, GetCurrentProcess(), hwloc_set, flags);
+}
+
+static int
+hwloc_win_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
+{
+ return hwloc_win_set_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags);
+}
+
+static int
+hwloc_win_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
+{
+ return hwloc_win_get_proc_cpubind(topology, GetCurrentProcess(), hwloc_cpuset, flags);
+}
+
+static int
+hwloc_win_get_thisproc_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
+{
+ return hwloc_win_get_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags);
+}
+
+static LPVOID WINAPI (*VirtualAllocExNumaProc)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, DWORD nndPreferred);
+static BOOL WINAPI (*VirtualFreeExProc)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
+static BOOL WINAPI (*QueryWorkingSetExProc)(HANDLE hProcess, PVOID pv, DWORD cb);
+
+static int hwloc_win_get_VirtualAllocExNumaProc(void) {
+ if (VirtualAllocExNumaProc == NULL) {
+ FARPROC alloc_fun = NULL, free_fun = NULL;
+ HMODULE kernel32;
+
+ kernel32 = LoadLibrary("kernel32.dll");
+ if (kernel32) {
+ alloc_fun = GetProcAddress(kernel32, "VirtualAllocExNuma");
+ free_fun = GetProcAddress(kernel32, "VirtualFreeEx");
+ }
+
+ if (!alloc_fun || !free_fun) {
+ VirtualAllocExNumaProc = (FARPROC) -1;
+ errno = ENOSYS;
+ return -1;
+ }
+
+ VirtualAllocExNumaProc = alloc_fun;
+ VirtualFreeExProc = free_fun;
+ } else if ((FARPROC) VirtualAllocExNumaProc == (FARPROC)-1) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void *
+hwloc_win_alloc(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) {
+ return VirtualAlloc(NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+}
+
+static void *
+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) {
+ int node;
+
+ switch (policy) {
+ case HWLOC_MEMBIND_DEFAULT:
+ case HWLOC_MEMBIND_BIND:
+ break;
+ default:
+ errno = ENOSYS;
+ return hwloc_alloc_or_fail(topology, len, flags);
+ }
+
+ if (flags & HWLOC_MEMBIND_STRICT) {
+ errno = ENOSYS;
+ return NULL;
+ }
+
+ if (hwloc_bitmap_weight(nodeset) != 1) {
+ /* Not a single node, can't do this */
+ errno = EXDEV;
+ return hwloc_alloc_or_fail(topology, len, flags);
+ }
+
+ node = hwloc_bitmap_first(nodeset);
+ return VirtualAllocExNumaProc(GetCurrentProcess(), NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE, node);
+}
+
+static int
+hwloc_win_free_membind(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused) {
+ if (!addr)
+ return 0;
+ if (!VirtualFreeExProc(GetCurrentProcess(), addr, 0, MEM_RELEASE))
+ return -1;
+ return 0;
+}
+
+static int hwloc_win_get_QueryWorkingSetExProc(void) {
+ if (QueryWorkingSetExProc == NULL) {
+ FARPROC fun = NULL;
+ HMODULE kernel32, psapi;
+
+ kernel32 = LoadLibrary("kernel32.dll");
+ if (kernel32)
+ fun = GetProcAddress(kernel32, "K32QueryWorkingSetEx");
+ if (!fun) {
+ psapi = LoadLibrary("psapi.dll");
+ if (psapi)
+ fun = GetProcAddress(psapi, "QueryWorkingSetEx");
+ }
+
+ if (!fun) {
+ QueryWorkingSetExProc = (FARPROC) -1;
+ errno = ENOSYS;
+ return -1;
+ }
+
+ QueryWorkingSetExProc = fun;
+ } else if ((FARPROC) QueryWorkingSetExProc == (FARPROC)-1) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+hwloc_win_get_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
+{
+ SYSTEM_INFO SystemInfo;
+ DWORD page_size;
+
+ GetSystemInfo(&SystemInfo);
+ page_size = SystemInfo.dwPageSize;
+
+ uintptr_t start = (((uintptr_t) addr) / page_size) * page_size;
+ unsigned nb = (((uintptr_t) addr + len - start) + page_size - 1) / page_size;
+
+ if (!nb)
+ nb = 1;
+
+ {
+ PSAPI_WORKING_SET_EX_INFORMATION pv[nb];
+ unsigned i;
+
+ for (i = 0; i < nb; i++)
+ pv[i].VirtualAddress = (void*) (start + i * page_size);
+ if (!QueryWorkingSetExProc(GetCurrentProcess(), &pv, sizeof(pv)))
+ return -1;
+ *policy = HWLOC_MEMBIND_BIND;
+ if (flags & HWLOC_MEMBIND_STRICT) {
+ unsigned node = pv[0].VirtualAttributes.Node;
+ for (i = 1; i < nb; i++) {
+ if (pv[i].VirtualAttributes.Node != node) {
+ errno = EXDEV;
+ return -1;
+ }
+ }
+ hwloc_bitmap_only(nodeset, node);
+ return 0;
+ }
+ hwloc_bitmap_zero(nodeset);
+ for (i = 0; i < nb; i++)
+ hwloc_bitmap_set(nodeset, pv[i].VirtualAttributes.Node);
+ return 0;
+ }
+}
+
+void
+hwloc_look_windows(struct hwloc_topology *topology)
+{
+ BOOL WINAPI (*GetLogicalProcessorInformationProc)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength);
+ BOOL WINAPI (*GetLogicalProcessorInformationExProc)(LOGICAL_PROCESSOR_RELATIONSHIP relationship, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, PDWORD ReturnLength);
+ BOOL WINAPI (*GetNumaAvailableMemoryNodeProc)(UCHAR Node, PULONGLONG AvailableBytes);
+ BOOL WINAPI (*GetNumaAvailableMemoryNodeExProc)(USHORT Node, PULONGLONG AvailableBytes);
+ SYSTEM_INFO SystemInfo;
+
+ DWORD length;
+
+ HMODULE kernel32;
+
+ GetSystemInfo(&SystemInfo);
+
+ kernel32 = LoadLibrary("kernel32.dll");
+ if (kernel32) {
+ GetLogicalProcessorInformationProc = GetProcAddress(kernel32, "GetLogicalProcessorInformation");
+ GetNumaAvailableMemoryNodeProc = GetProcAddress(kernel32, "GetNumaAvailableMemoryNode");
+ GetNumaAvailableMemoryNodeExProc = GetProcAddress(kernel32, "GetNumaAvailableMemoryNodeEx");
+ GetLogicalProcessorInformationExProc = GetProcAddress(kernel32, "GetLogicalProcessorInformationEx");
+
+ if (!GetLogicalProcessorInformationExProc && GetLogicalProcessorInformationProc) {
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION procInfo;
+ unsigned id;
+ unsigned i;
+ struct hwloc_obj *obj;
+ hwloc_obj_type_t type;
+
+ length = 0;
+ procInfo = NULL;
+
+ while (1) {
+ if (GetLogicalProcessorInformationProc(procInfo, &length))
+ break;
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ return;
+ procInfo = realloc(procInfo, length);
+ }
+
+ for (i = 0; i < length / sizeof(*procInfo); i++) {
+
+ /* Ignore non-data caches */
+ if (procInfo[i].Relationship == RelationCache
+ && procInfo[i].Cache.Type != CacheUnified
+ && procInfo[i].Cache.Type != CacheData)
+ continue;
+
+ id = -1;
+ switch (procInfo[i].Relationship) {
+ case RelationNumaNode:
+ type = HWLOC_OBJ_NODE;
+ id = procInfo[i].NumaNode.NodeNumber;
+ break;
+ case RelationProcessorPackage:
+ type = HWLOC_OBJ_SOCKET;
+ break;
+ case RelationCache:
+ type = HWLOC_OBJ_CACHE;
+ break;
+ case RelationProcessorCore:
+ type = HWLOC_OBJ_CORE;
+ break;
+ case RelationGroup:
+ default:
+ type = HWLOC_OBJ_GROUP;
+ break;
+ }
+
+ obj = hwloc_alloc_setup_object(type, id);
+ obj->cpuset = hwloc_bitmap_alloc();
+ hwloc_debug("%s#%u mask %lx\n", hwloc_obj_type_string(type), id, procInfo[i].ProcessorMask);
+ hwloc_bitmap_from_ulong(obj->cpuset, procInfo[i].ProcessorMask);
+
+ switch (type) {
+ case HWLOC_OBJ_NODE:
+ {
+ ULONGLONG avail;
+ obj->nodeset = hwloc_bitmap_alloc();
+ hwloc_bitmap_set(obj->nodeset, id);
+ if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail))
+ || (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail)))
+ obj->memory.local_memory = avail;
+ obj->memory.page_types_len = 2;
+ obj->memory.page_types = malloc(2 * sizeof(*obj->memory.page_types));
+ memset(obj->memory.page_types, 0, 2 * sizeof(*obj->memory.page_types));
+ obj->memory.page_types_len = 1;
+ obj->memory.page_types[0].size = SystemInfo.dwPageSize;
+#ifdef HAVE__SC_LARGE_PAGESIZE
+ obj->memory.page_types_len++;
+ obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
+#endif
+ break;
+ }
+ case HWLOC_OBJ_CACHE:
+ obj->attr->cache.size = procInfo[i].Cache.Size;
+ obj->attr->cache.linesize = procInfo[i].Cache.LineSize;
+ obj->attr->cache.depth = procInfo[i].Cache.Level;
+ break;
+ case HWLOC_OBJ_GROUP:
+ obj->attr->group.depth = procInfo[i].Relationship == RelationGroup;
+ break;
+ default:
+ break;
+ }
+ hwloc_insert_object_by_cpuset(topology, obj);
+ }
+
+ free(procInfo);
+ }
+
+ if (GetLogicalProcessorInformationExProc) {
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX procInfoTotal, procInfo;
+
+ unsigned id;
+ struct hwloc_obj *obj;
+ hwloc_obj_type_t type;
+
+ length = 0;
+ procInfoTotal = NULL;
+
+ while (1) {
+ if (GetLogicalProcessorInformationExProc(RelationAll, procInfoTotal, &length))
+ break;
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ return;
+ procInfoTotal = realloc(procInfoTotal, length);
+ }
+
+ for (procInfo = procInfoTotal;
+ (void*) procInfo < (void*) ((unsigned long) procInfoTotal + length);
+ procInfo = (void*) ((unsigned long) procInfo + procInfo->Size)) {
+ unsigned num, i;
+ GROUP_AFFINITY *GroupMask;
+
+ /* Ignore non-data caches */
+ if (procInfo->Relationship == RelationCache
+ && procInfo->Cache.Type != CacheUnified
+ && procInfo->Cache.Type != CacheData)
+ continue;
+
+ id = -1;
+ switch (procInfo->Relationship) {
+ case RelationNumaNode:
+ type = HWLOC_OBJ_NODE;
+ num = 1;
+ GroupMask = &procInfo->NumaNode.GroupMask;
+ id = procInfo->NumaNode.NodeNumber;
+ break;
+ case RelationProcessorPackage:
+ type = HWLOC_OBJ_SOCKET;
+ num = procInfo->Processor.GroupCount;
+ GroupMask = procInfo->Processor.GroupMask;
+ break;
+ case RelationCache:
+ type = HWLOC_OBJ_CACHE;
+ num = 1;
+ GroupMask = &procInfo->Cache.GroupMask;
+ break;
+ case RelationProcessorCore:
+ type = HWLOC_OBJ_CORE;
+ num = procInfo->Processor.GroupCount;
+ GroupMask = procInfo->Processor.GroupMask;
+ break;
+ case RelationGroup:
+ /* So strange an interface... */
+ for (id = 0; id < procInfo->Group.ActiveGroupCount; id++) {
+ KAFFINITY mask;
+ obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, id);
+ obj->cpuset = hwloc_bitmap_alloc();
+ mask = procInfo->Group.GroupInfo[id].ActiveProcessorMask;
+ hwloc_debug("group %u %d cpus mask %lx\n", id,
+ procInfo->Group.GroupInfo[id].ActiveProcessorCount, mask);
+ hwloc_bitmap_from_ith_ulong(obj->cpuset, id, mask);
+ hwloc_insert_object_by_cpuset(topology, obj);
+ }
+ continue;
+ default:
+ /* Don't know how to get the mask. */
+ hwloc_debug("unknown relation %d\n", procInfo->Relationship);
+ continue;
+ }
+
+ obj = hwloc_alloc_setup_object(type, id);
+ obj->cpuset = hwloc_bitmap_alloc();
+ for (i = 0; i < num; i++) {
+ hwloc_debug("%s#%u %d: mask %d:%lx\n", hwloc_obj_type_string(type), id, i, GroupMask[i].Group, GroupMask[i].Mask);
+ hwloc_bitmap_from_ith_ulong(obj->cpuset, GroupMask[i].Group, GroupMask[i].Mask);
+ }
+
+ switch (type) {
+ case HWLOC_OBJ_NODE:
+ {
+ ULONGLONG avail;
+ obj->nodeset = hwloc_bitmap_alloc();
+ hwloc_bitmap_set(obj->nodeset, id);
+ if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail))
+ || (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail)))
+ obj->memory.local_memory = avail;
+ obj->memory.page_types = malloc(2 * sizeof(*obj->memory.page_types));
+ memset(obj->memory.page_types, 0, 2 * sizeof(*obj->memory.page_types));
+ obj->memory.page_types_len = 1;
+ obj->memory.page_types[0].size = SystemInfo.dwPageSize;
+#ifdef HAVE__SC_LARGE_PAGESIZE
+ obj->memory.page_types_len++;
+ obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
+#endif
+ break;
+ }
+ case HWLOC_OBJ_CACHE:
+ obj->attr->cache.size = procInfo->Cache.CacheSize;
+ obj->attr->cache.linesize = procInfo->Cache.LineSize;
+ obj->attr->cache.depth = procInfo->Cache.Level;
+ break;
+ default:
+ break;
+ }
+ hwloc_insert_object_by_cpuset(topology, obj);
+ }
+ free(procInfoTotal);
+ }
+ }
+
+ /* add PU objects */
+ hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology));
+
+ hwloc_add_object_info(topology->levels[0][0], "Backend", "Windows");
+}
+
+void
+hwloc_set_windows_hooks(struct hwloc_topology *topology)
+{
+ topology->set_proc_cpubind = hwloc_win_set_proc_cpubind;
+ topology->get_proc_cpubind = hwloc_win_get_proc_cpubind;
+ topology->set_thread_cpubind = hwloc_win_set_thread_cpubind;
+ topology->set_thisproc_cpubind = hwloc_win_set_thisproc_cpubind;
+ topology->get_thisproc_cpubind = hwloc_win_get_thisproc_cpubind;
+ topology->set_thisthread_cpubind = hwloc_win_set_thisthread_cpubind;
+ /* TODO: get_last_cpu_location: use GetCurrentProcessorNumber */
+
+ topology->set_proc_membind = hwloc_win_set_proc_membind;
+ topology->get_proc_membind = hwloc_win_get_proc_membind;
+ topology->set_thisproc_membind = hwloc_win_set_thisproc_membind;
+ topology->get_thisproc_membind = hwloc_win_get_thisproc_membind;
+ topology->set_thisthread_membind = hwloc_win_set_thisthread_membind;
+
+ if (!hwloc_win_get_VirtualAllocExNumaProc()) {
+ topology->alloc_membind = hwloc_win_alloc_membind;
+ topology->alloc = hwloc_win_alloc;
+ topology->free_membind = hwloc_win_free_membind;
+ topology->support.membind->bind_membind = 1;
+ }
+
+ if (!hwloc_win_get_QueryWorkingSetExProc())
+ topology->get_area_membind = hwloc_win_get_area_membind;
+}