Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(699)

Side by Side Diff: Source/platform/scheduler/Scheduler.cpp

Issue 656463004: Use the scheduling mechanism provided by the platform (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Mike's comments. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/platform/scheduler/Scheduler.h ('k') | Source/platform/scheduler/SchedulerTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "platform/scheduler/Scheduler.h" 6 #include "platform/scheduler/Scheduler.h"
7 7
8 #include "platform/PlatformThreadData.h" 8 #include "platform/TraceLocation.h"
9 #include "platform/RuntimeEnabledFeatures.h"
10 #include "platform/Task.h"
11 #include "platform/ThreadTimers.h"
12 #include "platform/TraceEvent.h"
13 #include "public/platform/Platform.h" 9 #include "public/platform/Platform.h"
14 #include "wtf/MainThread.h" 10 #include "public/platform/WebScheduler.h"
15 11
16 namespace blink { 12 namespace blink {
17 13
18 namespace { 14 class IdleTaskRunner : public WebScheduler::IdleTask {
19
20 // The time we should stay in CompositorPriority mode for, after a touch event.
21 double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1;
22
23 } // namespace
24
25 // Typically only created from compositor or render threads.
26 // Note if the scheduler gets shutdown, this may be run after.
27 class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Tas k {
28 public: 15 public:
29 MainThreadPendingHighPriorityTaskRunner( 16 explicit IdleTaskRunner(const Scheduler::IdleTask& task)
30 const Scheduler::Task& task, const TraceLocation& location, const char* traceName) 17 : m_task(task)
31 : m_task(internal::TracedStandardTask::Create(task, location, traceName) )
32 { 18 {
33 ASSERT(Scheduler::shared());
34 } 19 }
35 20
36 // WebThread::Task implementation. 21 virtual ~IdleTaskRunner()
37 virtual void run() override
38 { 22 {
39 m_task->run();
40 if (Scheduler* scheduler = Scheduler::shared()) {
41 scheduler->updatePolicy();
42 scheduler->didRunHighPriorityTask();
43 }
44 } 23 }
45 24
25 // WebScheduler::IdleTask implementation.
26 void run(double deadlineSeconds) override
27 {
28 m_task(deadlineSeconds);
29 }
46 private: 30 private:
47 OwnPtr<internal::TracedStandardTask> m_task; 31 Scheduler::IdleTask m_task;
48 }; 32 };
49 33
50 // Can be created from any thread.
51 // Note if the scheduler gets shutdown, this may be run after.
52 class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task {
53 public:
54 MainThreadPendingTaskRunner(
55 const Scheduler::Task& task, const TraceLocation& location, const char* traceName)
56 : m_task(internal::TracedStandardTask::Create(task, location, traceName) )
57 {
58 ASSERT(Scheduler::shared());
59 }
60
61 // WebThread::Task implementation.
62 virtual void run() override
63 {
64 m_task->run();
65 if (Scheduler* scheduler = Scheduler::shared()) {
66 scheduler->updatePolicy();
67 }
68 }
69
70 private:
71 OwnPtr<internal::TracedStandardTask> m_task;
72 };
73
74
75 // Can be created from any thread.
76 // Note if the scheduler gets shutdown, this may be run after.
77 class Scheduler::MainThreadPendingIdleTaskRunner : public WebThread::Task {
78 public:
79 MainThreadPendingIdleTaskRunner()
80 {
81 ASSERT(Scheduler::shared());
82 }
83
84 // WebThread::Task implementation.
85 virtual void run() override
86 {
87 if (Scheduler* scheduler = Scheduler::shared()) {
88 scheduler->maybeRunPendingIdleTask();
89 // If possible, run the next idle task by reposting on the main thre ad.
90 scheduler->maybePostMainThreadPendingIdleTask();
91 }
92 }
93
94 };
95
96
97 Scheduler* Scheduler::s_sharedScheduler = nullptr; 34 Scheduler* Scheduler::s_sharedScheduler = nullptr;
98 35
99 void Scheduler::initializeOnMainThread()
100 {
101 s_sharedScheduler = new Scheduler();
102 }
103
104 void Scheduler::shutdown() 36 void Scheduler::shutdown()
105 { 37 {
106 delete s_sharedScheduler; 38 delete s_sharedScheduler;
107 s_sharedScheduler = nullptr; 39 s_sharedScheduler = nullptr;
108 } 40 }
109 41
110 Scheduler* Scheduler::shared() 42 Scheduler* Scheduler::shared()
111 { 43 {
44 if (!s_sharedScheduler)
45 s_sharedScheduler = new Scheduler(Platform::current()->scheduler());
112 return s_sharedScheduler; 46 return s_sharedScheduler;
113 } 47 }
114 48
115 Scheduler::Scheduler() 49 Scheduler::Scheduler(WebScheduler* webScheduler)
116 : m_sharedTimerFunction(nullptr) 50 : m_webScheduler(webScheduler)
117 , m_mainThread(blink::Platform::current()->currentThread())
118 , m_estimatedNextBeginFrameSeconds(0)
119 , m_highPriorityTaskCount(0)
120 , m_highPriorityTaskRunnerPosted(false)
121 , m_compositorPriorityPolicyEndTimeSeconds(0)
122 , m_schedulerPolicy(Normal)
123 { 51 {
124 } 52 }
125 53
126 Scheduler::~Scheduler() 54 Scheduler::~Scheduler()
127 { 55 {
128 } 56 if (m_webScheduler)
129 57 m_webScheduler->shutdown();
130 void Scheduler::willBeginFrame(double estimatedNextBeginFrameSeconds)
131 {
132 ASSERT(isMainThread());
133 m_currentFrameCommitted = false;
134 m_estimatedNextBeginFrameSeconds = estimatedNextBeginFrameSeconds;
135 // TODO: Schedule a deferred task here to run idle work if didCommitFrameToC ompositor never gets called.
136 }
137
138 void Scheduler::didCommitFrameToCompositor()
139 {
140 ASSERT(isMainThread());
141 m_currentFrameCommitted = true;
142 flushIncomingIdleTasks();
143 maybePostMainThreadPendingIdleTask();
144 }
145
146 void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, cons t Task& task, const char* traceName)
147 {
148 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner(task, loc ation, traceName));
149 atomicIncrement(&m_highPriorityTaskCount);
150 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount);
151 }
152
153 void Scheduler::didRunHighPriorityTask()
154 {
155 atomicDecrement(&m_highPriorityTaskCount);
156 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount);
157 }
158
159 void Scheduler::postIdleTaskInternal(const TraceLocation& location, const IdleTa sk& idleTask, const char* traceName)
160 {
161 Locker<Mutex> lock(m_incomingIdleTasksMutex);
162 m_incomingIdleTasks.append(internal::TracedIdleTask::Create(idleTask, locati on, traceName));
163 }
164
165 void Scheduler::postTask(const TraceLocation& location, const Task& task)
166 {
167 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Sche duler::MainThreadTask"));
168 }
169
170 void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
171 {
172 postHighPriorityTaskInternal(location, task, "Scheduler::InputTask");
173 }
174
175 void Scheduler::didReceiveInputEvent()
176 {
177 // FIXME: We probably want an explicit Disabled policy rather than disabling CompositorPriority.
178 if (RuntimeEnabledFeatures::blinkSchedulerEnabled())
179 enterSchedulerPolicy(CompositorPriority);
180 }
181
182 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk)
183 {
184 postHighPriorityTaskInternal(location, task, "Scheduler::CompositorTask");
185 }
186
187 void Scheduler::postIpcTask(const TraceLocation& location, const Task& task)
188 {
189 // FIXME: we want IPCs to be high priority, but we can't currently do that b ecause some of them can take a very long
190 // time to process. These need refactoring but we need to add some infrastru cture to identify them.
191 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Sche duler::IpcTask"));
192 } 58 }
193 59
194 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task) 60 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task)
195 { 61 {
196 postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask"); 62 if (m_webScheduler)
197 } 63 m_webScheduler->postIdleTask(location.toWebTraceLocation(), new IdleTask Runner(idleTask));
198
199 bool Scheduler::maybePostMainThreadPendingIdleTask()
200 {
201 ASSERT(isMainThread());
202 TRACE_EVENT0("blink", "Scheduler::maybePostMainThreadPendingIdleTask");
203 if (canRunIdleTask()) {
204 if (!m_pendingIdleTasks.isEmpty()) {
205 m_mainThread->postTask(new MainThreadPendingIdleTaskRunner());
206 return true;
207 }
208 }
209 return false;
210 }
211
212 void Scheduler::tickSharedTimer()
213 {
214 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
215 m_sharedTimerFunction();
216 }
217
218 void Scheduler::updatePolicy()
219 {
220 ASSERT(isMainThread());
221 Locker<Mutex> lock(m_policyStateMutex);
222
223 // Go back to the normal scheduler policy if enough time has elapsed.
224 if (schedulerPolicy() == CompositorPriority && Platform::current()->monotoni callyIncreasingTime() > m_compositorPriorityPolicyEndTimeSeconds)
225 enterSchedulerPolicyLocked(Normal);
226 }
227
228 void Scheduler::sharedTimerAdapter()
229 {
230 shared()->tickSharedTimer();
231 }
232
233 void Scheduler::setSharedTimerFiredFunction(void (*function)())
234 {
235 m_sharedTimerFunction = function;
236 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr);
237 }
238
239 void Scheduler::setSharedTimerFireInterval(double interval)
240 {
241 blink::Platform::current()->setSharedTimerFireInterval(interval);
242 }
243
244 void Scheduler::stopSharedTimer()
245 {
246 blink::Platform::current()->stopSharedTimer();
247 } 64 }
248 65
249 bool Scheduler::shouldYieldForHighPriorityWork() const 66 bool Scheduler::shouldYieldForHighPriorityWork() const
250 { 67 {
251 // It's only worthwhile yielding in CompositorPriority mode. 68 if (m_webScheduler)
252 if (schedulerPolicy() != CompositorPriority) 69 return m_webScheduler->shouldYieldForHighPriorityWork();
253 return false; 70 return false;
254
255 // This method is expected to be run on the main thread, but the high priori ty tasks will be posted by
256 // other threads. We could use locks here, but this function is (sometimes) called a lot by
257 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which
258 // should be cheaper.
259 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal.
260 return acquireLoad(&m_highPriorityTaskCount) != 0;
261 }
262
263 bool Scheduler::maybeRunPendingIdleTask()
264 {
265 ASSERT(isMainThread());
266 if (!canRunIdleTask() || m_pendingIdleTasks.isEmpty())
267 return false;
268
269 m_pendingIdleTasks.takeFirst()->run();
270 return true;
271 }
272
273 void Scheduler::flushIncomingIdleTasks()
274 {
275 ASSERT(isMainThread());
276 Locker<Mutex> lock(m_incomingIdleTasksMutex);
277 while (!m_incomingIdleTasks.isEmpty())
278 m_pendingIdleTasks.append(m_incomingIdleTasks.takeFirst());
279 }
280
281 double Scheduler::currentFrameDeadlineForIdleTasks() const
282 {
283 ASSERT(isMainThread());
284 // TODO: Make idle time more fine-grain chunks when in Compositor priority.
285 return m_estimatedNextBeginFrameSeconds;
286 }
287
288 bool Scheduler::canRunIdleTask() const
289 {
290 ASSERT(isMainThread());
291 return m_currentFrameCommitted
292 && !shouldYieldForHighPriorityWork()
293 && (m_estimatedNextBeginFrameSeconds > Platform::current()->monotonicall yIncreasingTime());
294 }
295
296 Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
297 {
298 ASSERT(isMainThread());
299 // It's important not to miss the transition from normal to low latency mode , otherwise we're likely to
300 // delay the processing of input tasks. Since that transition is triggered b y a different thread, we
301 // need either a lock or a memory barrier, and the memory barrier is probabl y cheaper.
302 return static_cast<SchedulerPolicy>(acquireLoad(&m_schedulerPolicy));
303 }
304
305 void Scheduler::enterSchedulerPolicy(SchedulerPolicy schedulerPolicy)
306 {
307 Locker<Mutex> lock(m_policyStateMutex);
308 enterSchedulerPolicyLocked(schedulerPolicy);
309 }
310
311 void Scheduler::enterSchedulerPolicyLocked(SchedulerPolicy schedulerPolicy)
312 {
313 ASSERT(m_policyStateMutex.locked());
314 if (schedulerPolicy == CompositorPriority)
315 m_compositorPriorityPolicyEndTimeSeconds = Platform::current()->monotoni callyIncreasingTime() + kLowSchedulerPolicyAfterTouchTimeSeconds;
316
317 releaseStore(&m_schedulerPolicy, schedulerPolicy);
318 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "SchedulerPolic y", schedulerPolicy);
319 } 71 }
320 72
321 } // namespace blink 73 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/scheduler/Scheduler.h ('k') | Source/platform/scheduler/SchedulerTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698