Skip to content

Commit 3af5c37

Browse files
committed
[OrcJIT] distinguish normal and abrupt TaskDispatcher shutdown
Add a `run_to_complete` complement to `shutdown`, which does nearly the same operations, but does not cancel future / pending work. The distinction is often mainly academic, but split for clarity of intent of each caller. Annotate each and every tests that assumes that any previously scheduled tasks have finished running with a call of `run_to_completion` before reading the variables written by those tasks. This more clearly emphasizes the expectations of each of these tests and makes them robust against data-races or changes to the default scheduler. These should have no impact currently, but have been tested and shown to pass with a scheduler which defers all work (as if being run on a thread) until an explicit synchronization point "acquires" that state, demonstrating that this is each and every test that would be affected by changes to the default scheduler.
1 parent f3a29bd commit 3af5c37

File tree

6 files changed

+80
-67
lines changed

6 files changed

+80
-67
lines changed

llvm/include/llvm/ExecutionEngine/Orc/TaskDispatch.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,14 @@ class LLVM_ABI TaskDispatcher {
134134
dispatch(std::move(T));
135135
}
136136

137-
/// Called by ExecutionSession. Waits until all tasks have completed.
138-
virtual void shutdown() = 0;
137+
/// The TaskDispatcher may be reused immediatly afterwards.
138+
void run_to_complete() { run(false); }
139+
140+
/// Called by ExecutionSession. Halts all in-progress work as soon as
141+
/// possible. May cause deadlocks since promises will not be set, so this
142+
/// should only be used immediately before exiting.
143+
/// The TaskDispatcher should not be reused afterwards.
144+
void shutdown() { run(true); }
139145

140146
protected:
141147
friend class future_base;
@@ -147,6 +153,9 @@ class LLVM_ABI TaskDispatcher {
147153
/// Notify all task dispatchers that a future with have_waiter became ready
148154
LLVM_ABI static void notifyWaiters();
149155

156+
/// Called by ExecutionSession. Waits until all tasks have completed.
157+
virtual void run(bool cancel) = 0;
158+
150159
#if LLVM_ENABLE_THREADS
151160
/// Shared synchronization primitives for all dispatchers
152161
static std::mutex DispatchMutex;
@@ -163,9 +172,9 @@ class LLVM_ABI InPlaceTaskDispatcher : public TaskDispatcher {
163172
public:
164173
void dispatch(std::unique_ptr<Task> T) override;
165174
void dispatch_elsewhere(std::unique_ptr<Task> T) override;
166-
void shutdown() override;
167175

168176
private:
177+
void run(bool cancel) override;
169178
void work_until(future_base &F) override;
170179

171180
/// C++ does not support non-static thread_local variables, so this needs to
@@ -188,9 +197,9 @@ class LLVM_ABI DynamicThreadPoolTaskDispatcher : public TaskDispatcher {
188197
: MaxMaterializationThreads(MaxMaterializationThreads) {}
189198

190199
void dispatch(std::unique_ptr<Task> T) override;
191-
void shutdown() override;
192200

193201
private:
202+
void run(bool cancel) override;
194203
void work_until(future_base &F) override;
195204
bool canRunMaterializationTaskNow();
196205
bool canRunIdleTaskNow();

llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void InPlaceTaskDispatcher::dispatch_elsewhere(std::unique_ptr<Task> T) {
5858
FutureReadyCV.notify_one();
5959
}
6060

61-
void InPlaceTaskDispatcher::shutdown() {
61+
void InPlaceTaskDispatcher::run(bool cancel) {
6262
// Keep processing until no tasks belonging to this dispatcher remain
6363
while (true) {
6464
// Check if any task belongs to this dispatcher
@@ -212,9 +212,10 @@ void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) {
212212
}).detach();
213213
}
214214

215-
void DynamicThreadPoolTaskDispatcher::shutdown() {
215+
void DynamicThreadPoolTaskDispatcher::run(bool cancel) {
216216
std::unique_lock<std::mutex> Lock(DispatchMutex);
217-
Shutdown = true;
217+
if (cancel)
218+
Shutdown = true;
218219
OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
219220
}
220221

0 commit comments

Comments
 (0)