#include "ThreadPinning.hpp" #include #include #include #include #include #if defined(__linux__) || defined(__ANDROID__) #include #define TP_THREAD_PINNING_SUPPORTED #endif namespace tp { namespace { std::vector parseCpuList(const std::string& text) { std::vector cpus; std::stringstream stream(text); std::string range; while (std::getline(stream, range, ',')) { if (range.empty()) continue; const size_t dash = range.find('-'); if (dash == std::string::npos) { cpus.push_back(std::stoi(range)); continue; } const int first = std::stoi(range.substr(0, dash)); const std::string tail = range.substr(dash + 1); const int last = tail.empty() ? first : std::stoi(tail); for (int cpu = first; cpu <= last; cpu++) cpus.push_back(cpu); } return cpus; } std::vector siblingsOf(int cpu) { std::ifstream file("/sys/devices/system/cpu/cpu" + std::to_string(cpu) + "/topology/thread_siblings_list"); std::string text; if (!file || !std::getline(file, text)) return { cpu }; const std::vector siblings = parseCpuList(text); return siblings.empty() ? std::vector{ cpu } : siblings; } } std::vector ThreadPinning::allowedCpus() { #ifdef TP_THREAD_PINNING_SUPPORTED cpu_set_t set; CPU_ZERO(&set); if (sched_getaffinity(0, sizeof(set), &set) != 0) return {}; std::vector cpus; for (int cpu = 0; cpu < CPU_SETSIZE; cpu++) if (CPU_ISSET(cpu, &set)) cpus.push_back(cpu); return cpus; #else return {}; #endif } std::vector> ThreadPinning::siblingGroups(const std::vector& allowed) { const std::vector cpus = allowed.empty() ? allowedCpus() : allowed; std::vector> groups; std::set seen; for (int cpu : cpus) { if (seen.count(cpu)) continue; std::vector group; for (int sibling : siblingsOf(cpu)) { if (!std::count(cpus.begin(), cpus.end(), sibling)) continue; group.push_back(sibling); seen.insert(sibling); } if (group.empty()) group.push_back(cpu); groups.push_back(group); } return groups; } void ThreadPinning::pinCallingThread(const std::vector& cpus) { #ifdef TP_THREAD_PINNING_SUPPORTED if (cpus.empty()) return; cpu_set_t set; CPU_ZERO(&set); for (int cpu : cpus) CPU_SET(cpu, &set); sched_setaffinity(0, sizeof(set), &set); #endif } }