diff options
Diffstat (limited to 'hwloc-1.2.1/src/topology-windows.c')
-rw-r--r-- | hwloc-1.2.1/src/topology-windows.c | 706 |
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; +} |