uint32_t Scheduler::Run() { ThreadLocalInfo& info = GetLocalInfo(); info.current_task = NULL; uint32_t do_max_count = runnale_task_count_; uint32_t do_count = 0; Debug("Run --------------------------"); // 每次Run执行的协程数量不能多于当前runnable协程数量 // 以防wait状态的协程得不到执行。 while (do_count < do_max_count) { uint32_t cnt = std::max((uint32_t)1, std::min( do_max_count / GetOptions().chunk_count, GetOptions().max_chunk_size)); Debug("want pop %u tasks.", cnt); SList<Task> slist = run_task_.pop(cnt); Debug("really pop %u tasks.", cnt); if (slist.empty()) break; SList<Task>::iterator it = slist.begin(); while (it != slist.end()) { Task* tk = &*it; info.current_task = tk; Debug("enter task(%llu)", tk->id_); swapcontext(&info.scheduler, &tk->ctx_); ++do_count; Debug("exit task(%llu) state=%d", tk->id_, tk->state_); info.current_task = NULL; switch (tk->state_) { case TaskState::runnable: ++it; break; case TaskState::io_block: case TaskState::sync_block: --runnale_task_count_; it = slist.erase(it); wait_task_.push(tk); break; case TaskState::done: default: --task_count_; --runnale_task_count_; it = slist.erase(it); delete tk; break; } } Debug("push %d task return to runnable list", slist.size()); run_task_.push(slist); } static thread_local epoll_event evs[1024]; int n = epoll_wait(epoll_fd, evs, 1024, 1); Debug("do_count=%u, do epoll event, n = %d", do_count, n); for (int i = 0; i < n; ++i) { Task* tk = (Task*)evs[i].data.ptr; if (tk->unlink()) AddTask(tk); } return do_count; }
uint32_t Processer::Run(ThreadLocalInfo &info, uint32_t &done_count) { info.current_task = NULL; done_count = 0; uint32_t c = 0; SList<Task> slist = runnable_list_.pop_all(); uint32_t do_count = slist.size(); DebugPrint(dbg_scheduler, "Run [Proc(%d) do_count:%u] --------------------------", id_, do_count); SList<Task>::iterator it = slist.begin(); for (; it != slist.end(); ++c) { Task* tk = &*it; info.current_task = tk; tk->state_ = TaskState::runnable; DebugPrint(dbg_switch, "enter task(%s)", tk->DebugInfo()); RestoreStack(tk); int ret = swapcontext(&info.scheduler, &tk->ctx_); if (ret) { fprintf(stderr, "swapcontext error:%s\n", strerror(errno)); runnable_list_.push(tk); ThrowError(eCoErrorCode::ec_swapcontext_failed); } DebugPrint(dbg_switch, "leave task(%s) state=%d", tk->DebugInfo(), tk->state_); info.current_task = NULL; switch (tk->state_) { case TaskState::runnable: ++it; break; case TaskState::io_block: it = slist.erase(it); g_Scheduler.io_wait_.SchedulerSwitch(tk); break; case TaskState::sleep: it = slist.erase(it); g_Scheduler.sleep_wait_.SchedulerSwitch(tk); break; case TaskState::sys_block: case TaskState::user_block: { if (tk->block_) { it = slist.erase(it); if (!tk->block_->AddWaitTask(tk)) runnable_list_.push(tk); tk->block_ = NULL; } else { std::unique_lock<LFLock> lock(g_Scheduler.user_wait_lock_); auto &zone = g_Scheduler.user_wait_tasks_[tk->user_wait_type_]; auto &wait_pair = zone[tk->user_wait_id_]; auto &task_queue = wait_pair.second; if (wait_pair.first) { --wait_pair.first; tk->state_ = TaskState::runnable; ++it; } else { it = slist.erase(it); task_queue.push(tk); } g_Scheduler.ClearWaitPairWithoutLock(tk->user_wait_type_, tk->user_wait_id_, zone, wait_pair); } } break; case TaskState::done: default: --task_count_; ++done_count; it = slist.erase(it); DebugPrint(dbg_task, "task(%s) done.", tk->DebugInfo()); if (tk->eptr_) { std::exception_ptr ep = tk->eptr_; runnable_list_.push(slist); tk->DecrementRef(); std::rethrow_exception(ep); } else tk->DecrementRef(); break; } } if (do_count) runnable_list_.push(slist); return c; }