1 //===------------ TaskDispatch.cpp - ORC task dispatch utils --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" 10 #include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_THREADS 11 #include "llvm/ExecutionEngine/Orc/Core.h" 12 13 namespace llvm { 14 namespace orc { 15 16 char Task::ID = 0; 17 char GenericNamedTask::ID = 0; 18 const char *GenericNamedTask::DefaultDescription = "Generic Task"; 19 20 void Task::anchor() {} 21 TaskDispatcher::~TaskDispatcher() = default; 22 23 void InPlaceTaskDispatcher::dispatch(std::unique_ptr<Task> T) { T->run(); } 24 25 void InPlaceTaskDispatcher::shutdown() {} 26 27 #if LLVM_ENABLE_THREADS 28 void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) { 29 bool IsMaterializationTask = isa<MaterializationTask>(*T); 30 31 { 32 std::lock_guard<std::mutex> Lock(DispatchMutex); 33 34 // Reject new tasks if they're dispatched after a call to shutdown. 35 if (Shutdown) 36 return; 37 38 if (IsMaterializationTask) { 39 40 // If this is a materialization task and there are too many running 41 // already then queue this one up and return early. 42 if (MaxMaterializationThreads && 43 NumMaterializationThreads == *MaxMaterializationThreads) { 44 MaterializationTaskQueue.push_back(std::move(T)); 45 return; 46 } 47 48 // Otherwise record that we have a materialization task running. 49 ++NumMaterializationThreads; 50 } 51 52 ++Outstanding; 53 } 54 55 std::thread([this, T = std::move(T), IsMaterializationTask]() mutable { 56 while (true) { 57 58 // Run the task. 59 T->run(); 60 61 // Reset the task to free any resources. We need this to happen *before* 62 // we notify anyone (via Outstanding) that this thread is done to ensure 63 // that we don't proceed with JIT shutdown while still holding resources. 64 // (E.g. this was causing "Dangling SymbolStringPtr" assertions). 65 T.reset(); 66 67 // Check the work queue state and either proceed with the next task or 68 // end this thread. 69 std::lock_guard<std::mutex> Lock(DispatchMutex); 70 if (!MaterializationTaskQueue.empty()) { 71 // If there are any materialization tasks running then steal that work. 72 T = std::move(MaterializationTaskQueue.front()); 73 MaterializationTaskQueue.pop_front(); 74 if (!IsMaterializationTask) { 75 ++NumMaterializationThreads; 76 IsMaterializationTask = true; 77 } 78 } else { 79 if (IsMaterializationTask) 80 --NumMaterializationThreads; 81 --Outstanding; 82 if (Outstanding == 0) 83 OutstandingCV.notify_all(); 84 return; 85 } 86 } 87 }).detach(); 88 } 89 90 void DynamicThreadPoolTaskDispatcher::shutdown() { 91 std::unique_lock<std::mutex> Lock(DispatchMutex); 92 Shutdown = true; 93 OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; }); 94 } 95 #endif 96 97 } // namespace orc 98 } // namespace llvm 99