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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc

Issue 2777063010: [scheduler] Make any thread lock in TaskQueueImpl reentrable. (Closed)
Patch Set: Created 3 years, 8 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
« no previous file with comments | « third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "platform/scheduler/base/task_queue_impl.h" 5 #include "platform/scheduler/base/task_queue_impl.h"
6 6
7 #include "base/format_macros.h" 7 #include "base/format_macros.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
10 #include "base/trace_event/blame_context.h" 10 #include "base/trace_event/blame_context.h"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 should_monitor_quiescence_(spec.should_monitor_quiescence), 86 should_monitor_quiescence_(spec.should_monitor_quiescence),
87 should_notify_observers_(spec.should_notify_observers), 87 should_notify_observers_(spec.should_notify_observers),
88 should_report_when_execution_blocked_( 88 should_report_when_execution_blocked_(
89 spec.should_report_when_execution_blocked) { 89 spec.should_report_when_execution_blocked) {
90 DCHECK(time_domain); 90 DCHECK(time_domain);
91 time_domain->RegisterQueue(this); 91 time_domain->RegisterQueue(this);
92 } 92 }
93 93
94 TaskQueueImpl::~TaskQueueImpl() { 94 TaskQueueImpl::~TaskQueueImpl() {
95 #if DCHECK_IS_ON() 95 #if DCHECK_IS_ON()
96 base::AutoLock lock(any_thread_lock_); 96 AnyThreadAutoLock lock = AcquireAnyThreadLock();
97 // NOTE this check shouldn't fire because |TaskQueueManager::queues_| 97 // NOTE this check shouldn't fire because |TaskQueueManager::queues_|
98 // contains a strong reference to this TaskQueueImpl and the TaskQueueManager 98 // contains a strong reference to this TaskQueueImpl and the TaskQueueManager
99 // destructor calls UnregisterTaskQueue on all task queues. 99 // destructor calls UnregisterTaskQueue on all task queues.
100 DCHECK(any_thread().task_queue_manager == nullptr) 100 DCHECK(any_thread().task_queue_manager == nullptr)
101 << "UnregisterTaskQueue must be called first!"; 101 << "UnregisterTaskQueue must be called first!";
102 102
103 #endif 103 #endif
104 } 104 }
105 105
106 TaskQueueImpl::Task::Task() 106 TaskQueueImpl::Task::Task()
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 time_domain(time_domain), 156 time_domain(time_domain),
157 delayed_work_queue( 157 delayed_work_queue(
158 new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)), 158 new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)),
159 immediate_work_queue(new WorkQueue(task_queue, 159 immediate_work_queue(new WorkQueue(task_queue,
160 "immediate", 160 "immediate",
161 WorkQueue::QueueType::IMMEDIATE)), 161 WorkQueue::QueueType::IMMEDIATE)),
162 set_index(0), 162 set_index(0),
163 is_enabled_refcount(0), 163 is_enabled_refcount(0),
164 voter_refcount(0), 164 voter_refcount(0),
165 blame_context(nullptr), 165 blame_context(nullptr),
166 current_fence(0) {} 166 current_fence(0),
167 any_thread_lock_acquired_count(0) {}
167 168
168 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 169 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
169 170
170 void TaskQueueImpl::UnregisterTaskQueue() { 171 void TaskQueueImpl::UnregisterTaskQueue() {
171 base::AutoLock lock(any_thread_lock_); 172 AnyThreadAutoLock lock = AcquireAnyThreadLock();
172 if (main_thread_only().time_domain) 173 if (main_thread_only().time_domain)
173 main_thread_only().time_domain->UnregisterQueue(this); 174 main_thread_only().time_domain->UnregisterQueue(this);
174 if (!any_thread().task_queue_manager) 175 if (!any_thread().task_queue_manager)
175 return; 176 return;
176 any_thread().time_domain = nullptr; 177 any_thread().time_domain = nullptr;
177 main_thread_only().time_domain = nullptr; 178 main_thread_only().time_domain = nullptr;
178 any_thread().task_queue_manager->UnregisterTaskQueue(this); 179 any_thread().task_queue_manager->UnregisterTaskQueue(this);
179 180
180 any_thread().task_queue_manager = nullptr; 181 any_thread().task_queue_manager = nullptr;
181 main_thread_only().task_queue_manager = nullptr; 182 main_thread_only().task_queue_manager = nullptr;
(...skipping 23 matching lines...) Expand all
205 if (delay.is_zero()) 206 if (delay.is_zero())
206 return PostImmediateTaskImpl(from_here, task, TaskType::NON_NESTABLE); 207 return PostImmediateTaskImpl(from_here, task, TaskType::NON_NESTABLE);
207 208
208 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); 209 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE);
209 } 210 }
210 211
211 bool TaskQueueImpl::PostImmediateTaskImpl( 212 bool TaskQueueImpl::PostImmediateTaskImpl(
212 const tracked_objects::Location& from_here, 213 const tracked_objects::Location& from_here,
213 const base::Closure& task, 214 const base::Closure& task,
214 TaskType task_type) { 215 TaskType task_type) {
215 base::AutoLock lock(any_thread_lock_); 216 AnyThreadAutoLock lock = AcquireAnyThreadLock();
216 if (!any_thread().task_queue_manager) 217 if (!any_thread().task_queue_manager)
217 return false; 218 return false;
218 219
219 EnqueueOrder sequence_number = 220 EnqueueOrder sequence_number =
220 any_thread().task_queue_manager->GetNextSequenceNumber(); 221 any_thread().task_queue_manager->GetNextSequenceNumber();
221 222
222 PushOntoImmediateIncomingQueueLocked( 223 PushOntoImmediateIncomingQueueLocked(
223 from_here, 224 from_here,
224 task, 225 task,
225 base::TimeTicks(), 226 base::TimeTicks(),
(...skipping 20 matching lines...) Expand all
246 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; 247 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
247 PushOntoDelayedIncomingQueueFromMainThread( 248 PushOntoDelayedIncomingQueueFromMainThread(
248 Task(from_here, task, time_domain_delayed_run_time, sequence_number, 249 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
249 task_type != TaskType::NON_NESTABLE), 250 task_type != TaskType::NON_NESTABLE),
250 time_domain_now); 251 time_domain_now);
251 } else { 252 } else {
252 // NOTE posting a delayed task from a different thread is not expected to 253 // NOTE posting a delayed task from a different thread is not expected to
253 // be common. This pathway is less optimal than perhaps it could be 254 // be common. This pathway is less optimal than perhaps it could be
254 // because it causes two main thread tasks to be run. Should this 255 // because it causes two main thread tasks to be run. Should this
255 // assumption prove to be false in future, we may need to revisit this. 256 // assumption prove to be false in future, we may need to revisit this.
256 base::AutoLock lock(any_thread_lock_); 257 AnyThreadAutoLock lock = AcquireAnyThreadLock();
257 if (!any_thread().task_queue_manager) 258 if (!any_thread().task_queue_manager)
258 return false; 259 return false;
259 260
260 EnqueueOrder sequence_number = 261 EnqueueOrder sequence_number =
261 any_thread().task_queue_manager->GetNextSequenceNumber(); 262 any_thread().task_queue_manager->GetNextSequenceNumber();
262 263
263 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); 264 base::TimeTicks time_domain_now = any_thread().time_domain->Now();
264 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; 265 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
265 PushOntoDelayedIncomingQueueLocked( 266 PushOntoDelayedIncomingQueueLocked(
266 Task(from_here, task, time_domain_delayed_run_time, sequence_number, 267 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 352 }
352 353
353 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { 354 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() {
354 if (!main_thread_only().immediate_work_queue->Empty()) 355 if (!main_thread_only().immediate_work_queue->Empty())
355 return; 356 return;
356 357
357 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); 358 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue();
358 } 359 }
359 360
360 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { 361 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() {
361 base::AutoLock lock(any_thread_lock_); 362 AnyThreadAutoLock lock = AcquireAnyThreadLock();
362 WTF::Deque<TaskQueueImpl::Task> queue; 363 WTF::Deque<TaskQueueImpl::Task> queue;
363 queue.swap(any_thread().immediate_incoming_queue); 364 queue.swap(any_thread().immediate_incoming_queue);
364 return queue; 365 return queue;
365 } 366 }
366 367
367 bool TaskQueueImpl::IsEmpty() const { 368 bool TaskQueueImpl::IsEmpty() const {
368 if (!main_thread_only().delayed_work_queue->Empty() || 369 if (!main_thread_only().delayed_work_queue->Empty() ||
369 !main_thread_only().delayed_incoming_queue.empty() || 370 !main_thread_only().delayed_incoming_queue.empty() ||
370 !main_thread_only().immediate_work_queue->Empty()) { 371 !main_thread_only().immediate_work_queue->Empty()) {
371 return false; 372 return false;
372 } 373 }
373 374
374 base::AutoLock lock(any_thread_lock_); 375 AnyThreadAutoLock lock = AcquireAnyThreadLock();
375 return any_thread().immediate_incoming_queue.empty(); 376 return any_thread().immediate_incoming_queue.empty();
376 } 377 }
377 378
378 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { 379 size_t TaskQueueImpl::GetNumberOfPendingTasks() const {
379 size_t task_count = 0; 380 size_t task_count = 0;
380 task_count += main_thread_only().delayed_work_queue->Size(); 381 task_count += main_thread_only().delayed_work_queue->Size();
381 task_count += main_thread_only().delayed_incoming_queue.size(); 382 task_count += main_thread_only().delayed_incoming_queue.size();
382 task_count += main_thread_only().immediate_work_queue->Size(); 383 task_count += main_thread_only().immediate_work_queue->Size();
383 384
384 base::AutoLock lock(any_thread_lock_); 385 AnyThreadAutoLock lock = AcquireAnyThreadLock();
385 task_count += any_thread().immediate_incoming_queue.size(); 386 task_count += any_thread().immediate_incoming_queue.size();
386 return task_count; 387 return task_count;
387 } 388 }
388 389
389 bool TaskQueueImpl::HasPendingImmediateWork() const { 390 bool TaskQueueImpl::HasPendingImmediateWork() const {
390 // Any work queue tasks count as immediate work. 391 // Any work queue tasks count as immediate work.
391 if (!main_thread_only().delayed_work_queue->Empty() || 392 if (!main_thread_only().delayed_work_queue->Empty() ||
392 !main_thread_only().immediate_work_queue->Empty()) { 393 !main_thread_only().immediate_work_queue->Empty()) {
393 return true; 394 return true;
394 } 395 }
395 396
396 // Tasks on |delayed_incoming_queue| that could run now, count as 397 // Tasks on |delayed_incoming_queue| that could run now, count as
397 // immediate work. 398 // immediate work.
398 if (!main_thread_only().delayed_incoming_queue.empty() && 399 if (!main_thread_only().delayed_incoming_queue.empty() &&
399 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= 400 main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
400 main_thread_only().time_domain->CreateLazyNow().Now()) { 401 main_thread_only().time_domain->CreateLazyNow().Now()) {
401 return true; 402 return true;
402 } 403 }
403 404
404 // Finally tasks on |immediate_incoming_queue| count as immediate work. 405 // Finally tasks on |immediate_incoming_queue| count as immediate work.
405 base::AutoLock lock(any_thread_lock_); 406 AnyThreadAutoLock lock = AcquireAnyThreadLock();
406 return !any_thread().immediate_incoming_queue.empty(); 407 return !any_thread().immediate_incoming_queue.empty();
407 } 408 }
408 409
409 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { 410 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
410 // Note we don't scheduled a wakeup for disabled queues. 411 // Note we don't scheduled a wakeup for disabled queues.
411 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) 412 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled())
412 return base::nullopt; 413 return base::nullopt;
413 414
414 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; 415 return main_thread_only().delayed_incoming_queue.top().delayed_run_time;
415 } 416 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 priority); 484 priority);
484 } 485 }
485 486
486 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { 487 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const {
487 size_t set_index = immediate_work_queue()->work_queue_set_index(); 488 size_t set_index = immediate_work_queue()->work_queue_set_index();
488 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); 489 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index());
489 return static_cast<TaskQueue::QueuePriority>(set_index); 490 return static_cast<TaskQueue::QueuePriority>(set_index);
490 } 491 }
491 492
492 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { 493 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const {
493 base::AutoLock lock(any_thread_lock_); 494 AnyThreadAutoLock lock = AcquireAnyThreadLock();
494 state->BeginDictionary(); 495 state->BeginDictionary();
495 state->SetString("name", GetName()); 496 state->SetString("name", GetName());
496 state->SetString( 497 state->SetString(
497 "task_queue_id", 498 "task_queue_id",
498 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( 499 base::StringPrintf("%" PRIx64, static_cast<uint64_t>(
499 reinterpret_cast<uintptr_t>(this)))); 500 reinterpret_cast<uintptr_t>(this))));
500 state->SetBoolean("enabled", IsQueueEnabled()); 501 state->SetBoolean("enabled", IsQueueEnabled());
501 state->SetString("time_domain_name", 502 state->SetString("time_domain_name",
502 main_thread_only().time_domain->GetName()); 503 main_thread_only().time_domain->GetName());
503 bool verbose_tracing_enabled = false; 504 bool verbose_tracing_enabled = false;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 const base::PendingTask& pending_task) { 562 const base::PendingTask& pending_task) {
562 DCHECK(should_notify_observers_); 563 DCHECK(should_notify_observers_);
563 for (auto& observer : main_thread_only().task_observers) 564 for (auto& observer : main_thread_only().task_observers)
564 observer.DidProcessTask(pending_task); 565 observer.DidProcessTask(pending_task);
565 if (main_thread_only().blame_context) 566 if (main_thread_only().blame_context)
566 main_thread_only().blame_context->Leave(); 567 main_thread_only().blame_context->Leave();
567 } 568 }
568 569
569 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { 570 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) {
570 { 571 {
571 base::AutoLock lock(any_thread_lock_); 572 AnyThreadAutoLock lock = AcquireAnyThreadLock();
572 DCHECK(time_domain); 573 DCHECK(time_domain);
573 // NOTE this is similar to checking |any_thread().task_queue_manager| but 574 // NOTE this is similar to checking |any_thread().task_queue_manager| but
574 // the TaskQueueSelectorTests constructs TaskQueueImpl directly with a null 575 // the TaskQueueSelectorTests constructs TaskQueueImpl directly with a null
575 // task_queue_manager. Instead we check |any_thread().time_domain| which is 576 // task_queue_manager. Instead we check |any_thread().time_domain| which is
576 // another way of asserting that UnregisterTaskQueue has not been called. 577 // another way of asserting that UnregisterTaskQueue has not been called.
577 DCHECK(any_thread().time_domain); 578 DCHECK(any_thread().time_domain);
578 if (!any_thread().time_domain) 579 if (!any_thread().time_domain)
579 return; 580 return;
580 DCHECK(main_thread_checker_.CalledOnValidThread()); 581 DCHECK(main_thread_checker_.CalledOnValidThread());
581 if (time_domain == main_thread_only().time_domain) 582 if (time_domain == main_thread_only().time_domain)
(...skipping 12 matching lines...) Expand all
594 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, 595 {main_thread_only().delayed_incoming_queue.top().delayed_run_time,
595 main_thread_only().delayed_incoming_queue.top().sequence_num}, 596 main_thread_only().delayed_incoming_queue.top().sequence_num},
596 time_domain->Now()); 597 time_domain->Now());
597 } 598 }
598 } 599 }
599 600
600 TimeDomain* TaskQueueImpl::GetTimeDomain() const { 601 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
601 if (base::PlatformThread::CurrentId() == thread_id_) 602 if (base::PlatformThread::CurrentId() == thread_id_)
602 return main_thread_only().time_domain; 603 return main_thread_only().time_domain;
603 604
604 base::AutoLock lock(any_thread_lock_); 605 AnyThreadAutoLock lock = AcquireAnyThreadLock();
605 return any_thread().time_domain; 606 return any_thread().time_domain;
606 } 607 }
607 608
608 void TaskQueueImpl::SetBlameContext( 609 void TaskQueueImpl::SetBlameContext(
609 base::trace_event::BlameContext* blame_context) { 610 base::trace_event::BlameContext* blame_context) {
610 main_thread_only().blame_context = blame_context; 611 main_thread_only().blame_context = blame_context;
611 } 612 }
612 613
613 void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) { 614 void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) {
614 if (!main_thread_only().task_queue_manager) 615 if (!main_thread_only().task_queue_manager)
615 return; 616 return;
616 617
617 EnqueueOrder previous_fence = main_thread_only().current_fence; 618 EnqueueOrder previous_fence = main_thread_only().current_fence;
618 main_thread_only().current_fence = 619 main_thread_only().current_fence =
619 position == TaskQueue::InsertFencePosition::NOW 620 position == TaskQueue::InsertFencePosition::NOW
620 ? main_thread_only().task_queue_manager->GetNextSequenceNumber() 621 ? main_thread_only().task_queue_manager->GetNextSequenceNumber()
621 : static_cast<EnqueueOrder>(EnqueueOrderValues::BLOCKING_FENCE); 622 : static_cast<EnqueueOrder>(EnqueueOrderValues::BLOCKING_FENCE);
622 623
623 // Tasks posted after this point will have a strictly higher enqueue order 624 // Tasks posted after this point will have a strictly higher enqueue order
624 // and will be blocked from running. 625 // and will be blocked from running.
625 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( 626 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence(
626 main_thread_only().current_fence); 627 main_thread_only().current_fence);
627 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( 628 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence(
628 main_thread_only().current_fence); 629 main_thread_only().current_fence);
629 630
630 if (!task_unblocked && previous_fence && 631 if (!task_unblocked && previous_fence &&
631 previous_fence < main_thread_only().current_fence) { 632 previous_fence < main_thread_only().current_fence) {
632 base::AutoLock lock(any_thread_lock_); 633 AnyThreadAutoLock lock = AcquireAnyThreadLock();
633 if (!any_thread().immediate_incoming_queue.empty() && 634 if (!any_thread().immediate_incoming_queue.empty() &&
634 any_thread().immediate_incoming_queue.front().enqueue_order() > 635 any_thread().immediate_incoming_queue.front().enqueue_order() >
635 previous_fence && 636 previous_fence &&
636 any_thread().immediate_incoming_queue.front().enqueue_order() < 637 any_thread().immediate_incoming_queue.front().enqueue_order() <
637 main_thread_only().current_fence) { 638 main_thread_only().current_fence) {
638 task_unblocked = true; 639 task_unblocked = true;
639 } 640 }
640 } 641 }
641 642
642 if (IsQueueEnabled() && task_unblocked) { 643 if (IsQueueEnabled() && task_unblocked) {
643 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 644 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
644 FROM_HERE); 645 FROM_HERE);
645 } 646 }
646 } 647 }
647 648
648 void TaskQueueImpl::RemoveFence() { 649 void TaskQueueImpl::RemoveFence() {
649 if (!main_thread_only().task_queue_manager) 650 if (!main_thread_only().task_queue_manager)
650 return; 651 return;
651 652
652 EnqueueOrder previous_fence = main_thread_only().current_fence; 653 EnqueueOrder previous_fence = main_thread_only().current_fence;
653 main_thread_only().current_fence = 0; 654 main_thread_only().current_fence = 0;
654 655
655 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); 656 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
656 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); 657 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
657 658
658 if (!task_unblocked && previous_fence) { 659 if (!task_unblocked && previous_fence) {
659 base::AutoLock lock(any_thread_lock_); 660 AnyThreadAutoLock lock = AcquireAnyThreadLock();
660 if (!any_thread().immediate_incoming_queue.empty() && 661 if (!any_thread().immediate_incoming_queue.empty() &&
661 any_thread().immediate_incoming_queue.front().enqueue_order() > 662 any_thread().immediate_incoming_queue.front().enqueue_order() >
662 previous_fence) { 663 previous_fence) {
663 task_unblocked = true; 664 task_unblocked = true;
664 } 665 }
665 } 666 }
666 667
667 if (IsQueueEnabled() && task_unblocked) { 668 if (IsQueueEnabled() && task_unblocked) {
668 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 669 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
669 FROM_HERE); 670 FROM_HERE);
670 } 671 }
671 } 672 }
672 673
673 bool TaskQueueImpl::BlockedByFence() const { 674 bool TaskQueueImpl::BlockedByFence() const {
674 if (!main_thread_only().current_fence) 675 if (!main_thread_only().current_fence)
675 return false; 676 return false;
676 677
677 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 678 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
678 !main_thread_only().delayed_work_queue->BlockedByFence()) { 679 !main_thread_only().delayed_work_queue->BlockedByFence()) {
679 return false; 680 return false;
680 } 681 }
681 682
682 base::AutoLock lock(any_thread_lock_); 683 AnyThreadAutoLock lock = AcquireAnyThreadLock();
683 if (any_thread().immediate_incoming_queue.empty()) 684 if (any_thread().immediate_incoming_queue.empty())
684 return true; 685 return true;
685 686
686 return any_thread().immediate_incoming_queue.front().enqueue_order() > 687 return any_thread().immediate_incoming_queue.front().enqueue_order() >
687 main_thread_only().current_fence; 688 main_thread_only().current_fence;
688 } 689 }
689 690
690 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { 691 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const {
691 if (!IsQueueEnabled()) 692 if (!IsQueueEnabled())
692 return false; 693 return false;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 806
806 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { 807 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) {
807 if (!main_thread_only().task_queue_manager) 808 if (!main_thread_only().task_queue_manager)
808 return; 809 return;
809 810
810 if (enable) { 811 if (enable) {
811 // Check if there's any immediate work on either queue. 812 // Check if there's any immediate work on either queue.
812 bool immediate_queues_empty = 813 bool immediate_queues_empty =
813 main_thread_only().immediate_work_queue->Empty(); 814 main_thread_only().immediate_work_queue->Empty();
814 if (immediate_queues_empty) { 815 if (immediate_queues_empty) {
815 base::AutoLock lock(any_thread_lock_); 816 AnyThreadAutoLock lock = AcquireAnyThreadLock();
816 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); 817 immediate_queues_empty = any_thread().immediate_incoming_queue.empty();
817 } 818 }
818 // Avoid holding the lock while we fire the notification. 819 // Avoid holding the lock while we fire the notification.
819 if (!immediate_queues_empty) 820 if (!immediate_queues_empty)
820 main_thread_only().time_domain->OnQueueHasImmediateWork(this); 821 main_thread_only().time_domain->OnQueueHasImmediateWork(this);
821 822
822 if (!main_thread_only().delayed_incoming_queue.empty()) { 823 if (!main_thread_only().delayed_incoming_queue.empty()) {
823 main_thread_only().time_domain->ScheduleDelayedWork( 824 main_thread_only().time_domain->ScheduleDelayedWork(
824 this, 825 this,
825 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, 826 {main_thread_only().delayed_incoming_queue.top().delayed_run_time,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 this, 873 this,
873 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, 874 {main_thread_only().delayed_incoming_queue.top().delayed_run_time,
874 main_thread_only().delayed_incoming_queue.top().sequence_num}, 875 main_thread_only().delayed_incoming_queue.top().sequence_num},
875 main_thread_only().time_domain->Now()); 876 main_thread_only().time_domain->Now());
876 } 877 }
877 } 878 }
878 } 879 }
879 880
880 void TaskQueueImpl::PushImmediateIncomingTaskForTest( 881 void TaskQueueImpl::PushImmediateIncomingTaskForTest(
881 TaskQueueImpl::Task&& task) { 882 TaskQueueImpl::Task&& task) {
882 base::AutoLock lock(any_thread_lock_); 883 AnyThreadAutoLock lock = AcquireAnyThreadLock();
883 any_thread().immediate_incoming_queue.push_back(std::move(task)); 884 any_thread().immediate_incoming_queue.push_back(std::move(task));
884 } 885 }
885 886
887 TaskQueueImpl::AnyThreadAutoLock TaskQueueImpl::AcquireAnyThreadLock() const {
888 size_t* any_thread_lock_acquired_from_main_thread_count = nullptr;
889 if (thread_id_ == base::PlatformThread::CurrentId())
890 any_thread_lock_acquired_from_main_thread_count =
891 &main_thread_only().any_thread_lock_acquired_count;
892 return AnyThreadAutoLock(any_thread_lock_,
893 any_thread_lock_acquired_from_main_thread_count);
894 }
895
896 TaskQueueImpl::AnyThreadAutoLock::AnyThreadAutoLock(base::Lock& lock,
897 size_t* acquired_count)
898 : lock_(lock), acquired_count_(acquired_count) {
899 if (!acquired_count_ || *acquired_count_ == 0) {
900 lock_.Acquire();
901 }
902 if (acquired_count_)
903 ++*acquired_count_;
904 lock_.AssertAcquired();
905 }
906
907 TaskQueueImpl::AnyThreadAutoLock::~AnyThreadAutoLock() {
908 lock_.AssertAcquired();
909 if (acquired_count_)
910 --*acquired_count_;
911 if (!acquired_count_ || *acquired_count_ == 0)
912 lock_.Release();
913 }
914
886 } // namespace internal 915 } // namespace internal
887 } // namespace scheduler 916 } // namespace scheduler
888 } // namespace blink 917 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698