aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/netliba/v6/cpu_affinity.cpp
blob: 55b4c98b71345253d2bb53b333ab3df7fb0bbc58 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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:
        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_)
    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();
            }
        }
    }

}