| Index: Source/platform/scheduler/Scheduler.cpp
|
| diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp
|
| index 61ae7aef1d486bd618417a2d2d62c14c08db06bc..5bfe8b34c7a9acd128fb8abb5a59f4081083d0e1 100644
|
| --- a/Source/platform/scheduler/Scheduler.cpp
|
| +++ b/Source/platform/scheduler/Scheduler.cpp
|
| @@ -5,59 +5,103 @@
|
| #include "config.h"
|
| #include "platform/scheduler/Scheduler.h"
|
|
|
| +#include "platform/PlatformThreadData.h"
|
| #include "platform/Task.h"
|
| +#include "platform/ThreadTimers.h"
|
| #include "platform/TraceEvent.h"
|
| -#include "platform/TraceLocation.h"
|
| #include "public/platform/Platform.h"
|
| -#include "public/platform/WebThread.h"
|
| +#include "wtf/ThreadingPrimitives.h"
|
|
|
| namespace blink {
|
|
|
| namespace {
|
|
|
| -class MainThreadTaskAdapter : public blink::WebThread::Task {
|
| +class MainThreadIdleTaskAdapter : public WebThread::Task {
|
| public:
|
| - explicit MainThreadTaskAdapter(const TraceLocation& location, const Scheduler::Task& task)
|
| - : m_location(location)
|
| - , m_task(task)
|
| + 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", "MainThreadTaskAdapter::run",
|
| + TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run",
|
| "src_file", m_location.fileName(),
|
| "src_func", m_location.functionName());
|
| - m_task();
|
| + m_idleTask(m_allottedTimeMs);
|
| }
|
|
|
| private:
|
| - const TraceLocation m_location;
|
| - Scheduler::Task m_task;
|
| + Scheduler::IdleTask m_idleTask;
|
| + double m_allottedTimeMs;
|
| + TraceLocation m_location;
|
| };
|
|
|
| -class MainThreadIdleTaskAdapter : public blink::WebThread::Task {
|
| +} // namespace
|
| +
|
| +class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Task {
|
| public:
|
| - MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs)
|
| - : m_idleTask(idleTask)
|
| - , m_allottedTimeMs(allottedTimeMs)
|
| + MainThreadPendingHighPriorityTaskRunner()
|
| + {
|
| + ASSERT(Scheduler::shared());
|
| + Scheduler::shared()->incrementMainThreadTaskRunnerCount();
|
| + }
|
| +
|
| + ~MainThreadPendingHighPriorityTaskRunner()
|
| {
|
| + Scheduler* scheduler = Scheduler::shared();
|
| + if (!scheduler)
|
| + return;
|
| + Scheduler::shared()->decrementMainThreadTaskRunnerCount();
|
| }
|
|
|
| // WebThread::Task implementation.
|
| virtual void run() OVERRIDE
|
| {
|
| - TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs);
|
| - m_idleTask(m_allottedTimeMs);
|
| + Scheduler* scheduler = Scheduler::shared();
|
| + if (!scheduler)
|
| + return;
|
| + scheduler->runHighPriorityTasks();
|
| }
|
| -
|
| -private:
|
| - Scheduler::IdleTask m_idleTask;
|
| - double m_allottedTimeMs;
|
| };
|
|
|
| -}
|
| +class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task {
|
| +public:
|
| + MainThreadPendingTaskRunner(
|
| + const Scheduler::Task& task, const TraceLocation& location)
|
| + : m_task(task)
|
| + , m_location(location)
|
| + {
|
| + ASSERT(Scheduler::shared());
|
| + Scheduler::shared()->incrementMainThreadTaskRunnerCount();
|
| + }
|
| +
|
| + ~MainThreadPendingTaskRunner()
|
| + {
|
| + Scheduler* scheduler = Scheduler::shared();
|
| + if (!scheduler)
|
| + return;
|
| + Scheduler::shared()->decrementMainThreadTaskRunnerCount();
|
| + }
|
| +
|
| + // WebThread::Task implementation.
|
| + virtual void run() OVERRIDE
|
| + {
|
| + TRACE_EVENT2("blink", "MainThreadPendingTaskRunner::run",
|
| + "src_file", m_location.fileName(),
|
| + "src_func", m_location.functionName());
|
| + Scheduler* scheduler = Scheduler::shared();
|
| + if (scheduler)
|
| + Scheduler::shared()->runHighPriorityTasks();
|
| + m_task();
|
| + }
|
| +
|
| + Scheduler::Task m_task;
|
| + TraceLocation m_location;
|
| +};
|
|
|
| Scheduler* Scheduler::s_sharedScheduler = nullptr;
|
|
|
| @@ -80,48 +124,103 @@ Scheduler* Scheduler::shared()
|
| Scheduler::Scheduler()
|
| : m_mainThread(blink::Platform::current()->currentThread())
|
| , m_sharedTimerFunction(nullptr)
|
| + , m_mainThreadTaskRunnerCount(0)
|
| + , m_highPriotityTaskCount(0)
|
| {
|
| }
|
|
|
| Scheduler::~Scheduler()
|
| {
|
| + while (shouldYieldForHighPriorityWork()) {
|
| + runHighPriorityTasks();
|
| + }
|
| }
|
|
|
| -void Scheduler::scheduleTask(const TraceLocation& location, const Task& task)
|
| -{
|
| - m_mainThread->postTask(new MainThreadTaskAdapter(location, task));
|
| -}
|
| -
|
| -void Scheduler::scheduleIdleTask(const IdleTask& idleTask)
|
| +void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
|
| {
|
| // TODO: send a real allottedTime here.
|
| - m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0));
|
| + m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
|
| }
|
|
|
| void Scheduler::postTask(const TraceLocation& location, const Task& task)
|
| {
|
| - scheduleTask(location, task);
|
| + m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location));
|
| }
|
|
|
| void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
|
| {
|
| - scheduleTask(location, task);
|
| + Locker<Mutex> lock(m_pendingTasksMutex);
|
| + m_pendingInputTasks.append(TracedTask(task, location));
|
| + atomicIncrement(&m_highPriotityTaskCount);
|
| + maybePostMainThreadPendingHighPriorityTaskRunner();
|
| }
|
|
|
| void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task)
|
| {
|
| - scheduleTask(location, task);
|
| + Locker<Mutex> lock(m_pendingTasksMutex);
|
| + m_pendingCompositorTasks.append(TracedTask(task, location));
|
| + atomicIncrement(&m_highPriotityTaskCount);
|
| + maybePostMainThreadPendingHighPriorityTaskRunner();
|
| }
|
|
|
| -void Scheduler::postIdleTask(const IdleTask& idleTask)
|
| +void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
|
| {
|
| - scheduleIdleTask(idleTask);
|
| + scheduleIdleTask(location, idleTask);
|
| }
|
|
|
| void Scheduler::tickSharedTimer()
|
| {
|
| TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
|
| +
|
| + // Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately.
|
| + runHighPriorityTasks();
|
| 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.
|
| + runHighPriorityTasks();
|
| +}
|
| +
|
| +void Scheduler::runHighPriorityTasks()
|
| +{
|
| + TRACE_EVENT0("blink", "Scheduler::runHighPriorityTasks");
|
| +
|
| + m_pendingTasksMutex.lock();
|
| + Deque<TracedTask>& inputTasks = m_pendingInputTasks.swapBuffers();
|
| + Deque<TracedTask>& compositorTasks = m_pendingCompositorTasks.swapBuffers();
|
| + m_pendingTasksMutex.unlock();
|
| +
|
| + for (;;) {
|
| + if (!inputTasks.isEmpty()) {
|
| + inputTasks.takeFirst().run();
|
| + atomicDecrement(&m_highPriotityTaskCount);
|
| + continue;
|
| + }
|
| +
|
| + if (compositorTasks.isEmpty())
|
| + break;
|
| + compositorTasks.takeFirst().run();
|
| + atomicDecrement(&m_highPriotityTaskCount);
|
| + }
|
| +}
|
| +
|
| +void Scheduler::incrementMainThreadTaskRunnerCount()
|
| +{
|
| + atomicIncrement(&m_mainThreadTaskRunnerCount);
|
| +}
|
| +
|
| +void Scheduler::decrementMainThreadTaskRunnerCount()
|
| +{
|
| + atomicDecrement(&m_mainThreadTaskRunnerCount);
|
| +}
|
| +
|
| +void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
|
| +{
|
| + // Only post a task if there isn't a task already in flight.
|
| + if (acquireLoad(&m_mainThreadTaskRunnerCount))
|
| + return;
|
| +
|
| + m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
|
| }
|
|
|
| void Scheduler::sharedTimerAdapter()
|
| @@ -147,7 +246,15 @@ void Scheduler::stopSharedTimer()
|
|
|
| bool Scheduler::shouldYieldForHighPriorityWork()
|
| {
|
| - return false;
|
| + return acquireLoad(&m_highPriotityTaskCount) != 0;
|
| +}
|
| +
|
| +void Scheduler::TracedTask::run()
|
| +{
|
| + TRACE_EVENT2("blink", "TracedTask::run",
|
| + "src_file", m_location.fileName(),
|
| + "src_func", m_location.functionName());
|
| + m_task();
|
| }
|
|
|
| } // namespace blink
|
|
|