LLVM 20.0.0git
TaskDispatch.cpp
Go to the documentation of this file.
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
10#include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_THREADS
12
13namespace llvm {
14namespace orc {
15
16char Task::ID = 0;
18char IdleTask::ID = 0;
19
20const char *GenericNamedTask::DefaultDescription = "Generic Task";
21
22void Task::anchor() {}
23void IdleTask::anchor() {}
24
26
27void InPlaceTaskDispatcher::dispatch(std::unique_ptr<Task> T) { T->run(); }
28
30
31#if LLVM_ENABLE_THREADS
32void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) {
33
34 enum { Normal, Materialization, Idle } TaskKind;
35
36 if (isa<MaterializationTask>(*T))
37 TaskKind = Materialization;
38 else if (isa<IdleTask>(*T))
39 TaskKind = Idle;
40 else
41 TaskKind = Normal;
42
43 {
44 std::lock_guard<std::mutex> Lock(DispatchMutex);
45
46 // Reject new tasks if they're dispatched after a call to shutdown.
47 if (Shutdown)
48 return;
49
50 if (TaskKind == Materialization) {
51
52 // If this is a materialization task and there are too many running
53 // already then queue this one up and return early.
54 if (!canRunMaterializationTaskNow())
55 return MaterializationTaskQueue.push_back(std::move(T));
56
57 // Otherwise record that we have a materialization task running.
58 ++NumMaterializationThreads;
59 } else if (TaskKind == Idle) {
60 if (!canRunIdleTaskNow())
61 return IdleTaskQueue.push_back(std::move(T));
62 }
63
64 ++Outstanding;
65 }
66
67 std::thread([this, T = std::move(T), TaskKind]() mutable {
68 while (true) {
69
70 // Run the task.
71 T->run();
72
73 // Reset the task to free any resources. We need this to happen *before*
74 // we notify anyone (via Outstanding) that this thread is done to ensure
75 // that we don't proceed with JIT shutdown while still holding resources.
76 // (E.g. this was causing "Dangling SymbolStringPtr" assertions).
77 T.reset();
78
79 // Check the work queue state and either proceed with the next task or
80 // end this thread.
81 std::lock_guard<std::mutex> Lock(DispatchMutex);
82
83 if (TaskKind == Materialization)
84 --NumMaterializationThreads;
85 --Outstanding;
86
87 if (!MaterializationTaskQueue.empty() && canRunMaterializationTaskNow()) {
88 // If there are any materialization tasks running then steal that work.
89 T = std::move(MaterializationTaskQueue.front());
90 MaterializationTaskQueue.pop_front();
91 TaskKind = Materialization;
92 ++NumMaterializationThreads;
93 ++Outstanding;
94 } else if (!IdleTaskQueue.empty() && canRunIdleTaskNow()) {
95 T = std::move(IdleTaskQueue.front());
96 IdleTaskQueue.pop_front();
97 TaskKind = Idle;
98 ++Outstanding;
99 } else {
100 if (Outstanding == 0)
101 OutstandingCV.notify_all();
102 return;
103 }
104 }
105 }).detach();
106}
107
108void DynamicThreadPoolTaskDispatcher::shutdown() {
109 std::unique_lock<std::mutex> Lock(DispatchMutex);
110 Shutdown = true;
111 OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
112}
113
114bool DynamicThreadPoolTaskDispatcher::canRunMaterializationTaskNow() {
115 return !MaxMaterializationThreads ||
116 (NumMaterializationThreads < *MaxMaterializationThreads);
117}
118
119bool DynamicThreadPoolTaskDispatcher::canRunIdleTaskNow() {
120 return !MaxMaterializationThreads ||
121 (Outstanding < *MaxMaterializationThreads);
122}
123
124#endif
125
126} // namespace orc
127} // namespace llvm
static const char * DefaultDescription
Definition: TaskDispatch.h:55
void shutdown() override
Called by ExecutionSession. Waits until all tasks have completed.
void dispatch(std::unique_ptr< Task > T) override
Run the given task.
static char ID
Definition: TaskDispatch.h:37
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18