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

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

Issue 2718293003: scheduler: Ensure consistent delayed task ordering between task queues (Closed)
Patch Set: Created 3 years, 9 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 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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 275 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
277 277
278 // If |pending_task| is at the head of the queue, then make sure a wakeup 278 // If |pending_task| is at the head of the queue, then make sure a wakeup
279 // is requested if the queue is enabled. Note we still want to schedule a 279 // is requested if the queue is enabled. Note we still want to schedule a
280 // wakeup even if blocked by a fence, because we'd break throttling logic 280 // wakeup even if blocked by a fence, because we'd break throttling logic
281 // otherwise. 281 // otherwise.
282 base::TimeTicks next_delayed_task = 282 base::TimeTicks next_delayed_task =
283 main_thread_only().delayed_incoming_queue.top().delayed_run_time; 283 main_thread_only().delayed_incoming_queue.top().delayed_run_time;
284 if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { 284 if (next_delayed_task == delayed_run_time && IsQueueEnabled()) {
285 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 285 main_thread_only().time_domain->ScheduleDelayedWork(
286 now); 286 this, delayed_run_time, pending_task.sequence_num, now);
287 } 287 }
288 288
289 TraceQueueSize(false); 289 TraceQueueSize(false);
290 } 290 }
291 291
292 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 292 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
293 any_thread().task_queue_manager->DidQueueTask(pending_task); 293 any_thread().task_queue_manager->DidQueueTask(pending_task);
294 294
295 int thread_hop_task_sequence_number = 295 int thread_hop_task_sequence_number =
296 any_thread().task_queue_manager->GetNextSequenceNumber(); 296 any_thread().task_queue_manager->GetNextSequenceNumber();
(...skipping 11 matching lines...) Expand all
308 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 308 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
309 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); 309 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
310 if (delayed_run_time <= time_domain_now) { 310 if (delayed_run_time <= time_domain_now) {
311 // If |delayed_run_time| is in the past then push it onto the work queue 311 // If |delayed_run_time| is in the past then push it onto the work queue
312 // immediately. To ensure the right task ordering we need to temporarily 312 // immediately. To ensure the right task ordering we need to temporarily
313 // push it onto the |delayed_incoming_queue|. 313 // push it onto the |delayed_incoming_queue|.
314 delayed_run_time = time_domain_now; 314 delayed_run_time = time_domain_now;
315 pending_task.delayed_run_time = time_domain_now; 315 pending_task.delayed_run_time = time_domain_now;
316 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 316 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
317 LazyNow lazy_now(time_domain_now); 317 LazyNow lazy_now(time_domain_now);
318 WakeUpForDelayedWork(&lazy_now); 318 base::TimeTicks ignored_next_wake_up_time;
319 int ignored_next_wake_up_sequence_num;
320 WakeUpForDelayedWork(&lazy_now, &ignored_next_wake_up_time,
321 &ignored_next_wake_up_sequence_num);
319 } else { 322 } else {
320 // If |delayed_run_time| is in the future we can queue it as normal. 323 // If |delayed_run_time| is in the future we can queue it as normal.
321 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), 324 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task),
322 time_domain_now); 325 time_domain_now);
323 } 326 }
324 TraceQueueSize(false); 327 TraceQueueSize(false);
325 } 328 }
326 329
327 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( 330 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
328 const tracked_objects::Location& posted_from, 331 const tracked_objects::Location& posted_from,
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 } 410 }
408 411
409 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { 412 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
410 // Note we don't scheduled a wakeup for disabled queues. 413 // Note we don't scheduled a wakeup for disabled queues.
411 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) 414 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled())
412 return base::nullopt; 415 return base::nullopt;
413 416
414 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; 417 return main_thread_only().delayed_incoming_queue.top().delayed_run_time;
415 } 418 }
416 419
417 base::Optional<base::TimeTicks> TaskQueueImpl::WakeUpForDelayedWork( 420 bool TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now,
418 LazyNow* lazy_now) { 421 base::TimeTicks* out_next_wake_up_time,
422 int* out_next_wake_up_sequence_num) {
419 // Enqueue all delayed tasks that should be running now, skipping any that 423 // Enqueue all delayed tasks that should be running now, skipping any that
420 // have been canceled. 424 // have been canceled.
421 while (!main_thread_only().delayed_incoming_queue.empty()) { 425 while (!main_thread_only().delayed_incoming_queue.empty()) {
422 Task& task = 426 Task& task =
423 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); 427 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
424 if (task.task.IsCancelled()) { 428 if (task.task.IsCancelled()) {
425 main_thread_only().delayed_incoming_queue.pop(); 429 main_thread_only().delayed_incoming_queue.pop();
426 continue; 430 continue;
427 } 431 }
428 if (task.delayed_run_time > lazy_now->Now()) 432 if (task.delayed_run_time > lazy_now->Now())
429 break; 433 break;
430 task.set_enqueue_order( 434 task.set_enqueue_order(
431 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 435 main_thread_only().task_queue_manager->GetNextSequenceNumber());
432 main_thread_only().delayed_work_queue->Push(std::move(task)); 436 main_thread_only().delayed_work_queue->Push(std::move(task));
433 main_thread_only().delayed_incoming_queue.pop(); 437 main_thread_only().delayed_incoming_queue.pop();
434 } 438 }
435 439
436 // Make sure the next wake up is scheduled. 440 // Make sure the next wake up is scheduled.
437 if (!main_thread_only().delayed_incoming_queue.empty()) 441 if (!main_thread_only().delayed_incoming_queue.empty()) {
438 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; 442 *out_next_wake_up_time =
443 main_thread_only().delayed_incoming_queue.top().delayed_run_time;
444 *out_next_wake_up_sequence_num =
445 main_thread_only().delayed_incoming_queue.top().sequence_num;
446 return true;
447 }
439 448
440 return base::nullopt; 449 return false;
441 } 450 }
442 451
443 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { 452 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
444 bool is_tracing; 453 bool is_tracing;
445 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 454 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
446 &is_tracing); 455 &is_tracing);
447 if (!is_tracing) 456 if (!is_tracing)
448 return; 457 return;
449 458
450 // It's only safe to access the work queues from the main thread. 459 // It's only safe to access the work queues from the main thread.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 any_thread().time_domain = time_domain; 590 any_thread().time_domain = time_domain;
582 } 591 }
583 592
584 main_thread_only().time_domain->UnregisterQueue(this); 593 main_thread_only().time_domain->UnregisterQueue(this);
585 main_thread_only().time_domain = time_domain; 594 main_thread_only().time_domain = time_domain;
586 time_domain->RegisterQueue(this); 595 time_domain->RegisterQueue(this);
587 596
588 if (IsQueueEnabled() && !main_thread_only().delayed_incoming_queue.empty()) { 597 if (IsQueueEnabled() && !main_thread_only().delayed_incoming_queue.empty()) {
589 time_domain->ScheduleDelayedWork( 598 time_domain->ScheduleDelayedWork(
590 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, 599 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
600 main_thread_only().delayed_incoming_queue.top().sequence_num,
591 time_domain->Now()); 601 time_domain->Now());
592 } 602 }
593 } 603 }
594 604
595 TimeDomain* TaskQueueImpl::GetTimeDomain() const { 605 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
596 if (base::PlatformThread::CurrentId() == thread_id_) 606 if (base::PlatformThread::CurrentId() == thread_id_)
597 return main_thread_only().time_domain; 607 return main_thread_only().time_domain;
598 608
599 base::AutoLock lock(any_thread_lock_); 609 base::AutoLock lock(any_thread_lock_);
600 return any_thread().time_domain; 610 return any_thread().time_domain;
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); 821 immediate_queues_empty = any_thread().immediate_incoming_queue.empty();
812 } 822 }
813 // Avoid holding the lock while we fire the notification. 823 // Avoid holding the lock while we fire the notification.
814 if (!immediate_queues_empty) 824 if (!immediate_queues_empty)
815 main_thread_only().time_domain->OnQueueHasImmediateWork(this); 825 main_thread_only().time_domain->OnQueueHasImmediateWork(this);
816 826
817 if (!main_thread_only().delayed_incoming_queue.empty()) { 827 if (!main_thread_only().delayed_incoming_queue.empty()) {
818 main_thread_only().time_domain->ScheduleDelayedWork( 828 main_thread_only().time_domain->ScheduleDelayedWork(
819 this, 829 this,
820 main_thread_only().delayed_incoming_queue.top().delayed_run_time, 830 main_thread_only().delayed_incoming_queue.top().delayed_run_time,
831 main_thread_only().delayed_incoming_queue.top().sequence_num,
821 main_thread_only().time_domain->Now()); 832 main_thread_only().time_domain->Now());
822 } 833 }
823 // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts 834 // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts
824 // a DoWork if needed. 835 // a DoWork if needed.
825 main_thread_only().task_queue_manager->selector_.EnableQueue(this); 836 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
826 } else { 837 } else {
827 if (!main_thread_only().delayed_incoming_queue.empty()) 838 if (!main_thread_only().delayed_incoming_queue.empty())
828 main_thread_only().time_domain->CancelDelayedWork(this); 839 main_thread_only().time_domain->CancelDelayedWork(this);
829 main_thread_only().task_queue_manager->selector_.DisableQueue(this); 840 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
830 } 841 }
(...skipping 27 matching lines...) Expand all
858 869
859 // Re-schedule delayed call to WakeUpForDelayedWork if needed. 870 // Re-schedule delayed call to WakeUpForDelayedWork if needed.
860 if (main_thread_only().delayed_incoming_queue.empty()) { 871 if (main_thread_only().delayed_incoming_queue.empty()) {
861 main_thread_only().time_domain->CancelDelayedWork(this); 872 main_thread_only().time_domain->CancelDelayedWork(this);
862 } else if (first_task_runtime != 873 } else if (first_task_runtime !=
863 main_thread_only().delayed_incoming_queue.top().delayed_run_time) { 874 main_thread_only().delayed_incoming_queue.top().delayed_run_time) {
864 if (IsQueueEnabled()) { 875 if (IsQueueEnabled()) {
865 main_thread_only().time_domain->ScheduleDelayedWork( 876 main_thread_only().time_domain->ScheduleDelayedWork(
866 this, 877 this,
867 main_thread_only().delayed_incoming_queue.top().delayed_run_time, 878 main_thread_only().delayed_incoming_queue.top().delayed_run_time,
879 main_thread_only().delayed_incoming_queue.top().sequence_num,
868 main_thread_only().time_domain->Now()); 880 main_thread_only().time_domain->Now());
869 } 881 }
870 } 882 }
871 } 883 }
872 884
873 void TaskQueueImpl::PushImmediateIncomingTaskForTest( 885 void TaskQueueImpl::PushImmediateIncomingTaskForTest(
874 TaskQueueImpl::Task&& task) { 886 TaskQueueImpl::Task&& task) {
875 base::AutoLock lock(any_thread_lock_); 887 base::AutoLock lock(any_thread_lock_);
876 any_thread().immediate_incoming_queue.push_back(std::move(task)); 888 any_thread().immediate_incoming_queue.push_back(std::move(task));
877 } 889 }
878 890
879 } // namespace internal 891 } // namespace internal
880 } // namespace scheduler 892 } // namespace scheduler
881 } // namespace blink 893 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698