1349cc55cSDimitry Andric //===------------ TaskDispatch.cpp - ORC task dispatch utils --------------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric 9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" 10*0fca6ea1SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h" 11349cc55cSDimitry Andric 12349cc55cSDimitry Andric namespace llvm { 13349cc55cSDimitry Andric namespace orc { 14349cc55cSDimitry Andric 15349cc55cSDimitry Andric char Task::ID = 0; 16349cc55cSDimitry Andric char GenericNamedTask::ID = 0; 17349cc55cSDimitry Andric const char *GenericNamedTask::DefaultDescription = "Generic Task"; 18349cc55cSDimitry Andric 19349cc55cSDimitry Andric void Task::anchor() {} 2081ad6265SDimitry Andric TaskDispatcher::~TaskDispatcher() = default; 21349cc55cSDimitry Andric 22349cc55cSDimitry Andric void InPlaceTaskDispatcher::dispatch(std::unique_ptr<Task> T) { T->run(); } 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric void InPlaceTaskDispatcher::shutdown() {} 25349cc55cSDimitry Andric 26349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 27349cc55cSDimitry Andric void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) { 28*0fca6ea1SDimitry Andric bool IsMaterializationTask = isa<MaterializationTask>(*T); 29*0fca6ea1SDimitry Andric 30349cc55cSDimitry Andric { 31349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex); 32*0fca6ea1SDimitry Andric 33*0fca6ea1SDimitry Andric if (IsMaterializationTask) { 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric // If this is a materialization task and there are too many running 36*0fca6ea1SDimitry Andric // already then queue this one up and return early. 37*0fca6ea1SDimitry Andric if (MaxMaterializationThreads && 38*0fca6ea1SDimitry Andric NumMaterializationThreads == *MaxMaterializationThreads) { 39*0fca6ea1SDimitry Andric MaterializationTaskQueue.push_back(std::move(T)); 40*0fca6ea1SDimitry Andric return; 41*0fca6ea1SDimitry Andric } 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric // Otherwise record that we have a materialization task running. 44*0fca6ea1SDimitry Andric ++NumMaterializationThreads; 45*0fca6ea1SDimitry Andric } 46*0fca6ea1SDimitry Andric 47349cc55cSDimitry Andric ++Outstanding; 48349cc55cSDimitry Andric } 49349cc55cSDimitry Andric 50*0fca6ea1SDimitry Andric std::thread([this, T = std::move(T), IsMaterializationTask]() mutable { 51*0fca6ea1SDimitry Andric while (true) { 52*0fca6ea1SDimitry Andric 53*0fca6ea1SDimitry Andric // Run the task. 54349cc55cSDimitry Andric T->run(); 55*0fca6ea1SDimitry Andric 56349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex); 57*0fca6ea1SDimitry Andric if (!MaterializationTaskQueue.empty()) { 58*0fca6ea1SDimitry Andric // If there are any materialization tasks running then steal that work. 59*0fca6ea1SDimitry Andric T = std::move(MaterializationTaskQueue.front()); 60*0fca6ea1SDimitry Andric MaterializationTaskQueue.pop_front(); 61*0fca6ea1SDimitry Andric if (!IsMaterializationTask) { 62*0fca6ea1SDimitry Andric ++NumMaterializationThreads; 63*0fca6ea1SDimitry Andric IsMaterializationTask = true; 64*0fca6ea1SDimitry Andric } 65*0fca6ea1SDimitry Andric } else { 66*0fca6ea1SDimitry Andric // Otherwise decrement work counters. 67*0fca6ea1SDimitry Andric if (IsMaterializationTask) 68*0fca6ea1SDimitry Andric --NumMaterializationThreads; 69349cc55cSDimitry Andric --Outstanding; 70349cc55cSDimitry Andric OutstandingCV.notify_all(); 71*0fca6ea1SDimitry Andric return; 72*0fca6ea1SDimitry Andric } 73*0fca6ea1SDimitry Andric } 74349cc55cSDimitry Andric }).detach(); 75349cc55cSDimitry Andric } 76349cc55cSDimitry Andric 77349cc55cSDimitry Andric void DynamicThreadPoolTaskDispatcher::shutdown() { 78349cc55cSDimitry Andric std::unique_lock<std::mutex> Lock(DispatchMutex); 79349cc55cSDimitry Andric Running = false; 80349cc55cSDimitry Andric OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; }); 81349cc55cSDimitry Andric } 82349cc55cSDimitry Andric #endif 83349cc55cSDimitry Andric 84349cc55cSDimitry Andric } // namespace orc 85349cc55cSDimitry Andric } // namespace llvm 86