| 179 | } |
| 180 | |
| 181 | auto TaskManager::Balance() -> void { |
| 182 | auto current_core = cpu_io::GetCurrentCoreId(); |
| 183 | auto& current_sched = cpu_schedulers_[current_core]; |
| 184 | |
| 185 | // 获取当前核心 kNormal 队列长度(无锁快速检查) |
| 186 | size_t current_load = 0; |
| 187 | if (current_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]) { |
| 188 | current_load = |
| 189 | current_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)] |
| 190 | ->GetQueueSize(); |
| 191 | } |
| 192 | |
| 193 | // 寻找负载最高的核心 |
| 194 | size_t max_load = 0; |
| 195 | size_t max_core = current_core; |
| 196 | |
| 197 | for (size_t core_id = 0; core_id < SIMPLEKERNEL_MAX_CORE_COUNT; ++core_id) { |
| 198 | if (core_id == current_core) { |
| 199 | continue; |
| 200 | } |
| 201 | auto& other_sched = cpu_schedulers_[core_id]; |
| 202 | if (other_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)]) { |
| 203 | size_t load = |
| 204 | other_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)] |
| 205 | ->GetQueueSize(); |
| 206 | if (load > max_load) { |
| 207 | max_load = load; |
| 208 | max_core = core_id; |
| 209 | } |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | // 仅当差值 > 1 时才窃取(避免 ping-pong) |
| 214 | if (max_core == current_core || max_load <= current_load + 1) { |
| 215 | return; |
| 216 | } |
| 217 | |
| 218 | // 按核心 ID 顺序获取锁,防止死锁 |
| 219 | auto& source_sched = cpu_schedulers_[max_core]; |
| 220 | size_t first_core = (current_core < max_core) ? current_core : max_core; |
| 221 | size_t second_core = (current_core < max_core) ? max_core : current_core; |
| 222 | |
| 223 | LockGuard<SpinLock> lock_first(cpu_schedulers_[first_core].lock); |
| 224 | LockGuard<SpinLock> lock_second(cpu_schedulers_[second_core].lock); |
| 225 | |
| 226 | // 重新检查(持锁后条件可能已变化) |
| 227 | auto* source_scheduler = |
| 228 | source_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)].get(); |
| 229 | auto* dest_scheduler = |
| 230 | current_sched.schedulers[static_cast<uint8_t>(SchedPolicy::kNormal)] |
| 231 | .get(); |
| 232 | |
| 233 | if (!source_scheduler || !dest_scheduler) { |
| 234 | return; |
| 235 | } |
| 236 | |
| 237 | size_t source_load = source_scheduler->GetQueueSize(); |
| 238 | size_t dest_load = dest_scheduler->GetQueueSize(); |
nothing calls this directly
no test coverage detected