OLD | NEW |
---|---|
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/RuntimeEnabledFeatures.h" | 9 #include "platform/RuntimeEnabledFeatures.h" |
10 #include "platform/Task.h" | 10 #include "platform/Task.h" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 ASSERT(isMainThread()); | 132 ASSERT(isMainThread()); |
133 m_currentFrameCommitted = false; | 133 m_currentFrameCommitted = false; |
134 m_estimatedNextBeginFrameSeconds = estimatedNextBeginFrameSeconds; | 134 m_estimatedNextBeginFrameSeconds = estimatedNextBeginFrameSeconds; |
135 // TODO: Schedule a deferred task here to run idle work if didCommitFrameToC ompositor never gets called. | 135 // TODO: Schedule a deferred task here to run idle work if didCommitFrameToC ompositor never gets called. |
136 } | 136 } |
137 | 137 |
138 void Scheduler::didCommitFrameToCompositor() | 138 void Scheduler::didCommitFrameToCompositor() |
139 { | 139 { |
140 ASSERT(isMainThread()); | 140 ASSERT(isMainThread()); |
141 m_currentFrameCommitted = true; | 141 m_currentFrameCommitted = true; |
142 flushIncomingIdleTasks(); | |
142 maybePostMainThreadPendingIdleTask(); | 143 maybePostMainThreadPendingIdleTask(); |
143 } | 144 } |
144 | 145 |
145 void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, cons t Task& task, const char* traceName) | 146 void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, cons t Task& task, const char* traceName) |
146 { | 147 { |
147 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner(task, loc ation, traceName)); | 148 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner(task, loc ation, traceName)); |
148 atomicIncrement(&m_highPriorityTaskCount); | 149 atomicIncrement(&m_highPriorityTaskCount); |
149 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount); | 150 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount); |
150 } | 151 } |
151 | 152 |
152 void Scheduler::didRunHighPriorityTask() | 153 void Scheduler::didRunHighPriorityTask() |
153 { | 154 { |
154 atomicDecrement(&m_highPriorityTaskCount); | 155 atomicDecrement(&m_highPriorityTaskCount); |
155 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount); | 156 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPri orityTasks", m_highPriorityTaskCount); |
156 } | 157 } |
157 | 158 |
158 void Scheduler::postIdleTaskInternal(const TraceLocation& location, const IdleTa sk& idleTask, const char* traceName) | 159 void Scheduler::postIdleTaskInternal(const TraceLocation& location, const IdleTa sk& idleTask, const char* traceName) |
159 { | 160 { |
160 Locker<Mutex> lock(m_pendingIdleTasksMutex); | 161 Locker<Mutex> lock(m_incomingIdleTasksMutex); |
161 m_pendingIdleTasks.append(internal::TracedIdleTask::Create(idleTask, locatio n, traceName)); | 162 m_incomingIdleTasks.append(internal::TracedIdleTask::Create(idleTask, locati on, traceName)); |
162 } | 163 } |
163 | 164 |
164 void Scheduler::postTask(const TraceLocation& location, const Task& task) | 165 void Scheduler::postTask(const TraceLocation& location, const Task& task) |
165 { | 166 { |
166 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Sche duler::MainThreadTask")); | 167 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Sche duler::MainThreadTask")); |
167 } | 168 } |
168 | 169 |
169 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) | 170 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) |
170 { | 171 { |
171 postHighPriorityTaskInternal(location, task, "Scheduler::InputTask"); | 172 postHighPriorityTaskInternal(location, task, "Scheduler::InputTask"); |
(...skipping 21 matching lines...) Expand all Loading... | |
193 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task) | 194 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task) |
194 { | 195 { |
195 postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask"); | 196 postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask"); |
196 } | 197 } |
197 | 198 |
198 bool Scheduler::maybePostMainThreadPendingIdleTask() | 199 bool Scheduler::maybePostMainThreadPendingIdleTask() |
199 { | 200 { |
200 ASSERT(isMainThread()); | 201 ASSERT(isMainThread()); |
201 TRACE_EVENT0("blink", "Scheduler::maybePostMainThreadPendingIdleTask"); | 202 TRACE_EVENT0("blink", "Scheduler::maybePostMainThreadPendingIdleTask"); |
202 if (canRunIdleTask()) { | 203 if (canRunIdleTask()) { |
203 Locker<Mutex> lock(m_pendingIdleTasksMutex); | |
204 if (!m_pendingIdleTasks.isEmpty()) { | 204 if (!m_pendingIdleTasks.isEmpty()) { |
205 m_mainThread->postTask(new MainThreadPendingIdleTaskRunner()); | 205 m_mainThread->postTask(new MainThreadPendingIdleTaskRunner()); |
206 return true; | 206 return true; |
207 } | 207 } |
208 } | 208 } |
209 return false; | 209 return false; |
210 } | 210 } |
211 | 211 |
212 void Scheduler::tickSharedTimer() | 212 void Scheduler::tickSharedTimer() |
213 { | 213 { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 // other threads. We could use locks here, but this function is (sometimes) called a lot 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 | 257 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which |
258 // should be cheaper. | 258 // should be cheaper. |
259 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal. | 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; | 260 return acquireLoad(&m_highPriorityTaskCount) != 0; |
261 } | 261 } |
262 | 262 |
263 bool Scheduler::maybeRunPendingIdleTask() | 263 bool Scheduler::maybeRunPendingIdleTask() |
264 { | 264 { |
265 ASSERT(isMainThread()); | 265 ASSERT(isMainThread()); |
266 if (!canRunIdleTask()) | 266 if (!canRunIdleTask() || m_pendingIdleTasks.isEmpty()) |
267 return false; | 267 return false; |
268 | 268 |
269 takeFirstPendingIdleTask()->run(); | 269 m_pendingIdleTasks.takeFirst()->run(); |
270 return true; | 270 return true; |
271 } | 271 } |
272 | 272 |
273 PassOwnPtr<internal::TracedIdleTask> Scheduler::takeFirstPendingIdleTask() | 273 void Scheduler::flushIncomingIdleTasks() |
274 { | 274 { |
275 Locker<Mutex> lock(m_pendingIdleTasksMutex); | 275 ASSERT(isMainThread()); |
276 ASSERT(!m_pendingIdleTasks.isEmpty()); | 276 Locker<Mutex> lock(m_incomingIdleTasksMutex); |
Sami
2014/10/10 17:31:31
I'm trying to decide whether we should only do thi
rmcilroy
2014/10/13 11:41:19
I don't think it would make much of a difference e
| |
277 return m_pendingIdleTasks.takeFirst(); | 277 if (m_incomingIdleTasks.isEmpty()) |
278 return; | |
279 | |
picksi1
2014/10/13 09:38:09
Is it worth doing this empty check here? The follo
rmcilroy
2014/10/13 11:41:19
Makes sense, dropped it.
| |
280 while (!m_incomingIdleTasks.isEmpty()) { | |
jochen (gone - plz use gerrit)
2014/10/13 08:09:11
nit. no { }
what happens if the idle task immedia
rmcilroy
2014/10/13 11:41:19
If the idle task immediately posts a new task it w
| |
281 m_pendingIdleTasks.append(m_incomingIdleTasks.takeFirst()); | |
282 } | |
picksi1
2014/10/13 09:38:09
Is there no quick way to append the entire queue h
rmcilroy
2014/10/13 11:41:19
I couldn't find any faster append in Deque - let m
| |
278 } | 283 } |
279 | 284 |
280 double Scheduler::currentFrameDeadlineForIdleTasks() const | 285 double Scheduler::currentFrameDeadlineForIdleTasks() const |
281 { | 286 { |
282 ASSERT(isMainThread()); | 287 ASSERT(isMainThread()); |
283 // TODO: Make idle time more fine-grain chunks when in Compositor priority. | 288 // TODO: Make idle time more fine-grain chunks when in Compositor priority. |
284 return m_estimatedNextBeginFrameSeconds; | 289 return m_estimatedNextBeginFrameSeconds; |
285 } | 290 } |
286 | 291 |
287 bool Scheduler::canRunIdleTask() const | 292 bool Scheduler::canRunIdleTask() const |
(...skipping 23 matching lines...) Expand all Loading... | |
311 { | 316 { |
312 ASSERT(m_policyStateMutex.locked()); | 317 ASSERT(m_policyStateMutex.locked()); |
313 if (schedulerPolicy == CompositorPriority) | 318 if (schedulerPolicy == CompositorPriority) |
314 m_compositorPriorityPolicyEndTimeSeconds = Platform::current()->monotoni callyIncreasingTime() + kLowSchedulerPolicyAfterTouchTimeSeconds; | 319 m_compositorPriorityPolicyEndTimeSeconds = Platform::current()->monotoni callyIncreasingTime() + kLowSchedulerPolicyAfterTouchTimeSeconds; |
315 | 320 |
316 releaseStore(&m_schedulerPolicy, schedulerPolicy); | 321 releaseStore(&m_schedulerPolicy, schedulerPolicy); |
317 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "SchedulerPolic y", schedulerPolicy); | 322 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "SchedulerPolic y", schedulerPolicy); |
318 } | 323 } |
319 | 324 |
320 } // namespace blink | 325 } // namespace blink |
OLD | NEW |