• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_LIBPANDABASE_OS_CPU_AFFINITY_H
17 #define PANDA_LIBPANDABASE_OS_CPU_AFFINITY_H
18 
19 #include "concepts.h"
20 #include "macros.h"
21 #include "os/thread.h"
22 
23 #include <array>
24 #include <limits>
25 
26 #ifdef PANDA_TARGET_UNIX
27 #include "platforms/unix/libpandabase/cpu_affinity.h"
28 #elif defined PANDA_TARGET_WINDOWS
29 #include "platforms/windows/libpandabase/cpu_affinity.h"
30 #else
31 #error "Unsupported platform"
32 #endif
33 
34 namespace ark::os {
35 
36 class CpuSet {
37 public:
38     PANDA_PUBLIC_API CpuSet();
39 
40     NO_COPY_SEMANTIC(CpuSet);
41     NO_MOVE_SEMANTIC(CpuSet);
42 
43     /**
44      * Add cpu into the cpu-set
45      * @param cpu number of cpu
46      */
47     void Set(int cpu);
48 
49     /// Full clear the cpu-set
50     PANDA_PUBLIC_API void Clear();
51 
52     /**
53      * Remove cpu from the cpu-set
54      * @param cpu number of cpu
55      */
56     void Remove(int cpu);
57 
58     /// @return CPUs count in the cpu-set
59     [[nodiscard]] PANDA_PUBLIC_API size_t Count() const;
60 
61     /**
62      * @param cpu number of cpu
63      * @return true if cpu-set has the cpu number, false - otherwise
64      */
65     [[nodiscard]] bool IsSet(int cpu) const;
66 
67     /// @return true if cpu-set has not any cpu
68     [[nodiscard]] PANDA_PUBLIC_API bool IsEmpty() const;
69 
70     ~CpuSet() = default;
71 
72     [[nodiscard]] bool operator==(const CpuSet &other) const;
73     [[nodiscard]] bool operator!=(const CpuSet &other) const;
74 
75     CpuSet &operator&=(const CpuSet &other);
76     CpuSet &operator|=(const CpuSet &other);
77     CpuSet &operator^=(const CpuSet &other);
78 
79     static void And(CpuSet &result, const CpuSet &lhs, const CpuSet &rhs);
80     static void Or(CpuSet &result, const CpuSet &lhs, const CpuSet &rhs);
81     static void Xor(CpuSet &result, const CpuSet &lhs, const CpuSet &rhs);
82     static void Copy(CpuSet &destination, const CpuSet &source);
83 
84 private:
85     [[nodiscard]] CpuSetType *GetData();
86     [[nodiscard]] const CpuSetType *GetData() const;
87 
88     friend class CpuAffinityManager;
89 
90     CpuSetType cpuset_;
91 };
92 
93 // NOLINTNEXTLINE(hicpp-signed-bitwise)
94 enum CpuPower : uint8_t { BEST = 1U, MIDDLE = 1U << 1U, WEAK = 1U << 2U, ANY = 0U, ALL = BEST | MIDDLE | WEAK };
95 
96 class CpuAffinityManager {
97 public:
98     struct CpuInfo {
99         size_t number;
100         uint64_t freq;
101     };
102 
103     CpuAffinityManager() = delete;
104     NO_COPY_SEMANTIC(CpuAffinityManager);
105     NO_MOVE_SEMANTIC(CpuAffinityManager);
106     ~CpuAffinityManager() = default;
107 
108     /// Initialize Cpu Affinity Manager: load CPUs info, indicate CPUs power
109     PANDA_PUBLIC_API static void Initialize();
110 
111     /// @return true if Cpu Affinity Manager was enabled correctly
112     [[nodiscard]] static bool IsCpuAffinityEnabled();
113 
114     /**
115      * Set the thread on specific CPUs
116      * @param tid thread id for setting
117      * @param cpuset cpu-set to indicate used CPU numbers
118      * @return true if setting was successfully, false - otherwise
119      */
120     PANDA_PUBLIC_API static bool SetAffinityForThread(int tid, const CpuSet &cpuset);
121 
122     /**
123      * Set the thread on CPUs with specific flags
124      * @param tid thread id for setting
125      * @param power_flags Flags to indicate CPUs power
126      * @return true if setting was successfully, false - otherwise
127      */
128     PANDA_PUBLIC_API static bool SetAffinityForThread(int tid, uint8_t powerFlags);
129 
130     /**
131      * Set current thread on CPUs with specific flags
132      * @param power_flags Flags to indicate CPUs power
133      * @see CpuPower
134      * @return true if setting was successfully, false - otherwise
135      */
136     PANDA_PUBLIC_API static bool SetAffinityForCurrentThread(uint8_t powerFlags);
137 
138     /**
139      * Set current thread on specific CPUs
140      * @param cpuset cpu-set to indicate used CPU numbers
141      * @see CpuSet
142      * @return true if setting was successfully, false - otherwise
143      */
144     PANDA_PUBLIC_API static bool SetAffinityForCurrentThread(const CpuSet &cpuset);
145 
146     /// @return const reference on best + middle cpu-set in system
GetBestAndMiddleCpuSet()147     PANDA_PUBLIC_API static const CpuSet &GetBestAndMiddleCpuSet()
148     {
149         return bestAndMiddleCpuSet_;
150     }
151 
152     /**
153      * Get cpu affinity for current thread
154      * @param tid thread id for getting
155      * @param cpuset reference for affinity saving
156      * @return true if getting was successfully, false - otherwise
157      */
158     static bool GetThreadAffinity(int tid, CpuSet &cpuset);
159 
160     /**
161      * Get cpu affinity for current thread
162      * @param cpuset reference for affinity saving
163      * @return true if getting was successfully, false - otherwise
164      */
165     PANDA_PUBLIC_API static bool GetCurrentThreadAffinity(CpuSet &cpuset);
166 
167     /**
168      * Get string representation for cpu-set
169      * @tparam StringType type of result string
170      * @param cpuset cpu-set for string representation
171      * @return string with 0 (unused cpu) and 1 (used cpu) for cpu-set representation
172      */
173     template <class StringType = std::string>
CpuSetToString(const CpuSet & cpuset)174     static std::enable_if_t<is_stringable_v<StringType>, StringType> CpuSetToString(const CpuSet &cpuset)
175     {
176         StringType mask(cpuCount_, '0');
177         for (size_t i = 0U; i < cpuCount_; ++i) {
178             if (cpuset.IsSet(i)) {
179                 mask[cpuCount_ - 1 - i] = '1';
180             }
181         }
182         return mask;
183     }
184 
185     /// Finalize Cpu Affinity Manager
186     PANDA_PUBLIC_API static void Finalize();
187 
188 private:
189     /// Load cpu frequency info from system
190     static void LoadCpuFreq();
191 
192     static size_t cpuCount_;
193 
194     static CpuSet bestCpuSet_;
195     static CpuSet middleCpuSet_;
196     PANDA_PUBLIC_API static CpuSet bestAndMiddleCpuSet_;
197     static CpuSet weakCpuSet_;
198 };
199 
200 }  // namespace ark::os
201 
202 #endif  // PANDA_LIBPANDABASE_OS_CPU_AFFINITY_H
203