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