Chromium Code Reviews| 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 * name, int flowTraceID) |
|
Sami
2014/08/29 14:50:25
No space before "*".
picksi1
2014/09/01 11:06:51
Done.
| |
| 77 : m_task(task, location) | 77 : m_task(task, location, name, 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 , m_highPriorityTaskRunnerPosted(false) | 118 , m_highPriorityTaskRunnerPosted(false) |
| 119 { | 119 { |
| 120 // Start trace ID off as 'this' to keep multiple instances of the scheduler | |
| 121 // having different(-ish) unique flow tracing IDs. Keep compiler happy | |
| 122 // by casting to a pointer and then to an integer. | |
| 123 intptr_t thisAsPointer = reinterpret_cast<intptr_t>(this); | |
|
Sami
2014/08/29 14:50:25
Maybe it's just me, but I think this is a little v
picksi1
2014/09/01 11:06:51
Done.
| |
| 124 int thisAsInteger = static_cast<int>(thisAsPointer); | |
| 125 m_nextFlowTraceID = thisAsInteger; | |
| 120 } | 126 } |
| 121 | 127 |
| 122 Scheduler::~Scheduler() | 128 Scheduler::~Scheduler() |
| 123 { | 129 { |
| 124 while (hasPendingHighPriorityWork()) { | 130 while (hasPendingHighPriorityWork()) { |
| 125 swapQueuesAndRunPendingTasks(); | 131 swapQueuesAndRunPendingTasks(); |
| 126 } | 132 } |
| 127 } | 133 } |
| 128 | 134 |
| 135 int Scheduler::generateFlowTraceID() | |
| 136 { | |
| 137 return atomicIncrement(&m_nextFlowTraceID); | |
| 138 } | |
| 139 | |
| 129 void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask) | 140 void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
| 130 { | 141 { |
| 131 // TODO: send a real allottedTime here. | 142 // TODO: send a real allottedTime here. |
| 132 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)) ; | 143 m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)) ; |
| 133 } | 144 } |
| 134 | 145 |
| 146 void Scheduler::postAsHighPriorityTask(const TraceLocation& location, const Task & task, const char * traceName) | |
|
Sami
2014/08/29 14:50:25
nit: postHighPriorityTask to match the wording of
picksi1
2014/09/01 11:06:51
I'd named this differently on purpose as it is an
| |
| 147 { | |
| 148 Locker<Mutex> lock(m_pendingTasksMutex); | |
| 149 | |
| 150 TracedTask tracedTask = TracedTask(task, location, traceName, generateFlowTr aceID()); | |
| 151 m_pendingHighPriorityTasks.append(tracedTask); | |
| 152 atomicIncrement(&m_highPriorityTaskCount); | |
| 153 maybePostMainThreadPendingHighPriorityTaskRunner(); | |
| 154 } | |
| 155 | |
| 135 void Scheduler::postTask(const TraceLocation& location, const Task& task) | 156 void Scheduler::postTask(const TraceLocation& location, const Task& task) |
| 136 { | 157 { |
| 137 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location)); | 158 m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Sche duler::MainThreadTask", generateFlowTraceID())); |
| 138 } | 159 } |
| 139 | 160 |
| 140 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) | 161 void Scheduler::postInputTask(const TraceLocation& location, const Task& task) |
| 141 { | 162 { |
| 142 Locker<Mutex> lock(m_pendingTasksMutex); | 163 postAsHighPriorityTask(location, task, "Scheduler::InputTask"); |
| 143 m_pendingHighPriorityTasks.append(TracedTask(task, location)); | |
| 144 atomicIncrement(&m_highPriorityTaskCount); | |
| 145 maybePostMainThreadPendingHighPriorityTaskRunner(); | |
| 146 } | 164 } |
| 147 | 165 |
| 148 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) | 166 void Scheduler::postCompositorTask(const TraceLocation& location, const Task& ta sk) |
| 149 { | 167 { |
| 150 Locker<Mutex> lock(m_pendingTasksMutex); | 168 postAsHighPriorityTask(location, task, "Scheduler::CompositorTask"); |
| 151 m_pendingHighPriorityTasks.append(TracedTask(task, location)); | |
| 152 atomicIncrement(&m_highPriorityTaskCount); | |
| 153 maybePostMainThreadPendingHighPriorityTaskRunner(); | |
| 154 } | 169 } |
| 155 | 170 |
| 156 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() | 171 void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() |
| 157 { | 172 { |
| 158 ASSERT(m_pendingTasksMutex.locked()); | 173 ASSERT(m_pendingTasksMutex.locked()); |
| 159 if (m_highPriorityTaskRunnerPosted) | 174 if (m_highPriorityTaskRunnerPosted) |
| 160 return; | 175 return; |
| 161 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner()); | 176 m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner()); |
| 162 m_highPriorityTaskRunnerPosted = true; | 177 m_highPriorityTaskRunnerPosted = true; |
| 163 } | 178 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 bool Scheduler::hasPendingHighPriorityWork() const | 264 bool Scheduler::hasPendingHighPriorityWork() const |
| 250 { | 265 { |
| 251 // This method is expected to be run on the main thread, but the high priori ty tasks will be posted by | 266 // 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 | 267 // 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 | 268 // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + bar rier loads here which |
| 254 // should be cheaper. | 269 // should be cheaper. |
| 255 // NOTE it's possible the barrier read is overkill here, since delayed yield ing isn't a big deal. | 270 // 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; | 271 return acquireLoad(&m_highPriorityTaskCount) != 0; |
| 257 } | 272 } |
| 258 | 273 |
| 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 | 274 } // namespace blink |
| OLD | NEW |