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

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

Issue 559973003: Adds the concept of Policies to the Blink Scheduler (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Adds a comment to a test Created 6 years, 3 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
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/PlatformThreadData.h"
9 #include "platform/Task.h" 9 #include "platform/Task.h"
10 #include "platform/ThreadTimers.h" 10 #include "platform/ThreadTimers.h"
11 #include "platform/TraceEvent.h" 11 #include "platform/TraceEvent.h"
12 #include "public/platform/Platform.h" 12 #include "public/platform/Platform.h"
13 #include "wtf/MainThread.h" 13 #include "wtf/MainThread.h"
14 #include "wtf/ThreadingPrimitives.h" 14 #include "wtf/ThreadingPrimitives.h"
15 15
16 16
17 namespace blink { 17 namespace blink {
18 18
19 double Scheduler::s_lowLatencyModeAfterTouchTimeSeconds = 0.1;
20
19 namespace { 21 namespace {
20 22
21 // Can be created from any thread. 23 // Can be created from any thread.
22 // Note if the scheduler gets shutdown, this may be run after. 24 // Note if the scheduler gets shutdown, this may be run after.
23 class MainThreadIdleTaskAdapter : public WebThread::Task { 25 class MainThreadIdleTaskAdapter : public WebThread::Task {
24 public: 26 public:
25 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs, const TraceLocation& location) 27 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs, const TraceLocation& location)
26 : m_idleTask(idleTask) 28 : m_idleTask(idleTask)
27 , m_allottedTimeMs(allottedTimeMs) 29 , m_allottedTimeMs(allottedTimeMs)
28 , m_location(location) 30 , m_location(location)
(...skipping 27 matching lines...) Expand all
56 } 58 }
57 59
58 // WebThread::Task implementation. 60 // WebThread::Task implementation.
59 virtual void run() OVERRIDE 61 virtual void run() OVERRIDE
60 { 62 {
61 Scheduler* scheduler = Scheduler::shared(); 63 Scheduler* scheduler = Scheduler::shared();
62 // FIXME: This check should't be necessary, tasks should not outlive bli nk. 64 // FIXME: This check should't be necessary, tasks should not outlive bli nk.
63 ASSERT(scheduler); 65 ASSERT(scheduler);
64 if (!scheduler) 66 if (!scheduler)
65 return; 67 return;
68 // NOTE if we're not in low latency mode, this is the only place they wi ll actually get executed.
Sami 2014/09/10 16:00:38 nit: reword? (it's not clear what |they| is referr
alexclarke 2014/09/10 17:35:36 Done.
66 scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPostin g(); 69 scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPostin g();
67 } 70 }
68 }; 71 };
69 72
70 73
71 // Can be created from any thread. 74 // Can be created from any thread.
72 // Note if the scheduler gets shutdown, this may be run after. 75 // Note if the scheduler gets shutdown, this may be run after.
73 class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task { 76 class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task {
74 public: 77 public:
75 MainThreadPendingTaskRunner( 78 MainThreadPendingTaskRunner(
76 const Scheduler::Task& task, const TraceLocation& location) 79 const Scheduler::Task& task, const TraceLocation& location)
77 : m_task(task, location) 80 : m_task(task, location)
78 { 81 {
79 ASSERT(Scheduler::shared()); 82 ASSERT(Scheduler::shared());
80 } 83 }
81 84
82 // WebThread::Task implementation. 85 // WebThread::Task implementation.
83 virtual void run() OVERRIDE 86 virtual void run() OVERRIDE
84 { 87 {
85 Scheduler* scheduler = Scheduler::shared(); 88 Scheduler* scheduler = Scheduler::shared();
86 // FIXME: This check should't be necessary, tasks should not outlive bli nk. 89 // FIXME: This check should't be necessary, tasks should not outlive bli nk.
87 ASSERT(scheduler); 90 ASSERT(scheduler);
88 if (scheduler) 91 if (scheduler)
89 Scheduler::shared()->swapQueuesAndRunPendingTasks(); 92 Scheduler::shared()->runPendingHighPrioirtyTasksIfInLowLatencyMode() ;
90 m_task.run(); 93 m_task.run();
91 } 94 }
92 95
93 Scheduler::TracedTask m_task; 96 Scheduler::TracedTask m_task;
94 }; 97 };
95 98
96 Scheduler* Scheduler::s_sharedScheduler = nullptr; 99 Scheduler* Scheduler::s_sharedScheduler = nullptr;
97 100
98 void Scheduler::initializeOnMainThread() 101 void Scheduler::initializeOnMainThread()
99 { 102 {
100 s_sharedScheduler = new Scheduler(); 103 s_sharedScheduler = new Scheduler();
101 } 104 }
102 105
103 void Scheduler::shutdown() 106 void Scheduler::shutdown()
104 { 107 {
105 delete s_sharedScheduler; 108 delete s_sharedScheduler;
106 s_sharedScheduler = nullptr; 109 s_sharedScheduler = nullptr;
107 } 110 }
108 111
109 Scheduler* Scheduler::shared() 112 Scheduler* Scheduler::shared()
110 { 113 {
111 return s_sharedScheduler; 114 return s_sharedScheduler;
112 } 115 }
113 116
114 Scheduler::Scheduler() 117 Scheduler::Scheduler()
115 : m_sharedTimerFunction(nullptr) 118 : m_sharedTimerFunction(nullptr)
116 , m_mainThread(blink::Platform::current()->currentThread()) 119 , m_mainThread(blink::Platform::current()->currentThread())
117 , m_highPriorityTaskCount(0) 120 , m_highPriorityTaskCount(0)
118 , m_highPriorityTaskRunnerPosted(false) 121 , m_highPriorityTaskRunnerPosted(false)
122 , m_latencyMode(Normal)
123 , m_lowLatencyModeEndTimeSeconds(0)
119 { 124 {
120 } 125 }
121 126
122 Scheduler::~Scheduler() 127 Scheduler::~Scheduler()
123 { 128 {
124 while (hasPendingHighPriorityWork()) { 129 while (hasPendingHighPriorityWork()) {
125 swapQueuesAndRunPendingTasks(); 130 swapQueuesAndRunPendingTasks();
126 } 131 }
127 } 132 }
128 133
(...skipping 14 matching lines...) Expand all
143 } 148 }
144 149
145 void Scheduler::postTask(const TraceLocation& location, const Task& task) 150 void Scheduler::postTask(const TraceLocation& location, const Task& task)
146 { 151 {
147 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location)); 152 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location));
148 } 153 }
149 154
150 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) 155 void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
151 { 156 {
152 Locker<Mutex> lock(m_pendingTasksMutex); 157 Locker<Mutex> lock(m_pendingTasksMutex);
158 setLatencyMode(LowLatency);
Sami 2014/09/10 16:00:38 Could you leave out this call so we'll only do thi
alexclarke 2014/09/10 17:35:36 Done.
153 m_pendingHighPriorityTasks.append(TracedTask(task, location)); 159 m_pendingHighPriorityTasks.append(TracedTask(task, location));
154 atomicIncrement(&m_highPriorityTaskCount); 160 atomicIncrement(&m_highPriorityTaskCount);
155 maybePostMainThreadPendingHighPriorityTaskRunner(); 161 maybePostMainThreadPendingHighPriorityTaskRunner();
162 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount);
156 } 163 }
157 164
158 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) 165 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk)
159 { 166 {
160 Locker<Mutex> lock(m_pendingTasksMutex); 167 Locker<Mutex> lock(m_pendingTasksMutex);
161 m_pendingHighPriorityTasks.append(TracedTask(task, location)); 168 m_pendingHighPriorityTasks.append(TracedTask(task, location));
162 atomicIncrement(&m_highPriorityTaskCount); 169 atomicIncrement(&m_highPriorityTaskCount);
163 maybePostMainThreadPendingHighPriorityTaskRunner(); 170 maybePostMainThreadPendingHighPriorityTaskRunner();
171 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount);
164 } 172 }
165 173
166 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() 174 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
167 { 175 {
168 ASSERT(m_pendingTasksMutex.locked()); 176 ASSERT(m_pendingTasksMutex.locked());
169 if (m_highPriorityTaskRunnerPosted) 177 if (m_highPriorityTaskRunnerPosted)
170 return; 178 return;
171 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner()); 179 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
172 m_highPriorityTaskRunnerPosted = true; 180 m_highPriorityTaskRunnerPosted = true;
173 } 181 }
174 182
175 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task) 183 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task)
176 { 184 {
177 scheduleIdleTask(location, idleTask); 185 scheduleIdleTask(location, idleTask);
178 } 186 }
179 187
180 void Scheduler::tickSharedTimer() 188 void Scheduler::tickSharedTimer()
181 { 189 {
182 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer"); 190 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
183 191
184 // Run any high priority tasks that are queued up, otherwise the blink timer s will yield immediately. 192 // Run any high priority tasks that are queued up, otherwise the blink timer s will yield immediately.
185 bool workDone = swapQueuesAndRunPendingTasks(); 193 bool workDone = runPendingHighPrioirtyTasksIfInLowLatencyMode();
186 m_sharedTimerFunction(); 194 m_sharedTimerFunction();
187 195
188 // The blink timers may have just yielded, so run any high priority tasks th at where queued up 196 // The blink timers may have just yielded, so run any high priority tasks th at where queued up
189 // while the blink timers were executing. 197 // while the blink timers were executing.
190 if (!workDone) 198 if (!workDone)
191 swapQueuesAndRunPendingTasks(); 199 runPendingHighPrioirtyTasksIfInLowLatencyMode();
200 }
201
202 bool Scheduler::runPendingHighPrioirtyTasksIfInLowLatencyMode()
203 {
204 if (latencyMode() != LowLatency)
Sami 2014/09/10 16:00:38 ASSERT(isMainThread());
alexclarke 2014/09/10 17:35:37 Done.
205 return false;
206
207 return swapQueuesAndRunPendingTasks();
192 } 208 }
193 209
194 bool Scheduler::swapQueuesAndRunPendingTasks() 210 bool Scheduler::swapQueuesAndRunPendingTasks()
195 { 211 {
196 ASSERT(isMainThread()); 212 ASSERT(isMainThread());
197 213
198 // These locks guard against another thread posting input or compositor task s while we swap the buffers. 214 // These locks guard against another thread posting input or compositor task s while we swap the buffers.
199 // One the buffers have been swapped we can safely access the returned deque without having to lock. 215 // One the buffers have been swapped we can safely access the returned deque without having to lock.
200 m_pendingTasksMutex.lock(); 216 m_pendingTasksMutex.lock();
201 Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffer s(); 217 Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffer s();
(...skipping 18 matching lines...) Expand all
220 { 236 {
221 TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks"); 237 TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
222 int highPriorityTasksExecuted = 0; 238 int highPriorityTasksExecuted = 0;
223 while (!highPriorityTasks.isEmpty()) { 239 while (!highPriorityTasks.isEmpty()) {
224 highPriorityTasks.takeFirst().run(); 240 highPriorityTasks.takeFirst().run();
225 highPriorityTasksExecuted++; 241 highPriorityTasksExecuted++;
226 } 242 }
227 243
228 int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPri orityTasksExecuted); 244 int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPri orityTasksExecuted);
229 ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0); 245 ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0);
246 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount);
247
248 // Go back to normal latency mode if enough time has elapsed.
249 if (latencyMode() == LowLatency && Platform::current()->monotonicallyIncreas ingTime() > m_lowLatencyModeEndTimeSeconds)
250 setLatencyMode(Normal);
230 return highPriorityTasksExecuted > 0; 251 return highPriorityTasksExecuted > 0;
231 } 252 }
232 253
233 void Scheduler::sharedTimerAdapter() 254 void Scheduler::sharedTimerAdapter()
234 { 255 {
235 shared()->tickSharedTimer(); 256 shared()->tickSharedTimer();
236 } 257 }
237 258
238 void Scheduler::setSharedTimerFiredFunction(void (*function)()) 259 void Scheduler::setSharedTimerFiredFunction(void (*function)())
239 { 260 {
240 m_sharedTimerFunction = function; 261 m_sharedTimerFunction = function;
241 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr); 262 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr);
242 } 263 }
243 264
244 void Scheduler::setSharedTimerFireInterval(double interval) 265 void Scheduler::setSharedTimerFireInterval(double interval)
245 { 266 {
246 blink::Platform::current()->setSharedTimerFireInterval(interval); 267 blink::Platform::current()->setSharedTimerFireInterval(interval);
247 } 268 }
248 269
249 void Scheduler::stopSharedTimer() 270 void Scheduler::stopSharedTimer()
250 { 271 {
251 blink::Platform::current()->stopSharedTimer(); 272 blink::Platform::current()->stopSharedTimer();
252 } 273 }
253 274
254 bool Scheduler::shouldYieldForHighPriorityWork() const 275 bool Scheduler::shouldYieldForHighPriorityWork() const
255 { 276 {
277 if (latencyMode() == Normal)
278 return false;
279
256 return hasPendingHighPriorityWork(); 280 return hasPendingHighPriorityWork();
257 } 281 }
258 282
259 bool Scheduler::hasPendingHighPriorityWork() const 283 bool Scheduler::hasPendingHighPriorityWork() const
260 { 284 {
261 // This method is expected to be run on the main thread, but the high priori ty tasks will be posted by 285 // This method is expected to be run on the main thread, but the high priori ty tasks will be posted by
262 // other threads. We could use locks here, but this function is (sometimes) called a lot by 286 // other threads. We could use locks here, but this function is (sometimes) called a lot by
263 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which 287 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which
264 // should be cheaper. 288 // should be cheaper.
265 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal. 289 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal.
266 return acquireLoad(&m_highPriorityTaskCount) != 0; 290 return acquireLoad(&m_highPriorityTaskCount) != 0;
267 } 291 }
268 292
293 Scheduler::LatencyMode Scheduler::latencyMode() const
294 {
295 ASSERT(isMainThread());
296 return static_cast<LatencyMode>(acquireLoad(&m_latencyMode));
297 }
298
299 void Scheduler::setLatencyMode(LatencyMode latencyMode)
300 {
301 if (latencyMode == LowLatency)
302 m_lowLatencyModeEndTimeSeconds = Platform::current()->monotonicallyIncre asingTime() + s_lowLatencyModeAfterTouchTimeSeconds;
303
304 releaseStore(&m_latencyMode, latencyMode);
305 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "LatencyMode", latencyMode);
306 }
307
269 void Scheduler::TracedTask::run() 308 void Scheduler::TracedTask::run()
270 { 309 {
271 TRACE_EVENT2("blink", "TracedTask::run", 310 TRACE_EVENT2("blink", "TracedTask::run",
272 "src_file", m_location.fileName(), 311 "src_file", m_location.fileName(),
273 "src_func", m_location.functionName()); 312 "src_func", m_location.functionName());
274 m_task(); 313 m_task();
275 } 314 }
276 315
277 } // namespace blink 316 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698