bool LoopManager::Break(ScriptExecutionState* state, COMMAND_ARGS) { if (!m_loops.size()) return false; LoopInfo* loopInfo = &m_loops.top(); RestoreStack(state, &loopInfo->ipInfo); opcodeOffsetPtr[kDataDeltaStackOffset] += loopInfo->endIP - (*opcodeOffsetPtr); delete loopInfo->loop; m_loops.pop(); return true; }
bool LoopManager::Continue(ScriptExecutionState* state, COMMAND_ARGS) { if (!m_loops.size()) return false; LoopInfo* loopInfo = &m_loops.top(); if (!loopInfo->loop->Update(PASS_COMMAND_ARGS)) { Break(state, PASS_COMMAND_ARGS); return true; } RestoreStack(state, &loopInfo->ipInfo); opcodeOffsetPtr[kDataDeltaStackOffset] += loopInfo->ipInfo.ip - (*opcodeOffsetPtr); return true; }
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; }
CBotStack* CBotStack::RestoreStackEOX(CBotCall* instr) { CBotStack* p = RestoreStack(); p->m_call = instr; return p; }