| 58 | } |
| 59 | |
| 60 | auto TaskManager::WakeupOne(ResourceId resource_id) -> void { |
| 61 | for (size_t i = 0; i < SIMPLEKERNEL_MAX_CORE_COUNT; ++i) { |
| 62 | auto& cpu_sched = cpu_schedulers_[i]; |
| 63 | LockGuard<SpinLock> lock_guard(cpu_sched.lock); |
| 64 | |
| 65 | auto it = cpu_sched.blocked_tasks.find(resource_id); |
| 66 | if (it == cpu_sched.blocked_tasks.end()) { |
| 67 | continue; |
| 68 | } |
| 69 | |
| 70 | auto& waiting_tasks = it->second; |
| 71 | if (waiting_tasks.empty()) { |
| 72 | continue; |
| 73 | } |
| 74 | |
| 75 | auto* task = waiting_tasks.front(); |
| 76 | waiting_tasks.pop_front(); |
| 77 | |
| 78 | assert(task->GetStatus() == TaskStatus::kBlocked && |
| 79 | "WakeupOne: task status must be kBlocked"); |
| 80 | |
| 81 | task->fsm.Receive(MsgWakeup{}); |
| 82 | task->aux->blocked_on = ResourceId{}; |
| 83 | |
| 84 | auto* scheduler = |
| 85 | cpu_sched.schedulers[static_cast<uint8_t>(task->policy)].get(); |
| 86 | assert(scheduler != nullptr && "WakeupOne: scheduler must not be null"); |
| 87 | scheduler->Enqueue(task); |
| 88 | |
| 89 | if (waiting_tasks.empty()) { |
| 90 | cpu_sched.blocked_tasks.erase(resource_id); |
| 91 | } |
| 92 | |
| 93 | klog::Debug("WakeupOne: Woke task pid={} from resource={}, data={:#x}", |
| 94 | task->pid, resource_id.GetTypeName(), |
| 95 | static_cast<uint64_t>(resource_id.GetData())); |
| 96 | return; // Only wake one |
| 97 | } |
| 98 | |
| 99 | klog::Debug("WakeupOne: No tasks waiting on resource={}, data={:#x}", |
| 100 | resource_id.GetTypeName(), |
| 101 | static_cast<uint64_t>(resource_id.GetData())); |
| 102 | } |