| 247 | } |
| 248 | |
| 249 | Maybe<void> VirtualMachine::Receive(vm::InstructionList* instruction_list) { |
| 250 | SyncVmModeGuard guard(SyncVmMode::kEnable); |
| 251 | RunMainThreadPendingTasks(); |
| 252 | if (unlikely(pthread_fork::IsForkedSubProcess())) { |
| 253 | INTRUSIVE_FOR_EACH_PTR(instruction, instruction_list) { |
| 254 | const auto& device = instruction->stream().device(); |
| 255 | CHECK_OR_RETURN(device->enum_type() == DeviceType::kCPU) |
| 256 | << pthread_fork::kOfCudaNotSupportInForkedSubProcess; |
| 257 | JUST(instruction->Prepare()); |
| 258 | instruction->Compute(); |
| 259 | } |
| 260 | instruction_list->Clear(); |
| 261 | } else if (unlikely(threads_closed_ || !multi_thread_)) { |
| 262 | JUST(RunInCurrentThread(instruction_list)); |
| 263 | } else { |
| 264 | const int64_t kHighWaterMark = GetInstructionHighWaterMark(); |
| 265 | if (engine_->flying_instruction_cnt() > kHighWaterMark) { |
| 266 | JUST(Singleton<ForeignLockHelper>::Get()->WithScopedRelease([&, this]() -> Maybe<void> { |
| 267 | auto bc = std::make_shared<BlockingCounter>(1); |
| 268 | engine_->InsertProbe([bc](vm::VirtualMachineEngine* engine) { |
| 269 | const int64_t kLowWaterMark = GetInstructionLowWaterMark(); |
| 270 | if (engine->flying_instruction_cnt() > kLowWaterMark) { return false; } |
| 271 | bc->Decrease(); |
| 272 | return true; |
| 273 | }); |
| 274 | pending_notifier_.Notify(); |
| 275 | JUST(bc->WaitUntilCntEqualZero(VirtualMachine::GetPredicatorNoMoreInstructionsFinished())); |
| 276 | return Maybe<void>::Ok(); |
| 277 | })); |
| 278 | } |
| 279 | if (JUST(engine_->Receive(instruction_list))) { |
| 280 | // old scheduler_pending_instruction_list is empty. |
| 281 | pending_notifier_.Notify(); |
| 282 | } |
| 283 | } |
| 284 | return Maybe<void>::Ok(); |
| 285 | } |
| 286 | |
| 287 | Maybe<void> VirtualMachine::NotifyOrRunScheduler() { |
| 288 | if (unlikely(pthread_fork::IsForkedSubProcess() || threads_closed_ || !multi_thread_)) { |
no test coverage detected