OLD | NEW |
---|---|
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/PlatformThreadData.h" |
9 #include "platform/Task.h" | 9 #include "platform/Task.h" |
10 #include "platform/ThreadTimers.h" | 10 #include "platform/ThreadTimers.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPostin g(); | 66 scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPostin g(); |
67 } | 67 } |
68 }; | 68 }; |
69 | 69 |
70 | 70 |
71 // Can be created from any thread. | 71 // Can be created from any thread. |
72 // Note if the scheduler gets shutdown, this may be run after. | 72 // Note if the scheduler gets shutdown, this may be run after. |
73 class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task { | 73 class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task { |
74 public: | 74 public: |
75 MainThreadPendingTaskRunner( | 75 MainThreadPendingTaskRunner( |
76 const Scheduler::Task& task, const TraceLocation& location) | 76 const Scheduler::Task& task, const TraceLocation& location, const char* traceName, int flowTraceID) |
77 : m_task(task, location) | 77 : m_task(task, location, traceName, flowTraceID) |
78 { | 78 { |
79 ASSERT(Scheduler::shared()); | 79 ASSERT(Scheduler::shared()); |
80 } | 80 } |
81 | 81 |
82 // WebThread::Task implementation. | 82 // WebThread::Task implementation. |
83 virtual void run() OVERRIDE | 83 virtual void run() OVERRIDE |
84 { | 84 { |
85 Scheduler* scheduler = Scheduler::shared(); | 85 Scheduler* scheduler = Scheduler::shared(); |
86 // FIXME: This check should't be necessary, tasks should not outlive bli nk. | 86 // FIXME: This check should't be necessary, tasks should not outlive bli nk. |
87 ASSERT(scheduler); | 87 ASSERT(scheduler); |
88 if (scheduler) | 88 if (scheduler) |
89 Scheduler::shared()->swapQueuesAndRunPendingTasks(); | 89 Scheduler::shared()->swapQueuesAndRunPendingTasks(); |
90 m_task.run(); | 90 m_task.run(); |
91 } | 91 } |
92 | 92 |
93 Scheduler::TracedTask m_task; | 93 TracedTask m_task; |
94 }; | 94 }; |
95 | 95 |
96 Scheduler* Scheduler::s_sharedScheduler = nullptr; | 96 Scheduler* Scheduler::s_sharedScheduler = nullptr; |
97 | 97 |
98 void Scheduler::initializeOnMainThread() | 98 void Scheduler::initializeOnMainThread() |
99 { | 99 { |
100 s_sharedScheduler = new Scheduler(); | 100 s_sharedScheduler = new Scheduler(); |
101 } | 101 } |
102 | 102 |
103 void Scheduler::shutdown() | 103 void Scheduler::shutdown() |
104 { | 104 { |
105 delete s_sharedScheduler; | 105 delete s_sharedScheduler; |
106 s_sharedScheduler = nullptr; | 106 s_sharedScheduler = nullptr; |
107 } | 107 } |
108 | 108 |
109 Scheduler* Scheduler::shared() | 109 Scheduler* Scheduler::shared() |
110 { | 110 { |
111 return s_sharedScheduler; | 111 return s_sharedScheduler; |
112 } | 112 } |
113 | 113 |
114 Scheduler::Scheduler() | 114 Scheduler::Scheduler() |
115 : m_sharedTimerFunction(nullptr) | 115 : m_sharedTimerFunction(nullptr) |
116 , m_mainThread(blink::Platform::current()->currentThread()) | 116 , m_mainThread(blink::Platform::current()->currentThread()) |
117 , m_highPriorityTaskCount(0) | 117 , m_highPriorityTaskCount(0) |
118 // Flow trace ID begins as the 'this' pointer to help ensure different sched uler | |
119 // instances don't generate identical IDs | |
120 , m_nextFlowTraceID(static_cast<int>(reinterpret_cast<intptr_t>(this))) | |
118 , m_highPriorityTaskRunnerPosted(false) | 121 , m_highPriorityTaskRunnerPosted(false) |
119 { | 122 { |
120 } | 123 } |
121 | 124 |
122 Scheduler::~Scheduler() | 125 Scheduler::~Scheduler() |
123 { | 126 { |
124 while (hasPendingHighPriorityWork()) { | 127 while (hasPendingHighPriorityWork()) { |
125 swapQueuesAndRunPendingTasks(); | 128 swapQueuesAndRunPendingTasks(); |
126 } | 129 } |
127 } | 130 } |
128 | 131 |
132 int Scheduler::generateFlowTraceID() | |
133 { | |
134 return atomicIncrement(&m_nextFlowTraceID); | |
135 } | |
136 | |
129 void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask) | 137 void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
130 { | 138 { |
131 // TODO: send a real allottedTime here. | 139 // TODO: send a real allottedTime here. |
132 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)) ; | 140 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)) ; |
133 } | 141 } |
134 | 142 |
143 void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, cons t Task& task, const char* traceName) | |
144 { | |
145 Locker<Mutex> lock(m_pendingTasksMutex); | |
146 | |
147 m_pendingHighPriorityTasks.append(TracedTask(task, location, traceName, gene rateFlowTraceID())); | |
eseidel
2014/09/02 16:19:25
Unfortunate we always generate these trace ids. a
picksi1
2014/09/03 16:32:57
I've moved ID generation into TracedTasks and only
| |
148 atomicIncrement(&m_highPriorityTaskCount); | |
149 maybePostMainThreadPendingHighPriorityTaskRunner(); | |
150 } | |
151 | |
135 void Scheduler::postTask(const TraceLocation& location, const Task& task) | 152 void Scheduler::postTask(const TraceLocation& location, const Task& task) |
136 { | 153 { |
137 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location)); | 154 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Sche duler::MainThreadTask", generateFlowTraceID())); |
138 } | 155 } |
139 | 156 |
140 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) | 157 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) |
141 { | 158 { |
142 Locker<Mutex> lock(m_pendingTasksMutex); | 159 postHighPriorityTaskInternal(location, task, "Scheduler::InputTask"); |
143 m_pendingHighPriorityTasks.append(TracedTask(task, location)); | |
144 atomicIncrement(&m_highPriorityTaskCount); | |
145 maybePostMainThreadPendingHighPriorityTaskRunner(); | |
146 } | 160 } |
147 | 161 |
148 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) | 162 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) |
149 { | 163 { |
150 Locker<Mutex> lock(m_pendingTasksMutex); | 164 postHighPriorityTaskInternal(location, task, "Scheduler::CompositorTask"); |
151 m_pendingHighPriorityTasks.append(TracedTask(task, location)); | |
152 atomicIncrement(&m_highPriorityTaskCount); | |
153 maybePostMainThreadPendingHighPriorityTaskRunner(); | |
154 } | 165 } |
155 | 166 |
156 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() | 167 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() |
157 { | 168 { |
158 ASSERT(m_pendingTasksMutex.locked()); | 169 ASSERT(m_pendingTasksMutex.locked()); |
159 if (m_highPriorityTaskRunnerPosted) | 170 if (m_highPriorityTaskRunnerPosted) |
160 return; | 171 return; |
161 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner()); | 172 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner()); |
162 m_highPriorityTaskRunnerPosted = true; | 173 m_highPriorityTaskRunnerPosted = true; |
163 } | 174 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 bool Scheduler::hasPendingHighPriorityWork() const | 260 bool Scheduler::hasPendingHighPriorityWork() const |
250 { | 261 { |
251 // This method is expected to be run on the main thread, but the high priori ty tasks will be posted by | 262 // This method is expected to be run on the main thread, but the high priori ty tasks will be posted by |
252 // other threads. We could use locks here, but this function is (sometimes) called a lot by | 263 // other threads. We could use locks here, but this function is (sometimes) called a lot by |
253 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which | 264 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which |
254 // should be cheaper. | 265 // should be cheaper. |
255 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal. | 266 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal. |
256 return acquireLoad(&m_highPriorityTaskCount) != 0; | 267 return acquireLoad(&m_highPriorityTaskCount) != 0; |
257 } | 268 } |
258 | 269 |
259 void Scheduler::TracedTask::run() | |
260 { | |
261 TRACE_EVENT2("blink", "TracedTask::run", | |
262 "src_file", m_location.fileName(), | |
263 "src_func", m_location.functionName()); | |
264 m_task(); | |
265 } | |
266 | |
267 } // namespace blink | 270 } // namespace blink |
OLD | NEW |