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

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: Responding to Sami's feedback 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 "wtf/ThreadingPrimitives.h"
13 14
14 namespace blink { 15 namespace blink {
15 16
16 namespace { 17 namespace {
17 18
18 class MainThreadTaskAdapter : public blink::WebThread::Task { 19 // Can be created from any thread.
20 // Note if the scheduler gets shutdown, this may be run after.
21 class MainThreadIdleTaskAdapter : public WebThread::Task {
19 public: 22 public:
20 explicit MainThreadTaskAdapter(const TraceLocation& location, const Schedule r::Task& task) 23 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs, const TraceLocation& location)
21 : m_location(location) 24 : m_idleTask(idleTask)
22 , m_task(task) 25 , m_allottedTimeMs(allottedTimeMs)
26 , m_location(location)
23 { 27 {
24 } 28 }
25 29
26 // WebThread::Task implementation. 30 // WebThread::Task implementation.
27 virtual void run() OVERRIDE 31 virtual void run() OVERRIDE
28 { 32 {
29 TRACE_EVENT2("blink", "MainThreadTaskAdapter::run", 33 TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run",
30 "src_file", m_location.fileName(), 34 "src_file", m_location.fileName(),
31 "src_func", m_location.functionName()); 35 "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 {
41 public:
42 MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allott edTimeMs)
43 : m_idleTask(idleTask)
44 , m_allottedTimeMs(allottedTimeMs)
45 {
46 }
47
48 // WebThread::Task implementation.
49 virtual void run() OVERRIDE
50 {
51 TRACE_EVENT1("blink", "MainThreadIdleTaskAdapter::run", "allottedTime", m_allottedTimeMs);
52 m_idleTask(m_allottedTimeMs); 36 m_idleTask(m_allottedTimeMs);
53 } 37 }
54 38
55 private: 39 private:
56 Scheduler::IdleTask m_idleTask; 40 Scheduler::IdleTask m_idleTask;
57 double m_allottedTimeMs; 41 double m_allottedTimeMs;
42 TraceLocation m_location;
58 }; 43 };
59 44
60 } 45 } // namespace
46
47 // Typically only created from compositor or render threads.
48 // Note if the scheduler gets shutdown, this may be run after.
49 class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Tas k {
50 public:
51 MainThreadPendingHighPriorityTaskRunner()
52 {
53 ASSERT(Scheduler::shared());
54 }
55
56 // WebThread::Task implementation.
57 virtual void run() OVERRIDE
58 {
59 Scheduler* scheduler = Scheduler::shared();
eseidel 2014/08/12 16:16:01 We should add a FIXME that this should be removed
alexclarke 2014/08/13 10:08:58 Done.
60 if (!scheduler)
61 return;
62 scheduler->runHighPriorityTasks();
63 }
64 };
65
66
67 // Can be created from any thread.
68 // Note if the scheduler gets shutdown, this may be run after.
69 class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task {
70 public:
71 MainThreadPendingTaskRunner(
72 const Scheduler::Task& task, const TraceLocation& location)
73 : m_task(task, location)
74 {
75 ASSERT(Scheduler::shared());
76 }
77
78 // WebThread::Task implementation.
79 virtual void run() OVERRIDE
80 {
81 Scheduler* scheduler = Scheduler::shared();
82 // This will assert if a posted task outlives blink, which is probably a bug.
83 ASSERT(scheduler);
84 if (scheduler)
85 Scheduler::shared()->runHighPriorityTasks();
86 m_task.run();
87 }
88
89 Scheduler::TracedTask m_task;
90 };
61 91
62 Scheduler* Scheduler::s_sharedScheduler = nullptr; 92 Scheduler* Scheduler::s_sharedScheduler = nullptr;
63 93
64 void Scheduler::initializeOnMainThread() 94 void Scheduler::initializeOnMainThread()
65 { 95 {
66 s_sharedScheduler = new Scheduler(); 96 s_sharedScheduler = new Scheduler();
67 } 97 }
68 98
69 void Scheduler::shutdown() 99 void Scheduler::shutdown()
70 { 100 {
71 delete s_sharedScheduler; 101 delete s_sharedScheduler;
72 s_sharedScheduler = nullptr; 102 s_sharedScheduler = nullptr;
73 } 103 }
74 104
75 Scheduler* Scheduler::shared() 105 Scheduler* Scheduler::shared()
76 { 106 {
77 return s_sharedScheduler; 107 return s_sharedScheduler;
78 } 108 }
79 109
80 Scheduler::Scheduler() 110 Scheduler::Scheduler()
81 : m_mainThread(blink::Platform::current()->currentThread()) 111 : m_sharedTimerFunction(nullptr)
82 , m_sharedTimerFunction(nullptr) 112 , m_mainThread(blink::Platform::current()->currentThread())
113 , m_highPriorityTaskCount(0)
83 { 114 {
84 } 115 }
85 116
86 Scheduler::~Scheduler() 117 Scheduler::~Scheduler()
87 { 118 {
119 while (hasPendingHighPriorityWork()) {
120 runHighPriorityTasks();
121 }
88 } 122 }
89 123
90 void Scheduler::scheduleTask(const TraceLocation& location, const Task& task) 124 void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
91 {
92 m_mainThread->postTask(new MainThreadTaskAdapter(location, task));
93 }
94
95 void Scheduler::scheduleIdleTask(const IdleTask& idleTask)
96 { 125 {
97 // TODO: send a real allottedTime here. 126 // TODO: send a real allottedTime here.
98 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0)); 127 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)) ;
99 } 128 }
100 129
101 void Scheduler::postTask(const TraceLocation& location, const Task& task) 130 void Scheduler::postTask(const TraceLocation& location, const Task& task)
102 { 131 {
103 scheduleTask(location, task); 132 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location));
104 } 133 }
105 134
106 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) 135 void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
107 { 136 {
108 scheduleTask(location, task); 137 Locker<Mutex> lock(m_pendingTasksMutex);
138 m_pendingInputTasks.append(TracedTask(task, location));
139 atomicIncrement(&m_highPriorityTaskCount);
140 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
109 } 141 }
110 142
111 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) 143 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk)
112 { 144 {
113 scheduleTask(location, task); 145 Locker<Mutex> lock(m_pendingTasksMutex);
146 m_pendingCompositorTasks.append(TracedTask(task, location));
147 atomicIncrement(&m_highPriorityTaskCount);
148 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
114 } 149 }
115 150
116 void Scheduler::postIdleTask(const IdleTask& idleTask) 151 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idle Task)
117 { 152 {
118 scheduleIdleTask(idleTask); 153 scheduleIdleTask(location, idleTask);
119 } 154 }
120 155
121 void Scheduler::tickSharedTimer() 156 void Scheduler::tickSharedTimer()
122 { 157 {
123 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer"); 158 TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
159
160 // Run any high priority tasks that are queued up, otherwise the blink timer s will yield immediately.
161 runHighPriorityTasks();
124 m_sharedTimerFunction(); 162 m_sharedTimerFunction();
163
164 // The blink timers may have just yielded, so run any high priority tasks th at where queued up
165 // while the blink timers were executing.
166 runHighPriorityTasks();
167 }
168
169 void Scheduler::runHighPriorityTasks()
170 {
171 TRACE_EVENT0("blink", "Scheduler::runHighPriorityTasks");
172
173 m_pendingTasksMutex.lock();
174 Deque<TracedTask>& inputTasks = m_pendingInputTasks.swapBuffers();
eseidel 2014/08/12 16:16:01 Because this is a bit fragile (if someone called t
alexclarke 2014/08/13 10:08:58 Done.
175 Deque<TracedTask>& compositorTasks = m_pendingCompositorTasks.swapBuffers();
176 m_pendingTasksMutex.unlock();
177
178 int highPriorityTasksExecuted = 0;
179 while (!inputTasks.isEmpty()) {
180 inputTasks.takeFirst().run();
181 highPriorityTasksExecuted++;
182 }
183
184 while (!compositorTasks.isEmpty()) {
185 compositorTasks.takeFirst().run();
186 highPriorityTasksExecuted++;
187 }
188
189 int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPri orityTasksExecuted);
190 ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0);
125 } 191 }
126 192
127 void Scheduler::sharedTimerAdapter() 193 void Scheduler::sharedTimerAdapter()
128 { 194 {
129 shared()->tickSharedTimer(); 195 shared()->tickSharedTimer();
130 } 196 }
131 197
132 void Scheduler::setSharedTimerFiredFunction(void (*function)()) 198 void Scheduler::setSharedTimerFiredFunction(void (*function)())
133 { 199 {
134 m_sharedTimerFunction = function; 200 m_sharedTimerFunction = function;
135 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr); 201 blink::Platform::current()->setSharedTimerFiredFunction(function ? &Schedule r::sharedTimerAdapter : nullptr);
136 } 202 }
137 203
138 void Scheduler::setSharedTimerFireInterval(double interval) 204 void Scheduler::setSharedTimerFireInterval(double interval)
139 { 205 {
140 blink::Platform::current()->setSharedTimerFireInterval(interval); 206 blink::Platform::current()->setSharedTimerFireInterval(interval);
141 } 207 }
142 208
143 void Scheduler::stopSharedTimer() 209 void Scheduler::stopSharedTimer()
144 { 210 {
145 blink::Platform::current()->stopSharedTimer(); 211 blink::Platform::current()->stopSharedTimer();
146 } 212 }
147 213
148 bool Scheduler::shouldYieldForHighPriorityWork() 214 bool Scheduler::shouldYieldForHighPriorityWork() const
149 { 215 {
150 return false; 216 return hasPendingHighPriorityWork();
217 }
218
219 bool Scheduler::hasPendingHighPriorityWork() const
220 {
221 return acquireLoad(&m_highPriorityTaskCount) != 0;
eseidel 2014/08/12 16:16:01 We should add a (possibly large) comment here to e
alexclarke 2014/08/13 10:08:58 Done.
222 }
223
224 void Scheduler::TracedTask::run()
225 {
226 TRACE_EVENT2("blink", "TracedTask::run",
227 "src_file", m_location.fileName(),
228 "src_func", m_location.functionName());
229 m_task();
151 } 230 }
152 231
153 } // namespace blink 232 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698