Adds the concept of Policies to the Blink Scheduler

In Normal mode (the default), there's virtually no 
prioritization of compositor events, and
shouldYieldForHighPriorityWork always returns false. In 
CompositorPriority mode, there *is* prioritization of 
compositor tasks and shouldYieldForHighPriorityWork will 
return false if there are pending high priority events.

Currently there is no way for client code to set the policy
but that will be introduced in a follow up CL.

Also adds some disabled by default tracing in
"blink.scheduler" to track the number of pending high
priority tasks and which policy mode the scheduler is in.

BUG=391005,411520

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

git-svn-id: svn://svn.chromium.org/blink/trunk@181818 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent cf6abd2d
...@@ -18,6 +18,9 @@ namespace blink { ...@@ -18,6 +18,9 @@ namespace blink {
namespace { namespace {
// The time we should stay in CompositorPriority mode for, after a touch event.
double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1;
// Can be created from any thread. // Can be created from any thread.
// Note if the scheduler gets shutdown, this may be run after. // Note if the scheduler gets shutdown, this may be run after.
class MainThreadIdleTaskAdapter : public WebThread::Task { class MainThreadIdleTaskAdapter : public WebThread::Task {
...@@ -63,6 +66,8 @@ public: ...@@ -63,6 +66,8 @@ public:
ASSERT(scheduler); ASSERT(scheduler);
if (!scheduler) if (!scheduler)
return; 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(); scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting();
} }
}; };
...@@ -86,7 +91,7 @@ public: ...@@ -86,7 +91,7 @@ public:
// FIXME: This check should't be necessary, tasks should not outlive blink. // FIXME: This check should't be necessary, tasks should not outlive blink.
ASSERT(scheduler); ASSERT(scheduler);
if (scheduler) if (scheduler)
Scheduler::shared()->swapQueuesAndRunPendingTasks(); Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority();
m_task.run(); m_task.run();
} }
...@@ -114,8 +119,10 @@ Scheduler* Scheduler::shared() ...@@ -114,8 +119,10 @@ Scheduler* Scheduler::shared()
Scheduler::Scheduler() Scheduler::Scheduler()
: m_sharedTimerFunction(nullptr) : m_sharedTimerFunction(nullptr)
, m_mainThread(blink::Platform::current()->currentThread()) , m_mainThread(blink::Platform::current()->currentThread())
, m_compositorPriorityPolicyEndTimeSeconds(0)
, m_highPriorityTaskCount(0) , m_highPriorityTaskCount(0)
, m_highPriorityTaskRunnerPosted(false) , m_highPriorityTaskRunnerPosted(false)
, m_schedulerPolicy(Normal)
{ {
} }
...@@ -153,6 +160,7 @@ void Scheduler::postInputTask(const TraceLocation& location, const Task& task) ...@@ -153,6 +160,7 @@ void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
m_pendingHighPriorityTasks.append(TracedTask(task, location)); m_pendingHighPriorityTasks.append(TracedTask(task, location));
atomicIncrement(&m_highPriorityTaskCount); atomicIncrement(&m_highPriorityTaskCount);
maybePostMainThreadPendingHighPriorityTaskRunner(); maybePostMainThreadPendingHighPriorityTaskRunner();
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
} }
void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task) void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task)
...@@ -161,6 +169,7 @@ void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta ...@@ -161,6 +169,7 @@ void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta
m_pendingHighPriorityTasks.append(TracedTask(task, location)); m_pendingHighPriorityTasks.append(TracedTask(task, location));
atomicIncrement(&m_highPriorityTaskCount); atomicIncrement(&m_highPriorityTaskCount);
maybePostMainThreadPendingHighPriorityTaskRunner(); maybePostMainThreadPendingHighPriorityTaskRunner();
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
} }
void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
...@@ -182,13 +191,22 @@ void Scheduler::tickSharedTimer() ...@@ -182,13 +191,22 @@ void Scheduler::tickSharedTimer()
TRACE_EVENT0("blink", "Scheduler::tickSharedTimer"); TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
// Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately. // Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately.
bool workDone = swapQueuesAndRunPendingTasks(); bool workDone = runPendingHighPriorityTasksIfInCompositorPriority();
m_sharedTimerFunction(); m_sharedTimerFunction();
// The blink timers may have just yielded, so run any high priority tasks that where queued up // The blink timers may have just yielded, so run any high priority tasks that where queued up
// while the blink timers were executing. // while the blink timers were executing.
if (!workDone) if (!workDone)
swapQueuesAndRunPendingTasks(); runPendingHighPriorityTasksIfInCompositorPriority();
}
bool Scheduler::runPendingHighPriorityTasksIfInCompositorPriority()
{
ASSERT(isMainThread());
if (schedulerPolicy() != CompositorPriority)
return false;
return swapQueuesAndRunPendingTasks();
} }
bool Scheduler::swapQueuesAndRunPendingTasks() bool Scheduler::swapQueuesAndRunPendingTasks()
...@@ -199,6 +217,7 @@ 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. // One the buffers have been swapped we can safely access the returned deque without having to lock.
m_pendingTasksMutex.lock(); m_pendingTasksMutex.lock();
Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
maybeEnterNormalSchedulerPolicy();
m_pendingTasksMutex.unlock(); m_pendingTasksMutex.unlock();
return executeHighPriorityTasks(highPriorityTasks); return executeHighPriorityTasks(highPriorityTasks);
} }
...@@ -212,10 +231,21 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting() ...@@ -212,10 +231,21 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting()
m_pendingTasksMutex.lock(); m_pendingTasksMutex.lock();
Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
m_highPriorityTaskRunnerPosted = false; m_highPriorityTaskRunnerPosted = false;
maybeEnterNormalSchedulerPolicy();
m_pendingTasksMutex.unlock(); m_pendingTasksMutex.unlock();
executeHighPriorityTasks(highPriorityTasks); 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) bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
{ {
TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks"); TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
...@@ -227,6 +257,7 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks) ...@@ -227,6 +257,7 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPriorityTasksExecuted); int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPriorityTasksExecuted);
ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0); ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0);
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
return highPriorityTasksExecuted > 0; return highPriorityTasksExecuted > 0;
} }
...@@ -253,6 +284,10 @@ void Scheduler::stopSharedTimer() ...@@ -253,6 +284,10 @@ void Scheduler::stopSharedTimer()
bool Scheduler::shouldYieldForHighPriorityWork() const bool Scheduler::shouldYieldForHighPriorityWork() const
{ {
// It's only worthwhile yielding in CompositorPriority mode.
if (schedulerPolicy() != CompositorPriority)
return false;
return hasPendingHighPriorityWork(); return hasPendingHighPriorityWork();
} }
...@@ -266,6 +301,31 @@ bool Scheduler::hasPendingHighPriorityWork() const ...@@ -266,6 +301,31 @@ bool Scheduler::hasPendingHighPriorityWork() const
return acquireLoad(&m_highPriorityTaskCount) != 0; 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() void Scheduler::TracedTask::run()
{ {
TRACE_EVENT2("blink", "TracedTask::run", TRACE_EVENT2("blink", "TracedTask::run",
......
...@@ -54,12 +54,17 @@ public: ...@@ -54,12 +54,17 @@ public:
void setSharedTimerFireInterval(double); void setSharedTimerFireInterval(double);
void stopSharedTimer(); void stopSharedTimer();
private: protected:
class MainThreadPendingTaskRunner; class MainThreadPendingTaskRunner;
class MainThreadPendingHighPriorityTaskRunner; class MainThreadPendingHighPriorityTaskRunner;
friend class MainThreadPendingTaskRunner; friend class MainThreadPendingTaskRunner;
friend class MainThreadPendingHighPriorityTaskRunner; friend class MainThreadPendingHighPriorityTaskRunner;
enum SchedulerPolicy {
Normal,
CompositorPriority,
};
class TracedTask { class TracedTask {
public: public:
TracedTask(const Task& task, const TraceLocation& location) TracedTask(const Task& task, const TraceLocation& location)
...@@ -74,37 +79,62 @@ private: ...@@ -74,37 +79,62 @@ private:
}; };
Scheduler(); Scheduler();
~Scheduler(); virtual ~Scheduler();
void scheduleIdleTask(const TraceLocation&, const IdleTask&);
static void sharedTimerAdapter(); static void sharedTimerAdapter();
void tickSharedTimer();
bool hasPendingHighPriorityWork() const;
// Start of main thread only members -----------------------------------
// Only does work in CompositorPriority mode. Returns true if any work was done.
bool runPendingHighPriorityTasksIfInCompositorPriority();
// Returns true if any work was done.
bool swapQueuesAndRunPendingTasks(); bool swapQueuesAndRunPendingTasks();
void swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting(); void swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting();
// Returns true if any work was done. // Returns true if any work was done.
bool executeHighPriorityTasks(Deque<TracedTask>&); bool executeHighPriorityTasks(Deque<TracedTask>&);
// Return the current SchedulerPolicy.
SchedulerPolicy schedulerPolicy() const;
void maybeEnterNormalSchedulerPolicy();
// Must be called while m_pendingTasksMutex is locked. // Must be called while m_pendingTasksMutex is locked.
void maybePostMainThreadPendingHighPriorityTaskRunner(); void maybePostMainThreadPendingHighPriorityTaskRunner();
static Scheduler* s_sharedScheduler; void tickSharedTimer();
// Should only be accessed from the main thread.
void (*m_sharedTimerFunction)(); void (*m_sharedTimerFunction)();
// These members can be accessed from any thread. // End of main thread only members -------------------------------------
void scheduleIdleTask(const TraceLocation&, const IdleTask&);
bool hasPendingHighPriorityWork() const;
void enterSchedulerPolicyLocked(SchedulerPolicy);
void enterSchedulerPolicy(SchedulerPolicy);
static Scheduler* s_sharedScheduler;
WebThread* m_mainThread; WebThread* m_mainThread;
// This mutex protects calls to the pending task queue and m_highPriorityTaskRunnerPosted. // This mutex protects calls to the pending task queue, m_highPriorityTaskRunnerPosted and
// m_compositorPriorityPolicyEndTimeSeconds.
Mutex m_pendingTasksMutex; Mutex m_pendingTasksMutex;
DoubleBufferedDeque<TracedTask> m_pendingHighPriorityTasks; DoubleBufferedDeque<TracedTask> m_pendingHighPriorityTasks;
double m_compositorPriorityPolicyEndTimeSeconds;
volatile int m_highPriorityTaskCount; volatile int m_highPriorityTaskCount;
bool m_highPriorityTaskRunnerPosted; bool m_highPriorityTaskRunnerPosted;
// Don't access m_schedulerPolicy directly, use enterSchedulerPolicyLocked and SchedulerPolicy instead.
volatile int m_schedulerPolicy;
}; };
} // namespace blink } // namespace blink
......
...@@ -19,6 +19,18 @@ using blink::Scheduler; ...@@ -19,6 +19,18 @@ using blink::Scheduler;
namespace { namespace {
class SchedulerForTest : public blink::Scheduler {
public:
static void initializeOnMainThread()
{
s_sharedScheduler = new SchedulerForTest();
}
using Scheduler::Normal;
using Scheduler::CompositorPriority;
using Scheduler::enterSchedulerPolicy;
};
class TestMainThread : public blink::WebThread { class TestMainThread : public blink::WebThread {
public: public:
// blink::WebThread implementation. // blink::WebThread implementation.
...@@ -75,6 +87,7 @@ public: ...@@ -75,6 +87,7 @@ public:
, m_sharedTimerFunction(nullptr) , m_sharedTimerFunction(nullptr)
, m_sharedTimerRunning(false) , m_sharedTimerRunning(false)
, m_sharedTimerFireInterval(0) , m_sharedTimerFireInterval(0)
, m_monotonicallyIncreasingTime(0)
{ {
} }
...@@ -89,6 +102,11 @@ public: ...@@ -89,6 +102,11 @@ public:
m_sharedTimerFunction = timerFunction; m_sharedTimerFunction = timerFunction;
} }
virtual double monotonicallyIncreasingTime() OVERRIDE
{
return m_monotonicallyIncreasingTime;
}
virtual void setSharedTimerFireInterval(double) virtual void setSharedTimerFireInterval(double)
{ {
m_sharedTimerFireInterval = 0; m_sharedTimerFireInterval = 0;
...@@ -125,11 +143,17 @@ public: ...@@ -125,11 +143,17 @@ public:
return m_mainThread.numPendingMainThreadTasks(); return m_mainThread.numPendingMainThreadTasks();
} }
void setMonotonicTimeForTest(double time)
{
m_monotonicallyIncreasingTime = time;
}
private: private:
TestMainThread m_mainThread; TestMainThread m_mainThread;
SharedTimerFunction m_sharedTimerFunction; SharedTimerFunction m_sharedTimerFunction;
bool m_sharedTimerRunning; bool m_sharedTimerRunning;
double m_sharedTimerFireInterval; double m_sharedTimerFireInterval;
double m_monotonicallyIncreasingTime;
}; };
class SchedulerTest : public testing::Test { class SchedulerTest : public testing::Test {
...@@ -138,8 +162,8 @@ public: ...@@ -138,8 +162,8 @@ public:
: m_reentrantCount(0) : m_reentrantCount(0)
, m_maxRecursion(4) , m_maxRecursion(4)
{ {
Scheduler::initializeOnMainThread(); SchedulerForTest::initializeOnMainThread();
m_scheduler = Scheduler::shared(); m_scheduler = static_cast<SchedulerForTest*>(Scheduler::shared());
} }
~SchedulerTest() ~SchedulerTest()
...@@ -147,6 +171,11 @@ public: ...@@ -147,6 +171,11 @@ public:
Scheduler::shutdown(); Scheduler::shutdown();
} }
virtual void SetUp() OVERRIDE
{
m_scheduler->enterSchedulerPolicy(SchedulerForTest::Normal);
}
void runPendingTasks() void runPendingTasks()
{ {
m_platformSupport.runPendingTasks(); m_platformSupport.runPendingTasks();
...@@ -186,7 +215,7 @@ public: ...@@ -186,7 +215,7 @@ public:
protected: protected:
SchedulerTestingPlatformSupport m_platformSupport; SchedulerTestingPlatformSupport m_platformSupport;
Scheduler* m_scheduler; SchedulerForTest* m_scheduler;
std::vector<std::string> m_order; std::vector<std::string> m_order;
std::vector<int> m_reentrantOrder; std::vector<int> m_reentrantOrder;
int m_reentrantCount; int m_reentrantCount;
...@@ -266,7 +295,7 @@ TEST_F(SchedulerTest, TestIdleTask) ...@@ -266,7 +295,7 @@ TEST_F(SchedulerTest, TestIdleTask)
EXPECT_EQ(4, result); EXPECT_EQ(4, result);
} }
TEST_F(SchedulerTest, TestTaskPrioritization) TEST_F(SchedulerTest, TestTaskPrioritization_normalPolicy)
{ {
m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L1"))); m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L1")));
m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L2"))); m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L2")));
...@@ -275,6 +304,21 @@ TEST_F(SchedulerTest, TestTaskPrioritization) ...@@ -275,6 +304,21 @@ TEST_F(SchedulerTest, TestTaskPrioritization)
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("I2"))); m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("I2")));
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("C2"))); m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("C2")));
runPendingTasks();
EXPECT_THAT(m_order, testing::ElementsAre(
std::string("L1"), std::string("L2"), std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2")));
}
TEST_F(SchedulerTest, TestTaskPrioritization_compositorPriorityPolicy)
{
m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L1")));
m_scheduler->postTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("L2")));
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("I1")));
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("C1")));
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("I2")));
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&SchedulerTest::appendToVector, this, std::string("C2")));
runPendingTasks(); runPendingTasks();
EXPECT_THAT(m_order, testing::ElementsAre( EXPECT_THAT(m_order, testing::ElementsAre(
std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2"), std::string("L1"), std::string("L2"))); std::string("I1"), std::string("C1"), std::string("I2"), std::string("C2"), std::string("L1"), std::string("L2")));
...@@ -383,9 +427,26 @@ void postDummyInputTask() ...@@ -383,9 +427,26 @@ void postDummyInputTask()
Scheduler::shared()->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); Scheduler::shared()->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
} }
TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring) TEST_F(SchedulerTest, HighPriorityTasksOnlyDontRunBecauseOfSharedTimerFiring_InNormalMode)
{
s_dummyTaskCount = 0;
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
// Trigger the posting of an input task during execution of the shared timer function.
m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask);
m_scheduler->setSharedTimerFireInterval(0);
m_platformSupport.triggerSharedTimer();
EXPECT_EQ(0, s_dummyTaskCount);
// Clean up.
m_scheduler->stopSharedTimer();
m_scheduler->setSharedTimerFiredFunction(nullptr);
}
TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring_InLowSchedulerPolicy)
{ {
s_dummyTaskCount = 0; s_dummyTaskCount = 0;
m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask)); m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
// Trigger the posting of an input task during execution of the shared timer function. // Trigger the posting of an input task during execution of the shared timer function.
m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask); m_scheduler->setSharedTimerFiredFunction(&postDummyInputTask);
...@@ -399,4 +460,49 @@ TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring) ...@@ -399,4 +460,49 @@ TEST_F(SchedulerTest, HighPriorityTasksOnlyRunOncePerSharedTimerFiring)
m_scheduler->setSharedTimerFiredFunction(nullptr); m_scheduler->setSharedTimerFiredFunction(nullptr);
} }
TEST_F(SchedulerTest, TestInputEventDoesNotTriggerShouldYield_InNormalMode)
{
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
}
TEST_F(SchedulerTest, TestCompositorEventDoesNotTriggerShouldYield_InNormalMode)
{
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
}
TEST_F(SchedulerTest, TestInputEventDoesTriggerShouldYield_InLowSchedulerPolicy)
{
m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork());
}
TEST_F(SchedulerTest, TestCompositorEventDoesTriggerShouldYield_InLowSchedulerPolicy)
{
m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
EXPECT_TRUE(m_scheduler->shouldYieldForHighPriorityWork());
}
TEST_F(SchedulerTest, TestCompositorEvent_LowSchedulerPolicyDoesntLastLong)
{
m_platformSupport.setMonotonicTimeForTest(1000.0);
m_scheduler->enterSchedulerPolicy(SchedulerForTest::CompositorPriority);
m_scheduler->postInputTask(FROM_HERE, WTF::bind(&dummyTask));
m_platformSupport.setMonotonicTimeForTest(1000.5);
runPendingTasks();
ASSERT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
m_scheduler->postCompositorTask(FROM_HERE, WTF::bind(&dummyTask));
EXPECT_FALSE(m_scheduler->shouldYieldForHighPriorityWork());
}
} // namespace } // namespace
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