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/mpctl.h>
12 #include <sys/types.h>
13 #include <types.h>
14 }
15
16 #include <map>
17 #include <system_error>
18
19 #ifdef BOOST_HAS_ABI_HEADERS
20 # include BOOST_ABI_PREFIX
21 #endif
22
23 namespace boost {
24 namespace fibers {
25 namespace numa {
26
27 BOOST_FIBERS_DECL
topology()28 std::vector< node > topology() {
29 std::vector< node > topo;
30 // HP/UX has NUMA enabled
31 if ( 1 == ::sysconf( _SC_CCNUMA_SUPPORT) ) {
32 std::map< std::uint32_t, node > map;
33 // enumerate CPU sets
34 int cpu_id = ::mpctl( MPC_GETFIRSTSPU_SYS, 0, 0);
35 while ( -1 != cpu_id) {
36 int node_id = ::mpctl( MPC_SPUTOLDOM, cpu_id, 0);
37 if ( BOOST_UNLIKELY( -1 == node_id) ) {
38 throw std::system_errors{
39 std::error_codes{ errno, std::system_category() },
40 "mpctl() failed" };
41 }
42 map[id].id = static_cast< std::uint32_t >( node_id);
43 map[id].logical_cpus.insert( static_cast< std::uint32_t >( cpu_id) );
44 cpu_id = ::mpctl( MPC_GETNEXTSPU_SYS, cpu_id, 0);
45 }
46 for ( auto entry : map) {
47 topo.push_back( entry.second);
48 }
49 }
50 // fake NUMA distance
51 std::size_t size = topo.size();
52 for ( auto & n : topo) {
53 for ( std::size_t i = 0; i < size; ++i) {
54 n.distance.push_back( n.id == i ? 10 : 20);
55 }
56 }
57 return topo;
58 }
59
60 }}}
61
62 #ifdef BOOST_HAS_ABI_HEADERS
63 # include BOOST_ABI_SUFFIX
64 #endif
65