Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "content/browser/scheduler/browser_ui_thread_scheduler.h" |
| 6 | |
mikt | 541ac71 | 2025-08-04 03:16:22 | [diff] [blame] | 7 | #include <memory> |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 8 | #include <utility> |
| 9 | |
Alex Clarke | 9018deb | 2019-03-18 19:17:34 | [diff] [blame] | 10 | #include "base/feature_list.h" |
Anand Ravi | 5e3bf10 | 2025-05-02 15:24:49 | [diff] [blame] | 11 | #include "base/functional/bind.h" |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 12 | #include "base/memory/ptr_util.h" |
Alex Clarke | 636e705 | 2019-05-30 10:49:37 | [diff] [blame] | 13 | #include "base/message_loop/message_pump.h" |
Chris Sharp | 7840c58 | 2019-08-02 15:45:32 | [diff] [blame] | 14 | #include "base/message_loop/message_pump_type.h" |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 15 | #include "base/process/process.h" |
Carlos Caballero | ff8c503 | 2019-04-01 11:15:08 | [diff] [blame] | 16 | #include "base/run_loop.h" |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 17 | #include "base/task/sequence_manager/sequence_manager.h" |
| 18 | #include "base/task/sequence_manager/sequence_manager_impl.h" |
Carlos Caballero | c472c2bf | 2019-04-18 09:30:36 | [diff] [blame] | 19 | #include "base/task/sequence_manager/task_queue.h" |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 20 | #include "base/task/sequence_manager/time_domain.h" |
| 21 | #include "base/threading/platform_thread.h" |
Stephen Nusko | 408b9a9 | 2022-09-15 10:03:57 | [diff] [blame] | 22 | #include "base/trace_event/trace_event.h" |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 23 | #include "build/build_config.h" |
Scott Haseley | 72d89b0 | 2023-02-17 03:29:25 | [diff] [blame] | 24 | #include "content/browser/scheduler/browser_task_priority.h" |
mikt | 541ac71 | 2025-08-04 03:16:22 | [diff] [blame] | 25 | #include "content/common/features.h" |
Carlos Caballero | 5f6212b | 2019-05-13 13:45:16 | [diff] [blame] | 26 | #include "content/public/browser/browser_thread.h" |
Alex Clarke | 9018deb | 2019-03-18 19:17:34 | [diff] [blame] | 27 | #include "content/public/common/content_features.h" |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 28 | |
Stephen Nusko | 408b9a9 | 2022-09-15 10:03:57 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | content::BrowserUIThreadScheduler* g_browser_ui_thread_scheduler = nullptr; |
| 32 | |
| 33 | } // namespace |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 34 | namespace content { |
| 35 | |
| 36 | BrowserUIThreadScheduler::~BrowserUIThreadScheduler() = default; |
| 37 | |
| 38 | // static |
| 39 | std::unique_ptr<BrowserUIThreadScheduler> |
mikt | 541ac71 | 2025-08-04 03:16:22 | [diff] [blame] | 40 | BrowserUIThreadScheduler::CreateForTesting() { |
| 41 | auto scheduler = base::WrapUnique(new BrowserUIThreadScheduler()); |
| 42 | scheduler->InstallPartitionAllocSchedulerLoopQuarantineTaskObserver(); |
| 43 | return scheduler; |
| 44 | } |
| 45 | // static |
| 46 | std::unique_ptr<BrowserUIThreadScheduler> |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 47 | BrowserUIThreadScheduler::CreateForTesting( |
Etienne Pierre-doray | 40545ac | 2021-11-11 13:34:28 | [diff] [blame] | 48 | base::sequence_manager::SequenceManager* sequence_manager) { |
mikt | 541ac71 | 2025-08-04 03:16:22 | [diff] [blame] | 49 | auto scheduler = |
| 50 | base::WrapUnique(new BrowserUIThreadScheduler(sequence_manager)); |
| 51 | scheduler->InstallPartitionAllocSchedulerLoopQuarantineTaskObserver(); |
| 52 | return scheduler; |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 53 | } |
Stephen Nusko | 408b9a9 | 2022-09-15 10:03:57 | [diff] [blame] | 54 | BrowserUIThreadScheduler* BrowserUIThreadScheduler::Get() { |
| 55 | DCHECK(g_browser_ui_thread_scheduler); |
| 56 | return g_browser_ui_thread_scheduler; |
| 57 | } |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 58 | BrowserUIThreadScheduler::BrowserUIThreadScheduler() |
| 59 | : owned_sequence_manager_( |
| 60 | base::sequence_manager::CreateUnboundSequenceManager( |
Alex Clarke | 5f3d461b | 2019-04-29 14:23:11 | [diff] [blame] | 61 | base::sequence_manager::SequenceManager::Settings::Builder() |
Chris Sharp | 7840c58 | 2019-08-02 15:45:32 | [diff] [blame] | 62 | .SetMessagePumpType(base::MessagePumpType::UI) |
François Doray | e616cfc | 2023-03-06 15:52:29 | [diff] [blame] | 63 | .SetCanRunTasksByBatches(true) |
Scott Haseley | 72d89b0 | 2023-02-17 03:29:25 | [diff] [blame] | 64 | .SetPrioritySettings( |
| 65 | internal::CreateBrowserTaskPrioritySettings()) |
Patrick Monette | a2e2f9c | 2025-08-06 14:25:01 | [diff] [blame] | 66 | .SetIsMainThread(true) |
Anand Ravi | 5e3bf10 | 2025-05-02 15:24:49 | [diff] [blame] | 67 | .SetShouldSampleCPUTime(true) |
Anand Ravi | 3007a57 | 2025-08-08 15:11:33 | [diff] [blame] | 68 | .SetShouldReportLockMetrics(true) |
Alex Clarke | 5f3d461b | 2019-04-29 14:23:11 | [diff] [blame] | 69 | .Build())), |
Etienne Pierre-doray | 40545ac | 2021-11-11 13:34:28 | [diff] [blame] | 70 | task_queues_(BrowserThread::UI, owned_sequence_manager_.get()), |
François Doray | 253a306 | 2022-10-24 16:45:29 | [diff] [blame] | 71 | handle_(task_queues_.GetHandle()) { |
Anand Ravi | 5e3bf10 | 2025-05-02 15:24:49 | [diff] [blame] | 72 | task_queues_.SetOnTaskCompletedHandler(base::BindRepeating( |
| 73 | &BrowserUIThreadScheduler::OnTaskCompleted, base::Unretained(this))); |
Carlos Caballero | 5f6212b | 2019-05-13 13:45:16 | [diff] [blame] | 74 | CommonSequenceManagerSetup(owned_sequence_manager_.get()); |
Alex Clarke | 49854cc | 2019-06-27 08:25:49 | [diff] [blame] | 75 | owned_sequence_manager_->SetDefaultTaskRunner( |
| 76 | handle_->GetDefaultTaskRunner()); |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 77 | |
Carlos Caballero | 5f6212b | 2019-05-13 13:45:16 | [diff] [blame] | 78 | owned_sequence_manager_->BindToMessagePump( |
Chris Sharp | 7840c58 | 2019-08-02 15:45:32 | [diff] [blame] | 79 | base::MessagePump::Create(base::MessagePumpType::UI)); |
Stephen Nusko | 408b9a9 | 2022-09-15 10:03:57 | [diff] [blame] | 80 | g_browser_ui_thread_scheduler = this; |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | BrowserUIThreadScheduler::BrowserUIThreadScheduler( |
Etienne Pierre-doray | 40545ac | 2021-11-11 13:34:28 | [diff] [blame] | 84 | base::sequence_manager::SequenceManager* sequence_manager) |
| 85 | : task_queues_(BrowserThread::UI, sequence_manager), |
François Doray | 253a306 | 2022-10-24 16:45:29 | [diff] [blame] | 86 | handle_(task_queues_.GetHandle()) { |
Carlos Caballero | 5f6212b | 2019-05-13 13:45:16 | [diff] [blame] | 87 | CommonSequenceManagerSetup(sequence_manager); |
Stephen Nusko | 408b9a9 | 2022-09-15 10:03:57 | [diff] [blame] | 88 | g_browser_ui_thread_scheduler = this; |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 89 | } |
| 90 | |
Carlos Caballero | 5f6212b | 2019-05-13 13:45:16 | [diff] [blame] | 91 | void BrowserUIThreadScheduler::CommonSequenceManagerSetup( |
| 92 | base::sequence_manager::SequenceManager* sequence_manager) { |
Scott Haseley | 72d89b0 | 2023-02-17 03:29:25 | [diff] [blame] | 93 | DCHECK_EQ(static_cast<size_t>(sequence_manager->GetPriorityCount()), |
| 94 | static_cast<size_t>(internal::BrowserTaskPriority::kPriorityCount)); |
Alexander Timin | e653dfc | 2020-01-07 17:55:06 | [diff] [blame] | 95 | sequence_manager->EnableCrashKeys("ui_scheduler_async_stack"); |
Carlos Caballero | ff8c503 | 2019-04-01 11:15:08 | [diff] [blame] | 96 | } |
| 97 | |
Anand Ravi | 5e3bf10 | 2025-05-02 15:24:49 | [diff] [blame] | 98 | void BrowserUIThreadScheduler::OnTaskCompleted( |
| 99 | const base::sequence_manager::Task& task, |
| 100 | base::sequence_manager::TaskQueue::TaskTiming* task_timing, |
| 101 | base::LazyNow* lazy_now) { |
| 102 | // Note: Thread time is already subsampled in sequence manager by a factor of |
| 103 | // |kTaskSamplingRateForRecordingCPUTime|. So browser main can piggy back on |
| 104 | // that subsampling to record histograms without fear of oversampling. |
| 105 | task_timing->RecordTaskEnd(lazy_now); |
| 106 | task_timing->RecordUmaOnCpuMetrics("BrowserScheduler.UIThread"); |
| 107 | } |
| 108 | |
mikt | 541ac71 | 2025-08-04 03:16:22 | [diff] [blame] | 109 | void BrowserUIThreadScheduler:: |
| 110 | InstallPartitionAllocSchedulerLoopQuarantineTaskObserver() { |
| 111 | if (base::FeatureList::IsEnabled( |
| 112 | features:: |
| 113 | kPartitionAllocSchedulerLoopQuarantineTaskObserverForBrowserUIThread)) { |
| 114 | task_queues_.AddTaskObserver(&scheduler_loop_quarantine_task_observer_); |
| 115 | } |
| 116 | } |
| 117 | |
Alex Clarke | 831ed1e6 | 2019-02-18 21:10:08 | [diff] [blame] | 118 | } // namespace content |