| Index: Source/platform/scheduler/Scheduler.cpp
|
| diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
|
| index c88c4203a6a7e3c9ad6a36fb3f400e6ea1a7bcc0..136d5c11fa278770ccaf085e6b397be9feed398c 100644
|
| --- a/Source/platform/scheduler/Scheduler.cpp
|
| +++ b/Source/platform/scheduler/Scheduler.cpp
|
| @@ -19,32 +19,6 @@ 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 {
|
| -public:
|
| - MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs, const TraceLocation& location)
|
| - : m_idleTask(idleTask)
|
| - , m_allottedTimeMs(allottedTimeMs)
|
| - , m_location(location)
|
| - {
|
| - }
|
| -
|
| - // WebThread::Task implementation.
|
| - virtual void run() OVERRIDE
|
| - {
|
| - TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run",
|
| - "src_file", m_location.fileName(),
|
| - "src_func", m_location.functionName());
|
| - m_idleTask(m_allottedTimeMs);
|
| - }
|
| -
|
| -private:
|
| - Scheduler::IdleTask m_idleTask;
|
| - double m_allottedTimeMs;
|
| - TraceLocation m_location;
|
| -};
|
| -
|
| } // namespace
|
|
|
| // Typically only created from compositor or render threads.
|
| @@ -86,16 +60,44 @@ public:
|
| virtual void run() OVERRIDE
|
| {
|
| Scheduler* scheduler = Scheduler::shared();
|
| - // FIXME: This check should't be necessary, tasks should not outlive blink.
|
| + // FIXME: This check shouldn't be necessary, tasks should not outlive blink.
|
| ASSERT(scheduler);
|
| if (scheduler)
|
| - Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority();
|
| + scheduler->runPendingHighPriorityTasksIfInCompositorPriority();
|
| +
|
| m_task.run();
|
| }
|
|
|
| - TracedTask m_task;
|
| +private:
|
| + TracedStandardTask m_task;
|
| };
|
|
|
| +
|
| +// Can be created from any thread.
|
| +// Note if the scheduler gets shutdown, this may be run after.
|
| +class Scheduler::MainThreadPendingIdleTaskRunner : public WebThread::Task {
|
| +public:
|
| + MainThreadPendingIdleTaskRunner()
|
| + {
|
| + ASSERT(Scheduler::shared());
|
| + }
|
| +
|
| + // WebThread::Task implementation.
|
| + virtual void run() OVERRIDE
|
| + {
|
| + Scheduler* scheduler = Scheduler::shared();
|
| + // FIXME: This check shouldn't be necessary, tasks should not outlive blink.
|
| + ASSERT(scheduler);
|
| + if (scheduler) {
|
| + scheduler->maybeRunPendingIdleTask();
|
| + // If possible, run the next idle task by reposting on the main thread.
|
| + scheduler->maybePostMainThreadPendingIdleTask();
|
| + }
|
| + }
|
| +
|
| +};
|
| +
|
| +
|
| Scheduler* Scheduler::s_sharedScheduler = nullptr;
|
|
|
| void Scheduler::initializeOnMainThread()
|
| @@ -118,6 +120,7 @@ Scheduler::Scheduler()
|
| : m_sharedTimerFunction(nullptr)
|
| , m_mainThread(blink::Platform::current()->currentThread())
|
| , m_compositorPriorityPolicyEndTimeSeconds(0)
|
| + , m_estimatedNextBeginFrameSeconds(0)
|
| , m_highPriorityTaskCount(0)
|
| , m_highPriorityTaskRunnerPosted(false)
|
| , m_schedulerPolicy(Normal)
|
| @@ -131,32 +134,37 @@ Scheduler::~Scheduler()
|
| }
|
| }
|
|
|
| -void Scheduler::willBeginFrame(const WebBeginFrameArgs& args)
|
| +void Scheduler::willBeginFrame(double estimatedNextBeginFrameSeconds)
|
| {
|
| - // TODO: Use frame deadline and interval to schedule idle tasks.
|
| + ASSERT(isMainThread());
|
| + m_currentFrameCommitted = false;
|
| + m_estimatedNextBeginFrameSeconds = estimatedNextBeginFrameSeconds;
|
| + // TODO: Schedule a deferred task here to run idle work if didCommitFrameToCompositor never gets called.
|
| }
|
|
|
| void Scheduler::didCommitFrameToCompositor()
|
| {
|
| - // TODO: Trigger the frame deadline immediately.
|
| -}
|
| -
|
| -void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
|
| -{
|
| - // TODO: send a real allottedTime here.
|
| - m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
|
| + ASSERT(isMainThread());
|
| + m_currentFrameCommitted = true;
|
| + maybePostMainThreadPendingIdleTask();
|
| }
|
|
|
| void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, const Task& task, const char* traceName)
|
| {
|
| Locker<Mutex> lock(m_pendingTasksMutex);
|
|
|
| - m_pendingHighPriorityTasks.append(TracedTask(task, location, traceName));
|
| + m_pendingHighPriorityTasks.append(TracedStandardTask(task, location, traceName));
|
| atomicIncrement(&m_highPriorityTaskCount);
|
| maybePostMainThreadPendingHighPriorityTaskRunner();
|
| TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
|
| }
|
|
|
| +void Scheduler::postIdleTaskInternal(const TraceLocation& location, const IdleTask& idleTask, const char* traceName)
|
| +{
|
| + Locker<Mutex> lock(m_pendingTasksMutex);
|
| + m_pendingIdleTasks.append(TracedIdleTask(idleTask, location, traceName));
|
| +}
|
| +
|
| void Scheduler::postTask(const TraceLocation& location, const Task& task)
|
| {
|
| m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::MainThreadTask"));
|
| @@ -184,6 +192,11 @@ void Scheduler::postIpcTask(const TraceLocation& location, const Task& task)
|
| m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::IpcTask"));
|
| }
|
|
|
| +void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
|
| +{
|
| + postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask");
|
| +}
|
| +
|
| void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
|
| {
|
| ASSERT(m_pendingTasksMutex.locked());
|
| @@ -193,9 +206,18 @@ void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
|
| m_highPriorityTaskRunnerPosted = true;
|
| }
|
|
|
| -void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
|
| +bool Scheduler::maybePostMainThreadPendingIdleTask()
|
| {
|
| - scheduleIdleTask(location, idleTask);
|
| + ASSERT(isMainThread());
|
| + TRACE_EVENT0("blink", "Scheduler::maybePostMainThreadPendingIdleTask");
|
| + if (canRunIdleTask()) {
|
| + Locker<Mutex> lock(m_pendingTasksMutex);
|
| + if (!m_pendingIdleTasks.isEmpty()) {
|
| + m_mainThread->postTask(new MainThreadPendingIdleTaskRunner());
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| }
|
|
|
| void Scheduler::tickSharedTimer()
|
| @@ -221,6 +243,23 @@ bool Scheduler::runPendingHighPriorityTasksIfInCompositorPriority()
|
| return swapQueuesAndRunPendingTasks();
|
| }
|
|
|
| +bool Scheduler::maybeRunPendingIdleTask()
|
| +{
|
| + ASSERT(isMainThread());
|
| + if (!canRunIdleTask())
|
| + return false;
|
| +
|
| + takeFirstPendingIdleTask().run();
|
| + return true;
|
| +}
|
| +
|
| +TracedIdleTask Scheduler::takeFirstPendingIdleTask()
|
| +{
|
| + Locker<Mutex> lock(m_pendingTasksMutex);
|
| + ASSERT(!m_pendingIdleTasks.isEmpty());
|
| + return m_pendingIdleTasks.takeFirst();
|
| +}
|
| +
|
| bool Scheduler::swapQueuesAndRunPendingTasks()
|
| {
|
| ASSERT(isMainThread());
|
| @@ -228,7 +267,7 @@ bool Scheduler::swapQueuesAndRunPendingTasks()
|
| // These locks guard against another thread posting input or compositor tasks while we swap the buffers.
|
| // 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();
|
| + Deque<TracedStandardTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
|
| maybeEnterNormalSchedulerPolicy();
|
| m_pendingTasksMutex.unlock();
|
| return executeHighPriorityTasks(highPriorityTasks);
|
| @@ -241,7 +280,7 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting()
|
| // These locks guard against another thread posting input or compositor tasks while we swap the buffers.
|
| // 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();
|
| + Deque<TracedStandardTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
|
| m_highPriorityTaskRunnerPosted = false;
|
| maybeEnterNormalSchedulerPolicy();
|
| m_pendingTasksMutex.unlock();
|
| @@ -258,7 +297,7 @@ void Scheduler::maybeEnterNormalSchedulerPolicy()
|
| enterSchedulerPolicyLocked(Normal);
|
| }
|
|
|
| -bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
|
| +bool Scheduler::executeHighPriorityTasks(Deque<TracedStandardTask>& highPriorityTasks)
|
| {
|
| TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
|
| int highPriorityTasksExecuted = 0;
|
| @@ -313,6 +352,21 @@ bool Scheduler::hasPendingHighPriorityWork() const
|
| return acquireLoad(&m_highPriorityTaskCount) != 0;
|
| }
|
|
|
| +double Scheduler::currentFrameDeadlineForIdleTasks() const
|
| +{
|
| + ASSERT(isMainThread());
|
| + // TODO: Make idle time more fine-grain chunks when in Compositor priority.
|
| + return m_estimatedNextBeginFrameSeconds;
|
| +}
|
| +
|
| +bool Scheduler::canRunIdleTask() const
|
| +{
|
| + ASSERT(isMainThread());
|
| + return m_currentFrameCommitted
|
| + && !shouldYieldForHighPriorityWork()
|
| + && (m_estimatedNextBeginFrameSeconds > Platform::current()->monotonicallyIncreasingTime());
|
| +}
|
| +
|
| Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
|
| {
|
| ASSERT(isMainThread());
|
|
|