4 #include "Mu2e-STMDAQ/utils/async_logger.hh"
5 #include "Mu2e-STMDAQ/utils/cpu_utils.hh"
8 std::shared_ptr<cpu_utils> cpu_utils::instance =
nullptr;
9 std::once_flag cpu_utils::init_flag;
12 const std::vector<int> cpu_utils::socket0_cores = {
13 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
16 const std::vector<int> cpu_utils::socket1_cores = {24, 25, 26, 27, 28, 29, 30, 31,
17 32, 33, 34, 35, 36, 37, 38, 39,
18 40, 41, 42, 43, 44, 45, 46, 47};
21 void cpu_utils::log(
const std::string& msg,
int level)
23 std::lock_guard<std::mutex> lock(log_mutex);
25 logger->log(msg, level);
27 pending_logs.emplace_back(msg, level);
30 void cpu_utils::set_logger(std::shared_ptr<AsyncLogger> l)
32 std::lock_guard<std::mutex> lock(log_mutex);
34 for(
const auto& [msg, level] : pending_logs)
35 logger->log(msg, level);
40 std::shared_ptr<cpu_utils> cpu_utils::getInstance(
const Config& cfg, CpuRole role)
42 std::call_once(init_flag, [&]() {
43 instance = std::shared_ptr<cpu_utils>(
new cpu_utils(cfg, role));
50 cpu_utils::cpu_utils(
const Config& cfg_, CpuRole role_)
51 : cfg(cfg_), role(role_), next_core_id(0)
54 max_cores = std::thread::hardware_concurrency();
61 if(role == CpuRole::Standalone)
64 EnvVars::expand(
"${HOSTNAME}") == cfg.getValue<std::string>(
"stm.ch0_host")
67 starting_core_id = cfg.getValue<
int>(
"stm.stmdaq_starting_core");
72 EnvVars::expand(
"${HOSTNAME}") == cfg.getValue<std::string>(
"stm.ch0_host")
75 starting_core_id = cfg.getValue<
int>(
"stm.artdaq_starting_core");
78 allowed_cores = socket_id == 0 ? socket0_cores : socket1_cores;
82 std::string role_name = role == CpuRole::Standalone ?
"Standalone" :
"ArtDAQ";
83 log(
"CPU utils initialised: Role: " + role_name +
84 ", Socket: " + std::to_string(socket_id) +
85 ", Starting core offset: " + std::to_string(starting_core_id) +
86 ", Managed cores: " + std::to_string(allowed_cores.size()),
91 size_t cpu_utils::get_next_core(
const std::string& name)
94 const size_t local_id = next_core_id.fetch_add(1);
95 const size_t logical_core = (starting_core_id + local_id) % allowed_cores.size();
96 const size_t core_id = allowed_cores[logical_core];
100 std::lock_guard<std::mutex> lock(tracking_mutex);
103 if(used_cores.find(core_id) != used_cores.end())
105 log(
"CPU utils: Warning! Core " + std::to_string(core_id) +
106 " has already been assigned.",
111 used_cores.insert(core_id);
115 if(used_cores.size() > allowed_cores.size())
117 log(
"CPU utils: Warning! Thread count exceeds available cores on socket.", 2);
122 pin_thread_to_core(core_id, name);
128 void cpu_utils::pin_thread_to_core(
size_t core_id,
const std::string& name)
135 CPU_SET(core_id, &cpuset);
138 const int result = pthread_setaffinity_np(pthread_self(),
sizeof(cpu_set_t), &cpuset);
143 log(
"CPU utils: Error! Failed to pin " + name +
" to core " +
144 std::to_string(core_id) +
" (errno " + std::to_string(result) +
")",
149 log(
"CPU utils: Pinned " + name +
" to core " + std::to_string(core_id), 1);