Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: Source/platform/scheduler/Scheduler.cpp

Issue 439923006: Prioritizing input and compositor tasks in the blink scheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "platform/scheduler/Scheduler.h" 6 #include "platform/scheduler/Scheduler.h"
7 7
8 #include "platform/PlatformThreadData.h"
8 #include "platform/Task.h" 9 #include "platform/Task.h"
10 #include "platform/ThreadTimers.h"
9 #include "platform/TraceEvent.h" 11 #include "platform/TraceEvent.h"
10 #include "platform/TraceLocation.h"
11 #include "public/platform/Platform.h" 12 #include "public/platform/Platform.h"
12 #include "public/platform/WebThread.h" 13 #include "public/platform/WebThread.h"
14 #include "wtf/Atomics.h"
13 15
14 namespace blink { 16 namespace blink {
15 17
16 namespace { 18 namespace {
17 19
18 class MainThreadTaskAdapter : public blink::WebThread::Task {
19 public:
20 explicit MainThreadTaskAdapter(const TraceLocation& location, const Schedule r::Task& task)
21 : m_location(location)
22 , m_task(task)
23 {
24 }
25
26 // WebThread::Task implementation.
27 virtual void run() OVERRIDE
28 {
29 TRACE_EVENT2("blink", "MainThreadTaskAdapter::run",
30 "src_file", m_location.fileName(),
31 "src_func", m_location.functionName());
32 m_task();
33 }
34
35 private:
36 const TraceLocation m_location;
37 Scheduler::Task m_task;
38 };
39
40 class MainThreadIdleTaskAdapter : public blink::WebThread::Task { 20 class MainThreadIdleTaskAdapter : public blink::WebThread::Task {
41 public: 21 public:
42 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs) 22 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs)
43 : m_idleTask(idleTask) 23 : m_idleTask(idleTask)
44 , m_allottedTimeMs(allottedTimeMs) 24 , m_allottedTimeMs(allottedTimeMs)
45 { 25 {
46 } 26 }
47 27
48 // WebThread::Task implementation. 28 // WebThread::Task implementation.
49 virtual void run() OVERRIDE 29 virtual void run() OVERRIDE
50 { 30 {
51 TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs); 31 TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs);
52 m_idleTask(m_allottedTimeMs); 32 m_idleTask(m_allottedTimeMs);
53 } 33 }
54 34
55 private: 35 private:
56 Scheduler::IdleTask m_idleTask; 36 Scheduler::IdleTask m_idleTask;
57 double m_allottedTimeMs; 37 double m_allottedTimeMs;
58 }; 38 };
59 39
40 class MainThreadPendingTaskRunner : public blink::WebThread::Task {
41 public:
42 // WebThread::Task implementation.
43 virtual void run() OVERRIDE
44 {
45 Scheduler::shared()->runPendingTasks();
46 Scheduler::shared()->allowMainThreadTaskPosting();
47 }
48 };
49
60 } 50 }
61 51
62 Scheduler* Scheduler::s_sharedScheduler = nullptr; 52 Scheduler* Scheduler::s_sharedScheduler = nullptr;
63 53
64 void Scheduler::initializeOnMainThread() 54 void Scheduler::initializeOnMainThread()
65 { 55 {
66 s_sharedScheduler = new Scheduler(); 56 s_sharedScheduler = new Scheduler();
67 } 57 }
68 58
69 void Scheduler::shutdown() 59 void Scheduler::shutdown()
70 { 60 {
71 delete s_sharedScheduler; 61 delete s_sharedScheduler;
72 s_sharedScheduler = nullptr; 62 s_sharedScheduler = nullptr;
73 } 63 }
74 64
75 Scheduler* Scheduler::shared() 65 Scheduler* Scheduler::shared()
76 { 66 {
77 return s_sharedScheduler; 67 return s_sharedScheduler;
78 } 68 }
79 69
80 Scheduler::Scheduler() 70 Scheduler::Scheduler()
81 : m_mainThread(blink::Platform::current()->currentThread()) 71 : m_mainThread(blink::Platform::current()->currentThread())
72 , m_mainThreadTaskPosted(0)
73 , m_blinkShouldNotYield(1)
82 , m_sharedTimerFunction(nullptr) 74 , m_sharedTimerFunction(nullptr)
83 { 75 {
84 } 76 }
85 77
86 Scheduler::~Scheduler() 78 Scheduler::~Scheduler()
87 { 79 {
88 } 80 runPendingTasks();
89
90 void Scheduler::scheduleTask(const TraceLocation& location, const Task& task)
91 {
92 m_mainThread->postTask(new MainThreadTaskAdapter(location, task));
93 } 81 }
94 82
95 void Scheduler::scheduleIdleTask(const IdleTask& idleTask) 83 void Scheduler::scheduleIdleTask(const IdleTask& idleTask)
96 { 84 {
97 // TODO: send a real allottedTime here. 85 // TODO: send a real allottedTime here.
98 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0)); 86 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0));
99 } 87 }
100 88
101 void Scheduler::postTask(const TraceLocation& location, const Task& task) 89 void Scheduler::postTask(const TraceLocation& location, const Task& task)
102 { 90 {
103 scheduleTask(location, task); 91 m_pendingBlinkTasks.append(TracedTask(task, location));
92 maybePostTaskLoopOnMainThread();
104 } 93 }
105 94
106 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) 95 void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
107 { 96 {
108 scheduleTask(location, task); 97 m_pendingInputTasks.pushMaySpinlock(new TracedTask(task, location));
98 maybePostTaskLoopOnMainThread();
99
100 setBlinkShouldYield();
109 } 101 }
110 102
111 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) 103 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk)
112 { 104 {
113 scheduleTask(location, task); 105 m_pendingCompositorTasks.pushMaySpinlock(new TracedTask(task, location));
106 maybePostTaskLoopOnMainThread();
107
108 setBlinkShouldYield();
114 } 109 }
115 110
116 void Scheduler::postIdleTask(const IdleTask& idleTask) 111 void Scheduler::postIdleTask(const IdleTask& idleTask)
117 { 112 {
118 scheduleIdleTask(idleTask); 113 scheduleIdleTask(idleTask);
119 } 114 }
120 115
121 void Scheduler::tickSharedTimer() 116 void Scheduler::tickSharedTimer()
122 { 117 {
123 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer"); 118 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
119
120 // Execute any pending tasks.
121 if (shouldYieldForHighPriorityWork())
122 runPendingTasks();
123
124 m_sharedTimerFunction(); 124 m_sharedTimerFunction();
125 } 125 }
126 126
127 void Scheduler::runPendingTasks()
128 {
129 TRACE_EVENT0("blink", "Scheduler::runPendingTasks");
130
131 // Execute tasks from the queues in order of priority.
132 for (;;) {
133 TracedTask* task = m_pendingInputTasks.pop();
Sami 2014/08/06 10:19:52 How about making this slightly safer by wrapping t
alexclarke 2014/08/07 12:08:06 Done.
134 if (task) {
135 task->run();
136 delete task;
137 continue;
138 }
139
140 task = m_pendingCompositorTasks.pop();
141 if (task) {
142 task->run();
143 delete task;
144 continue;
145 }
146
147 if (m_pendingBlinkTasks.isEmpty())
148 break;
149
150 m_pendingBlinkTasks.takeFirst().run();
Sami 2014/08/06 10:19:52 It seems like it's possible for low priority tasks
alexclarke 2014/08/07 12:08:06 It's also possible for compositor tasks to do some
151 }
152
153 clearBlinkShouldYield();
154 }
155
156 void Scheduler::maybePostTaskLoopOnMainThread()
157 {
158 if (atomicTestAndSetToOne(&m_mainThreadTaskPosted))
159 return;
160
161 m_mainThread->postTask(new MainThreadPendingTaskRunner());
162 }
163
164 void Scheduler::allowMainThreadTaskPosting()
165 {
166 // Allow posting of the main thread task again.
167 atomicSetOneToZero(&m_mainThreadTaskPosted);
168 }
169
170 void Scheduler::setBlinkShouldYield()
171 {
172 atomicSetOneToZero(&m_blinkShouldNotYield);
173 }
174
175 void Scheduler::clearBlinkShouldYield()
176 {
177 atomicTestAndSetToOne(&m_blinkShouldNotYield);
178 }
179
127 void Scheduler::sharedTimerAdapter() 180 void Scheduler::sharedTimerAdapter()
128 { 181 {
129 shared()->tickSharedTimer(); 182 shared()->tickSharedTimer();
130 } 183 }
131 184
132 void Scheduler::setSharedTimerFiredFunction(void (*function)()) 185 void Scheduler::setSharedTimerFiredFunction(void (*function)())
133 { 186 {
134 m_sharedTimerFunction = function; 187 m_sharedTimerFunction = function;
135 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr); 188 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr);
136 } 189 }
137 190
138 void Scheduler::setSharedTimerFireInterval(double interval) 191 void Scheduler::setSharedTimerFireInterval(double interval)
139 { 192 {
140 blink::Platform::current()->setSharedTimerFireInterval(interval); 193 blink::Platform::current()->setSharedTimerFireInterval(interval);
141 } 194 }
142 195
143 void Scheduler::stopSharedTimer() 196 void Scheduler::stopSharedTimer()
144 { 197 {
145 blink::Platform::current()->stopSharedTimer(); 198 blink::Platform::current()->stopSharedTimer();
146 } 199 }
147 200
148 bool Scheduler::shouldYieldForHighPriorityWork() 201 bool Scheduler::shouldYieldForHighPriorityWork()
149 { 202 {
150 return false; 203 return !atomicTestAndSetToOne(&m_blinkShouldNotYield);
204 }
205
206 void Scheduler::TracedTask::run()
207 {
208 TRACE_EVENT2("blink", "TracedTask::run",
209 "src_file", m_location.fileName(),
210 "src_func", m_location.functionName());
211 m_task();
151 } 212 }
152 213
153 } // namespace blink 214 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698