/* * 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 #include #include #include #include #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; }