| Index: Source/platform/scheduler/Scheduler.cpp
|
| diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
|
| index 4a447721f58921b8fe0500568ed583f76288b5c8..eb6c698604630c429e1374f82446497987a24b74 100644
|
| --- a/Source/platform/scheduler/Scheduler.cpp
|
| +++ b/Source/platform/scheduler/Scheduler.cpp
|
| @@ -18,6 +18,9 @@ namespace blink {
|
|
|
| namespace {
|
|
|
| +// The time we should stay in CompositorPriority mode for, after a touch event.
|
| +double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1;
|
| +
|
| // Can be created from any thread.
|
| // Note if the scheduler gets shutdown, this may be run after.
|
| class MainThreadIdleTaskAdapter : public WebThread::Task {
|
| @@ -63,6 +66,8 @@ public:
|
| ASSERT(scheduler);
|
| if (!scheduler)
|
| return;
|
| + // NOTE we must unconditionally execute high priority tasks here, since if we're not in CompositorPriority
|
| + // mode, then this is the only place where high priority tasks will be executed.
|
| scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting();
|
| }
|
| };
|
| @@ -86,7 +91,7 @@ public:
|
| // FIXME: This check should't be necessary, tasks should not outlive blink.
|
| ASSERT(scheduler);
|
| if (scheduler)
|
| - Scheduler::shared()->swapQueuesAndRunPendingTasks();
|
| + Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority();
|
| m_task.run();
|
| }
|
|
|
| @@ -114,8 +119,10 @@ Scheduler* Scheduler::shared()
|
| Scheduler::Scheduler()
|
| : m_sharedTimerFunction(nullptr)
|
| , m_mainThread(blink::Platform::current()->currentThread())
|
| + , m_compositorPriorityPolicyEndTimeSeconds(0)
|
| , m_highPriorityTaskCount(0)
|
| , m_highPriorityTaskRunnerPosted(false)
|
| + , m_schedulerPolicy(Normal)
|
| {
|
| }
|
|
|
| @@ -153,6 +160,7 @@ void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
|
| m_pendingHighPriorityTasks.append(TracedTask(task, location));
|
| atomicIncrement(&m_highPriorityTaskCount);
|
| maybePostMainThreadPendingHighPriorityTaskRunner();
|
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
|
| }
|
|
|
| void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task)
|
| @@ -161,6 +169,7 @@ void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta
|
| m_pendingHighPriorityTasks.append(TracedTask(task, location));
|
| atomicIncrement(&m_highPriorityTaskCount);
|
| maybePostMainThreadPendingHighPriorityTaskRunner();
|
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
|
| }
|
|
|
| void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
|
| @@ -182,13 +191,22 @@ void Scheduler::tickSharedTimer()
|
| TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
|
|
|
| // Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately.
|
| - bool workDone = swapQueuesAndRunPendingTasks();
|
| + bool workDone = runPendingHighPriorityTasksIfInCompositorPriority();
|
| m_sharedTimerFunction();
|
|
|
| // The blink timers may have just yielded, so run any high priority tasks that where queued up
|
| // while the blink timers were executing.
|
| if (!workDone)
|
| - swapQueuesAndRunPendingTasks();
|
| + runPendingHighPriorityTasksIfInCompositorPriority();
|
| +}
|
| +
|
| +bool Scheduler::runPendingHighPriorityTasksIfInCompositorPriority()
|
| +{
|
| + ASSERT(isMainThread());
|
| + if (schedulerPolicy() != CompositorPriority)
|
| + return false;
|
| +
|
| + return swapQueuesAndRunPendingTasks();
|
| }
|
|
|
| bool Scheduler::swapQueuesAndRunPendingTasks()
|
| @@ -199,6 +217,7 @@ bool Scheduler::swapQueuesAndRunPendingTasks()
|
| // One the buffers have been swapped we can safely access the returned deque without having to lock.
|
| m_pendingTasksMutex.lock();
|
| Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
|
| + maybeEnterNormalSchedulerPolicy();
|
| m_pendingTasksMutex.unlock();
|
| return executeHighPriorityTasks(highPriorityTasks);
|
| }
|
| @@ -212,10 +231,21 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting()
|
| m_pendingTasksMutex.lock();
|
| Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
|
| m_highPriorityTaskRunnerPosted = false;
|
| + maybeEnterNormalSchedulerPolicy();
|
| m_pendingTasksMutex.unlock();
|
| executeHighPriorityTasks(highPriorityTasks);
|
| }
|
|
|
| +void Scheduler::maybeEnterNormalSchedulerPolicy()
|
| +{
|
| + ASSERT(isMainThread());
|
| + ASSERT(m_pendingTasksMutex.locked());
|
| +
|
| + // Go back to the normal scheduler policy if enough time has elapsed.
|
| + if (schedulerPolicy() == CompositorPriority && Platform::current()->monotonicallyIncreasingTime() > m_compositorPriorityPolicyEndTimeSeconds)
|
| + enterSchedulerPolicyLocked(Normal);
|
| +}
|
| +
|
| bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
|
| {
|
| TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
|
| @@ -227,6 +257,7 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
|
|
|
| int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPriorityTasksExecuted);
|
| ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0);
|
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
|
| return highPriorityTasksExecuted > 0;
|
| }
|
|
|
| @@ -253,6 +284,10 @@ void Scheduler::stopSharedTimer()
|
|
|
| bool Scheduler::shouldYieldForHighPriorityWork() const
|
| {
|
| + // It's only worthwhile yielding in CompositorPriority mode.
|
| + if (schedulerPolicy() != CompositorPriority)
|
| + return false;
|
| +
|
| return hasPendingHighPriorityWork();
|
| }
|
|
|
| @@ -266,6 +301,31 @@ bool Scheduler::hasPendingHighPriorityWork() const
|
| return acquireLoad(&m_highPriorityTaskCount) != 0;
|
| }
|
|
|
| +Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
|
| +{
|
| + ASSERT(isMainThread());
|
| + // It's important not to miss the transition from normal to low latency mode, otherwise we're likely to
|
| + // delay the processing of input tasks. Since that transition is triggered by a different thread, we
|
| + // need either a lock or a memory barrier, and the memory barrier is probably cheaper.
|
| + return static_cast<SchedulerPolicy>(acquireLoad(&m_schedulerPolicy));
|
| +}
|
| +
|
| +void Scheduler::enterSchedulerPolicy(SchedulerPolicy schedulerPolicy)
|
| +{
|
| + Locker<Mutex> lock(m_pendingTasksMutex);
|
| + enterSchedulerPolicyLocked(schedulerPolicy);
|
| +}
|
| +
|
| +void Scheduler::enterSchedulerPolicyLocked(SchedulerPolicy schedulerPolicy)
|
| +{
|
| + ASSERT(m_pendingTasksMutex.locked());
|
| + if (schedulerPolicy == CompositorPriority)
|
| + m_compositorPriorityPolicyEndTimeSeconds = Platform::current()->monotonicallyIncreasingTime() + kLowSchedulerPolicyAfterTouchTimeSeconds;
|
| +
|
| + releaseStore(&m_schedulerPolicy, schedulerPolicy);
|
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "SchedulerPolicy", schedulerPolicy);
|
| +}
|
| +
|
| void Scheduler::TracedTask::run()
|
| {
|
| TRACE_EVENT2("blink", "TracedTask::run",
|
|
|