Commit 9d7e8ea3 authored by Andreas Haas's avatar Andreas Haas Committed by V8 LUCI CQ

[d8] Clean up DefaultForegroundTaskRunner::Terminate

Follow-up to post-submit comments in
https://chromium-review.googlesource.com/c/v8/v8/+/3782796

Bug: chromium:1346250, v8:12926
Change-Id: I09a8601c600b24fbc92489224ad69602e557bf7f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3784604
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82154}
parent 9afba3ff
......@@ -27,39 +27,24 @@ DefaultForegroundTaskRunner::DefaultForegroundTaskRunner(
: idle_task_support_(idle_task_support), time_function_(time_function) {}
void DefaultForegroundTaskRunner::Terminate() {
// Drain the task queues.
// We make sure to delete tasks outside the TaskRunner lock, to avoid
// potential deadlocks.
std::deque<TaskQueueEntry> obsolete_tasks;
std::priority_queue<DelayedEntry, std::vector<DelayedEntry>,
DelayedEntryCompare>
obsolete_delayed_tasks;
std::queue<std::unique_ptr<IdleTask>> obsolete_idle_tasks;
{
base::MutexGuard guard(&lock_);
terminated_ = true;
task_queue_.swap(obsolete_tasks);
delayed_task_queue_.swap(obsolete_delayed_tasks);
idle_task_queue_.swap(obsolete_idle_tasks);
}
// Drain the task queues.
// We have to do this lock dance here to avoid a lock order inversion warning
// of TSAN: during initialization, the WasmEngine lock gets taken before the
// TaskRunner lock. The TaskRunner lock is taken during WasmEngine
// initialization when the ForegroundTaskRunner gets acquire. During shutdown,
// the TaskRunner lock gets taken before the WasmEngine lock. The WasmEngine
// lock gets taken in the destructor of the LogCode task.
// In the code below we pop one task at a time from the task queue while
// holding the TaskRunner lock, but delete the task only after releasing the
// TaskRunner lock. Thereby we avoid holding the TaskRunner lock when the
// destructor of the task may take other locks.
while (true) {
std::unique_ptr<Task> task;
{
base::MutexGuard guard(&lock_);
if (task_queue_.empty()) break;
task = std::move(task_queue_.front().second);
task_queue_.pop_front();
}
// Reset the unique_ptr just for readability, to show that the task gets
// deallocated here without holding the lock.
task.reset();
}
// TODO(v8): If it ever becomes necessary, do the same lock dance for delayed
// tasks and idle tasks as above.
base::MutexGuard guard(&lock_);
while (!delayed_task_queue_.empty()) delayed_task_queue_.pop();
while (!idle_task_queue_.empty()) idle_task_queue_.pop();
while (!obsolete_tasks.empty()) obsolete_tasks.pop_front();
while (!obsolete_delayed_tasks.empty()) obsolete_delayed_tasks.pop();
while (!obsolete_idle_tasks.empty()) obsolete_idle_tasks.pop();
}
void DefaultForegroundTaskRunner::PostTaskLocked(std::unique_ptr<Task> task,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment