xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 Andric void Task::anchor() {}
20145449b1SDimitry Andric TaskDispatcher::~TaskDispatcher() = default;
21c0981da4SDimitry Andric 
dispatch(std::unique_ptr<Task> T)22c0981da4SDimitry Andric void InPlaceTaskDispatcher::dispatch(std::unique_ptr<Task> T) { T->run(); }
23c0981da4SDimitry Andric 
shutdown()24c0981da4SDimitry Andric void InPlaceTaskDispatcher::shutdown() {}
25c0981da4SDimitry Andric 
26c0981da4SDimitry Andric #if LLVM_ENABLE_THREADS
dispatch(std::unique_ptr<Task> T)27c0981da4SDimitry Andric void 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 Andric void 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