1c0981da4SDimitry Andric //===------------ TaskDispatch.cpp - ORC task dispatch utils --------------===// 2c0981da4SDimitry Andric // 3c0981da4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c0981da4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5c0981da4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c0981da4SDimitry Andric // 7c0981da4SDimitry Andric //===----------------------------------------------------------------------===// 8c0981da4SDimitry Andric 9c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" 10ac9a064cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h" 11c0981da4SDimitry Andric 12c0981da4SDimitry Andric namespace llvm { 13c0981da4SDimitry Andric namespace orc { 14c0981da4SDimitry Andric 15c0981da4SDimitry Andric char Task::ID = 0; 16c0981da4SDimitry Andric char GenericNamedTask::ID = 0; 17c0981da4SDimitry Andric const char *GenericNamedTask::DefaultDescription = "Generic Task"; 18c0981da4SDimitry Andric anchor()19c0981da4SDimitry Andricvoid Task::anchor() {} 20145449b1SDimitry Andric TaskDispatcher::~TaskDispatcher() = default; 21c0981da4SDimitry Andric dispatch(std::unique_ptr<Task> T)22c0981da4SDimitry Andricvoid InPlaceTaskDispatcher::dispatch(std::unique_ptr<Task> T) { T->run(); } 23c0981da4SDimitry Andric shutdown()24c0981da4SDimitry Andricvoid InPlaceTaskDispatcher::shutdown() {} 25c0981da4SDimitry Andric 26c0981da4SDimitry Andric #if LLVM_ENABLE_THREADS dispatch(std::unique_ptr<Task> T)27c0981da4SDimitry Andricvoid DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) { 28ac9a064cSDimitry Andric bool IsMaterializationTask = isa<MaterializationTask>(*T); 29ac9a064cSDimitry Andric 30c0981da4SDimitry Andric { 31c0981da4SDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex); 32ac9a064cSDimitry Andric 33ac9a064cSDimitry Andric if (IsMaterializationTask) { 34ac9a064cSDimitry Andric 35ac9a064cSDimitry Andric // If this is a materialization task and there are too many running 36ac9a064cSDimitry Andric // already then queue this one up and return early. 37ac9a064cSDimitry Andric if (MaxMaterializationThreads && 38ac9a064cSDimitry Andric NumMaterializationThreads == *MaxMaterializationThreads) { 39ac9a064cSDimitry Andric MaterializationTaskQueue.push_back(std::move(T)); 40ac9a064cSDimitry Andric return; 41ac9a064cSDimitry Andric } 42ac9a064cSDimitry Andric 43ac9a064cSDimitry Andric // Otherwise record that we have a materialization task running. 44ac9a064cSDimitry Andric ++NumMaterializationThreads; 45ac9a064cSDimitry Andric } 46ac9a064cSDimitry Andric 47c0981da4SDimitry Andric ++Outstanding; 48c0981da4SDimitry Andric } 49c0981da4SDimitry Andric 50ac9a064cSDimitry Andric std::thread([this, T = std::move(T), IsMaterializationTask]() mutable { 51ac9a064cSDimitry Andric while (true) { 52ac9a064cSDimitry Andric 53ac9a064cSDimitry Andric // Run the task. 54c0981da4SDimitry Andric T->run(); 55ac9a064cSDimitry Andric 56c0981da4SDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex); 57ac9a064cSDimitry Andric if (!MaterializationTaskQueue.empty()) { 58ac9a064cSDimitry Andric // If there are any materialization tasks running then steal that work. 59ac9a064cSDimitry Andric T = std::move(MaterializationTaskQueue.front()); 60ac9a064cSDimitry Andric MaterializationTaskQueue.pop_front(); 61ac9a064cSDimitry Andric if (!IsMaterializationTask) { 62ac9a064cSDimitry Andric ++NumMaterializationThreads; 63ac9a064cSDimitry Andric IsMaterializationTask = true; 64ac9a064cSDimitry Andric } 65ac9a064cSDimitry Andric } else { 66ac9a064cSDimitry Andric // Otherwise decrement work counters. 67ac9a064cSDimitry Andric if (IsMaterializationTask) 68ac9a064cSDimitry Andric --NumMaterializationThreads; 69c0981da4SDimitry Andric --Outstanding; 70c0981da4SDimitry Andric OutstandingCV.notify_all(); 71ac9a064cSDimitry Andric return; 72ac9a064cSDimitry Andric } 73ac9a064cSDimitry Andric } 74c0981da4SDimitry Andric }).detach(); 75c0981da4SDimitry Andric } 76c0981da4SDimitry Andric shutdown()77c0981da4SDimitry Andricvoid DynamicThreadPoolTaskDispatcher::shutdown() { 78c0981da4SDimitry Andric std::unique_lock<std::mutex> Lock(DispatchMutex); 79c0981da4SDimitry Andric Running = false; 80c0981da4SDimitry Andric OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; }); 81c0981da4SDimitry Andric } 82c0981da4SDimitry Andric #endif 83c0981da4SDimitry Andric 84c0981da4SDimitry Andric } // namespace orc 85c0981da4SDimitry Andric } // namespace llvm 86