Commit 64fc75b6 authored by skyostil@chromium.org's avatar skyostil@chromium.org

Use the scheduling mechanism provided by the platform

This uses the newly added WebScheduler interface for posting idle
tasks and checking whether main thread work should yield to let
more critical tasks run. This interface is implemented by the platform.

Design doc: https://docs.google.com/a/chromium.org/document/d/16f_RIhZa47uEK_OdtTgzWdRU0RFMTQWMpEWyWXIpXUo/edit#heading=h.srz53flt1rrp

BUG=391005

Review URL: https://codereview.chromium.org/656463004

git-svn-id: svn://svn.chromium.org/blink/trunk@184374 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 2c9b6d1c
......@@ -26,24 +26,23 @@
#include "config.h"
#include "platform/SharedTimer.h"
#include "platform/scheduler/Scheduler.h"
#include "public/platform/Platform.h"
namespace blink {
void setSharedTimerFiredFunction(void (*f)())
{
Scheduler::shared()->setSharedTimerFiredFunction(f);
Platform::current()->setSharedTimerFiredFunction(f);
}
void setSharedTimerFireInterval(double fireTime)
{
Scheduler::shared()->setSharedTimerFireInterval(fireTime);
Platform::current()->setSharedTimerFireInterval(fireTime);
}
void stopSharedTimer()
{
Scheduler::shared()->stopSharedTimer();
Platform::current()->stopSharedTimer();
}
} // namespace blink
......@@ -5,6 +5,8 @@
#ifndef TraceLocation_h
#define TraceLocation_h
#include "public/platform/WebTraceLocation.h"
// This is intentionally similar to base/location.h
// that we could easily replace usage of TraceLocation
// with base::Location after merging into Chromium.
......@@ -13,7 +15,7 @@ namespace blink {
class TraceLocation {
public:
// Currenetly only store the bits used in Blink, base::Location stores more.
// Currently only store the bits used in Blink, base::Location stores more.
// These char*s are not copied and must live for the duration of the program.
TraceLocation(const char* functionName, const char* fileName)
: m_functionName(functionName)
......@@ -28,6 +30,11 @@ public:
const char* functionName() const { return m_functionName; }
const char* fileName() const { return m_fileName; }
WebTraceLocation toWebTraceLocation() const
{
return WebTraceLocation(m_functionName, m_fileName);
}
private:
const char* m_functionName;
const char* m_fileName;
......
......@@ -743,8 +743,6 @@
'plugins/PluginListBuilder.h',
'scheduler/Scheduler.cpp',
'scheduler/Scheduler.h',
'scheduler/TracedTask.cpp',
'scheduler/TracedTask.h',
'scroll/ProgrammaticScrollAnimator.cpp',
'scroll/ProgrammaticScrollAnimator.h',
'scroll/ScrollAnimator.cpp',
......
......@@ -6,15 +6,12 @@
#define Scheduler_h
#include "platform/PlatformExport.h"
#include "platform/scheduler/TracedTask.h"
#include "wtf/DoubleBufferedDeque.h"
#include "wtf/Functional.h"
#include "wtf/Noncopyable.h"
#include "wtf/ThreadingPrimitives.h"
namespace blink {
class WebThread;
struct WebBeginFrameArgs;
class TraceLocation;
class WebScheduler;
// The scheduler is an opinionated gateway for arranging work to be run on the
// main thread. It decides which tasks get priority over others based on a
......@@ -22,123 +19,27 @@ struct WebBeginFrameArgs;
class PLATFORM_EXPORT Scheduler {
WTF_MAKE_NONCOPYABLE(Scheduler);
public:
typedef Function<void()> Task;
// An IdleTask is passed a deadline in CLOCK_MONOTONIC seconds and is expected to complete before this deadline.
typedef Function<void(double deadlineSeconds)> IdleTask;
static Scheduler* shared();
static void initializeOnMainThread();
static void shutdown();
// Called to notify about the start of a new frame.
void willBeginFrame(double estimatedNextBeginFrameSeconds);
// Called to notify that a previously begun frame was committed.
void didCommitFrameToCompositor();
// The following entrypoints are used to schedule different types of tasks
// to be run on the main thread. They can be called from any thread.
void postInputTask(const TraceLocation&, const Task&);
void postCompositorTask(const TraceLocation&, const Task&);
void postIpcTask(const TraceLocation&, const Task&);
void postTask(const TraceLocation&, const Task&); // For generic (low priority) tasks.
// For non-critical tasks which may be reordered relative to other task types and may be starved
// for an arbitrarily long time if no idle time is available.
void postIdleTask(const TraceLocation&, const IdleTask&);
// Tells the scheduler that the system received an input event. This causes the scheduler to go into
// Compositor Priority mode for a short duration.
void didReceiveInputEvent();
// Returns true if there is high priority work pending on the main thread
// and the caller should yield to let the scheduler service that work.
// Can be called on any thread.
// Must be called on the main thread.
bool shouldYieldForHighPriorityWork() const;
// The shared timer can be used to schedule a periodic callback which may
// get preempted by higher priority work.
void setSharedTimerFiredFunction(void (*function)());
void setSharedTimerFireInterval(double);
void stopSharedTimer();
// Returns the deadline, in CLOCK_MONOTONIC seconds, which an idle task should
// finish by for the current frame.
double currentFrameDeadlineForIdleTasks() const;
protected:
class MainThreadPendingTaskRunner;
class MainThreadPendingHighPriorityTaskRunner;
class MainThreadPendingIdleTaskRunner;
friend class MainThreadPendingTaskRunner;
friend class MainThreadPendingHighPriorityTaskRunner;
enum SchedulerPolicy {
Normal,
CompositorPriority,
};
Scheduler();
Scheduler(WebScheduler*);
virtual ~Scheduler();
void postHighPriorityTaskInternal(const TraceLocation&, const Task&, const char* traceName);
void postIdleTaskInternal(const TraceLocation&, const IdleTask&, const char* traceName);
void didRunHighPriorityTask();
static void sharedTimerAdapter();
// Start of main thread only members -----------------------------------
// Only does work in CompositorPriority mode. Returns true if any work was done.
bool runPendingHighPriorityTasksIfInCompositorPriority();
// Returns true if an idle task was posted to the main thread for execution.
bool maybePostMainThreadPendingIdleTask();
// Only does work if canRunIdleTask. Returns true if any work was done.
bool maybeRunPendingIdleTask();
// Returns true if the scheduler can run idle tasks at this time.
bool canRunIdleTask() const;
// Flush the incoming idle tasks to the end of the pending idle task queue.
void flushIncomingIdleTasks();
// Return the current SchedulerPolicy.
SchedulerPolicy schedulerPolicy() const;
void updatePolicy();
void tickSharedTimer();
void (*m_sharedTimerFunction)();
// End of main thread only members -------------------------------------
void enterSchedulerPolicyLocked(SchedulerPolicy);
void enterSchedulerPolicy(SchedulerPolicy);
static Scheduler* s_sharedScheduler;
WebThread* m_mainThread;
// This mutex protects calls to the incoming idle task queue.
Mutex m_incomingIdleTasksMutex;
Deque<OwnPtr<internal::TracedIdleTask>> m_incomingIdleTasks;
bool m_currentFrameCommitted;
double m_estimatedNextBeginFrameSeconds;
Deque<OwnPtr<internal::TracedIdleTask>> m_pendingIdleTasks;
// Declared volatile as it is atomically incremented.
volatile int m_highPriorityTaskCount;
bool m_highPriorityTaskRunnerPosted;
Mutex m_policyStateMutex;
double m_compositorPriorityPolicyEndTimeSeconds;
// Don't access m_schedulerPolicy directly, use enterSchedulerPolicyLocked and schedulerPolicy instead.
volatile int m_schedulerPolicy;
WebScheduler* m_webScheduler;
};
} // namespace blink
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "platform/scheduler/TracedTask.h"
#include "platform/scheduler/Scheduler.h"
#include "wtf/PassOwnPtr.h"
namespace blink {
namespace internal {
volatile int TracedTask::s_nextFlowTraceID = 0;
TracedTask::TracedTask(const TraceLocation& location, const char* traceName)
: m_location(location)
, m_traceName(traceName)
{
bool tracingEnabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink", &tracingEnabled);
if (tracingEnabled) {
// atomicIncrement is slow so we only do it if tracing is enabled
m_flowTraceID = static_cast<uint64_t>(atomicIncrement(&s_nextFlowTraceID));
TRACE_EVENT_FLOW_BEGIN2("blink", m_traceName, MANGLE(m_flowTraceID),
"src_file", m_location.fileName(),
"src_func", m_location.functionName());
}
}
TraceLocation TracedTask::getLocation() const
{
return m_location;
}
const char* TracedTask::getTraceName() const
{
return m_traceName;
}
void TracedTask::endFlowTraceEvent() const
{
TRACE_EVENT_FLOW_END0("blink", m_traceName, MANGLE(m_flowTraceID));
}
TracedTask::~TracedTask() { }
TracedStandardTask::TracedStandardTask(const Task& task, const TraceLocation& location, const char* traceName)
: TracedTask(location, traceName)
, m_task(task) { }
TracedStandardTask::~TracedStandardTask() { }
// static
PassOwnPtr<TracedStandardTask> TracedStandardTask::Create(const Task& task, const TraceLocation& location, const char* traceName)
{
return adoptPtr(new TracedStandardTask(task, location, traceName));
}
void TracedStandardTask::run() const
{
endFlowTraceEvent();
TRACE_EVENT2("blink", getTraceName(),
"src_file", getLocation().fileName(),
"src_func", getLocation().functionName());
m_task();
}
TracedIdleTask::TracedIdleTask(const IdleTask& idleTask, const TraceLocation& location, const char* traceName)
: TracedTask(location, traceName)
, m_idleTask(idleTask)
{
ASSERT(Scheduler::shared());
}
TracedIdleTask::~TracedIdleTask() { }
// static
PassOwnPtr<TracedIdleTask> TracedIdleTask::Create(const IdleTask& idleTask, const TraceLocation& location, const char* traceName)
{
return adoptPtr(new TracedIdleTask(idleTask, location, traceName));
}
void TracedIdleTask::run() const
{
endFlowTraceEvent();
TRACE_EVENT2("blink", getTraceName(),
"src_file", getLocation().fileName(),
"src_func", getLocation().functionName());
m_idleTask(Scheduler::shared()->currentFrameDeadlineForIdleTasks());
}
} // namespace internal
} // namespace blink
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TracedTask_h
#define TracedTask_h
#include "platform/Task.h"
#include "platform/TraceEvent.h"
#include "platform/TraceLocation.h"
namespace blink {
namespace internal {
#ifdef MANGLE_COMPILES_ON_WIN_OK
// TODO: Once win version compiles correctly when using TRACE_ID_MANGLE remove
// the ifdef to always mangle
#define MANGLE(id) TRACE_ID_MANGLE(id)
#else
#define MANGLE(id) (id)
#endif
class TracedTask {
public:
virtual void run() const = 0;
virtual ~TracedTask();
protected:
TracedTask(const TraceLocation&, const char* traceName);
TraceLocation getLocation() const;
const char* getTraceName() const;
void endFlowTraceEvent() const;
private:
// Declared volatile as it is atomically incremented.
static volatile int s_nextFlowTraceID;
uint64_t m_flowTraceID;
TraceLocation m_location;
const char* m_traceName;
};
class TracedStandardTask : public TracedTask {
public:
typedef Function<void()> Task;
static PassOwnPtr<TracedStandardTask> Create(const Task&, const TraceLocation&, const char* traceName);
virtual void run() const;
virtual ~TracedStandardTask();
private:
TracedStandardTask(const Task&, const TraceLocation&, const char* traceName);
Task m_task;
};
class TracedIdleTask : public TracedTask {
public:
typedef Function<void(double deadlineSeconds)> IdleTask;
static PassOwnPtr<TracedIdleTask> Create(const IdleTask&, const TraceLocation&, const char* traceName);
virtual void run() const;
virtual ~TracedIdleTask();
private:
TracedIdleTask(const IdleTask&, const TraceLocation&, const char* traceName);
IdleTask m_idleTask;
};
} // namespace internal
} // namespace blink
#endif // TracedTask_h
......@@ -148,7 +148,6 @@ void initializeWithoutV8(Platform* platform)
WTF::initialize(currentTimeFunction, monotonicallyIncreasingTimeFunction);
WTF::initializeMainThread(callOnMainThreadFunction);
Heap::init();
Scheduler::initializeOnMainThread();
ThreadState::attachMainThread();
// currentThread will always be non-null in production, but can be null in Chromium unit tests.
......
......@@ -112,7 +112,6 @@
#include "platform/graphics/FirstPaintInvalidationTracking.h"
#include "platform/graphics/Image.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/scheduler/Scheduler.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "public/platform/Platform.h"
......@@ -1849,8 +1848,6 @@ void WebViewImpl::beginFrame(const WebBeginFrameArgs& frameTime)
if (!validFrameTime.lastFrameTimeMonotonic)
validFrameTime.lastFrameTimeMonotonic = monotonicallyIncreasingTime();
Scheduler::shared()->willBeginFrame(validFrameTime.lastFrameTimeMonotonic + validFrameTime.interval);
// Create synthetic wheel events as necessary for fling.
if (m_gestureAnimation) {
if (m_gestureAnimation->animate(validFrameTime.lastFrameTimeMonotonic))
......@@ -1882,7 +1879,7 @@ void WebViewImpl::beginFrame(const WebBeginFrameArgs& frameTime)
void WebViewImpl::didCommitFrameToCompositor()
{
Scheduler::shared()->didCommitFrameToCompositor();
// TODO: Remove this function.
}
void WebViewImpl::layout()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment