1
2 // Copyright Oliver Kowalke 2017.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #include "boost/fiber/numa/topology.hpp"
8
9 extern "C" {
10 #include <errno.h>
11 #include <sys/lgrp_user.h>
12 }
13
14 #include <system_error>
15
16 #ifdef BOOST_HAS_ABI_HEADERS
17 # include BOOST_ABI_PREFIX
18 #endif
19
20 namespace {
21
explore(std::vector<boost::fibers::numa::node> & topo,lgrp_cookie_t cookie,lgrp_id_t node)22 void explore( std::vector< boost::fibers::numa::node > & topo, lgrp_cookie_t cookie, lgrp_id_t node) {
23 int size = ::lgrp_cpus( cookie, node, nullptr, 0, LGRP_CONTENT_HIERARCHY);
24 if ( -1 == size) {
25 return;
26 }
27 // is node a NUMA Node?
28 if ( 0 < ::lgrp_mem_size( cookie, node, LGRP_MEM_SZ_INSTALLED, LGRP_CONTENT_DIRECT) ) {
29 std::vector< processorid_t > cpus;
30 cpus.resize( size);
31 ::lgrp_cpus( cookie, node, cpus.data(), size, LGRP_CONTENT_HIERARCHY);
32 boost::fibers::numa::node n;
33 n.id = static_cast< std::uint32_t >( node);
34 for ( auto cpu_id : cpus) {
35 n.logical_cpus.insert( static_cast< std::uint32_t >( cpu_id) );
36 }
37 topo.push_back( n);
38 }
39 size = ::lgrp_children( cookie, node, nullptr, 0);
40 std::vector< lgrp_id_t > nodes;
41 nodes.resize( size);
42 ::lgrp_children( cookie, node, nodes.data(), size);
43 for ( auto node : nodes) {
44 explore( topo, cookie, node);
45 }
46 }
47
48 }
49
50 namespace boost {
51 namespace fibers {
52 namespace numa {
53
54 BOOST_FIBERS_DECL
topology()55 std::vector< node > topology() {
56 std::vector< node > topo;
57 lgrp_cookie_t cookie = ::lgrp_init( LGRP_VIEW_OS);
58 if ( BOOST_UNLIKELY( LGRP_COOKIE_NONE == cookie) ) {
59 throw std::system_error{
60 std::error_code{ errno, std::system_category() },
61 "lprp_init() failed" };
62 }
63 lgrp_id_t root = ::lgrp_root( cookie);
64 explore( topo, cookie, root);
65 ::lgrp_fini( cookie);
66 // fake NUMA distance
67 std::size_t size = topo.size();
68 for ( auto & n : topo) {
69 for ( std::size_t i = 0; i < size; ++i) {
70 n.distance.push_back( n.id == i ? 10 : 20);
71 }
72 }
73 return topo;
74 }
75
76 }}}
77
78 #ifdef BOOST_HAS_ABI_HEADERS
79 # include BOOST_ABI_SUFFIX
80 #endif
81