#include "stdafx.h" #include "cpu_affinity.h" #if defined(__FreeBSD__) && (__FreeBSD__ >= 7) #include #include #elif defined(_linux_) #include #include #include #endif namespace NNetliba { class TCPUSet { public: static constexpr int MAX_SIZE = 128; private: #if defined(__FreeBSD__) && (__FreeBSD__ >= 7) #define NUMCPU ((CPU_MAXSIZE > MAX_SIZE) ? 1 : (MAX_SIZE / CPU_MAXSIZE)) cpuset_t CpuInfo[NUMCPU]; public: bool GetAffinity() { int error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(CpuInfo), CpuInfo); return error == 0; } bool SetAffinity() { int error = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(CpuInfo), CpuInfo); return error == 0; } bool IsSet(size_t i) { return CPU_ISSET(i, CpuInfo); } void Set(size_t i) { CPU_SET(i, CpuInfo); } #elif defined(_linux_) && !defined(__ANDROID__) public: #define NUMCPU ((CPU_SETSIZE > MAX_SIZE) ? 1 : (MAX_SIZE / CPU_SETSIZE)) cpu_set_t CpuInfo[NUMCPU]; public: bool GetAffinity() { int error = pthread_getaffinity_np(pthread_self(), sizeof(CpuInfo), CpuInfo); return error == 0; } bool SetAffinity() { int error = pthread_setaffinity_np(pthread_self(), sizeof(CpuInfo), CpuInfo); return error == 0; } bool IsSet(size_t i) { return CPU_ISSET(i, CpuInfo); } void Set(size_t i) { CPU_SET(i, CpuInfo); } #else public: bool GetAffinity() { return true; } bool SetAffinity() { return true; } bool IsSet(size_t i) { Y_UNUSED(i); return true; } void Set(size_t i) { Y_UNUSED(i); } #endif TCPUSet() { Clear(); } void Clear() { memset(this, 0, sizeof(*this)); } }; static TMutex CPUSetsLock; struct TCPUSetInfo { TCPUSet CPUSet; bool IsOk; TCPUSetInfo() : IsOk(false) { } }; static THashMap CPUSets; void BindToSocket(int n) { TGuard gg(CPUSetsLock); if (CPUSets.find(n) == CPUSets.end()) { TCPUSetInfo& res = CPUSets[n]; bool foundCPU = false; #ifdef _linux_ for (int cpuId = 0; cpuId < TCPUSet::MAX_SIZE; ++cpuId) { try { // I just wanna check if file exists, I don't want your stinking exceptions :/ TIFStream f(Sprintf("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpuId).c_str()); TString s; if (f.ReadLine(s) && !s.empty()) { //printf("cpu%d - %s\n", cpuId, s.c_str()); int physCPU = atoi(s.c_str()); if (physCPU == 0) { res.IsOk = true; res.CPUSet.Set(cpuId); foundCPU = true; } } else { break; } } catch (const TFileError&) { break; } } #endif if (!foundCPU && n == 0) { for (int i = 0; i < 6; ++i) { res.CPUSet.Set(i); } res.IsOk = true; foundCPU = true; } } { TCPUSetInfo& cc = CPUSets[n]; if (cc.IsOk) { cc.CPUSet.SetAffinity(); } } } }