127 lines
3.2 KiB
C++
127 lines
3.2 KiB
C++
#include <hwloc.h>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
#include "nm.h"
|
|
|
|
struct nm_obj {
|
|
int level;
|
|
int id;
|
|
struct nm_obj *parent;
|
|
std::vector<struct nm_obj *> children;
|
|
};
|
|
|
|
static bool nm_obj_comparator(struct nm_obj * a, struct nm_obj * b)
|
|
{
|
|
return a->id < b->id;
|
|
}
|
|
|
|
static std::vector<struct nm_obj *> nodes;
|
|
static std::vector<struct nm_obj *> cores;
|
|
static std::vector<struct nm_obj *> cpus;
|
|
|
|
std::vector<struct nm_obj *> * nm_get_nodes()
|
|
{
|
|
return &nodes;
|
|
}
|
|
|
|
std::vector<struct nm_obj *> * nm_get_cpus()
|
|
{
|
|
return &cpus;
|
|
}
|
|
|
|
std::vector<struct nm_obj *> * nm_get_cores()
|
|
{
|
|
return &cores;
|
|
}
|
|
|
|
hwloc_obj_t get_parent_type(hwloc_obj_t obj, hwloc_obj_type_t type)
|
|
{
|
|
while(obj != nullptr) {
|
|
if (obj->type == type) {
|
|
break;
|
|
}
|
|
obj = obj->parent;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
// 0 on success
|
|
// -1 on error
|
|
int nm_init()
|
|
{
|
|
int ret;
|
|
|
|
hwloc_topology * topo;
|
|
if ((ret = hwloc_topology_init(&topo)) != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if ((ret = hwloc_topology_load(topo)) != 0)
|
|
return ret;
|
|
|
|
// populate numa nodes
|
|
hwloc_obj_t obj = nullptr;
|
|
while(1) {
|
|
obj = hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_PACKAGE, obj);
|
|
if (obj == nullptr) {
|
|
break;
|
|
}
|
|
|
|
struct nm_obj * each = new struct nm_obj;
|
|
each->id = obj->logical_index;
|
|
each->level = NM_LEVEL_NUMA;
|
|
each->parent = nullptr;
|
|
nodes.push_back(each);
|
|
printf("libnm: identified NUMA node %d\n", each->id);
|
|
}
|
|
std::sort(nodes.begin(), nodes.end(), nm_obj_comparator);
|
|
|
|
// populate cpus
|
|
obj = nullptr;
|
|
while(1) {
|
|
obj = hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_CORE, obj);
|
|
if (obj == nullptr) {
|
|
break;
|
|
}
|
|
struct nm_obj * each = new struct nm_obj;
|
|
each->id = obj->logical_index;
|
|
each->level = NM_LEVEL_CPU;
|
|
hwloc_obj_t parent = get_parent_type(obj, HWLOC_OBJ_PACKAGE);
|
|
if (parent == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
// XXX: this faults if the OS decides to be stupid
|
|
each->parent = nodes.at(parent->logical_index);
|
|
each->parent->children.push_back(each);
|
|
cpus.push_back(each);
|
|
printf("libnm: identified CPU %d on NUMA node %d\n", each->id, each->parent->id);
|
|
}
|
|
std::sort(cpus.begin(), cpus.end(), nm_obj_comparator);
|
|
|
|
// populate cores
|
|
obj = nullptr;
|
|
while(1) {
|
|
obj = hwloc_get_next_obj_by_type(topo, HWLOC_OBJ_PU, obj);
|
|
if (obj == nullptr) {
|
|
break;
|
|
}
|
|
struct nm_obj * each = new struct nm_obj;
|
|
each->id = obj->logical_index;
|
|
each->level = NM_LEVEL_CORE;
|
|
hwloc_obj_t parent = get_parent_type(obj, HWLOC_OBJ_CORE);
|
|
if (parent == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
// XXX: this faults if the OS decides to be stupid
|
|
each->parent = cpus.at(parent->logical_index);
|
|
each->parent->children.push_back(each);
|
|
cores.push_back(each);
|
|
printf("libnm: identified core %d on CPU %d, NUMA node %d\n", each->id, each->parent->id, each->parent->parent->id);
|
|
}
|
|
std::sort(cores.begin(), cores.end(), nm_obj_comparator);
|
|
|
|
return ret;
|
|
} |