aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/netliba/v6/cpu_affinity.cpp
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /library/cpp/netliba/v6/cpu_affinity.cpp
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'library/cpp/netliba/v6/cpu_affinity.cpp')
-rw-r--r--library/cpp/netliba/v6/cpu_affinity.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/library/cpp/netliba/v6/cpu_affinity.cpp b/library/cpp/netliba/v6/cpu_affinity.cpp
new file mode 100644
index 0000000000..7808092a72
--- /dev/null
+++ b/library/cpp/netliba/v6/cpu_affinity.cpp
@@ -0,0 +1,138 @@
+#include "stdafx.h"
+#include "cpu_affinity.h"
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 7)
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#elif defined(_linux_)
+#include <pthread.h>
+#include <util/stream/file.h>
+#include <util/string/printf.h>
+#endif
+
+namespace NNetliba {
+ class TCPUSet {
+ public:
+ enum { 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_)
+ 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<int, TCPUSetInfo> CPUSets;
+
+ void BindToSocket(int n) {
+ TGuard<TMutex> 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();
+ }
+ }
+ }
+
+}