Commit 00074543 authored by Jesse McKenna's avatar Jesse McKenna Committed by Commit Bot

TaskScheduler: Add unit tests for TaskSchedulerImpl::UpdatePriority()

Bug: 889029
Change-Id: I87d82881660aaec994fab40543463bf6e61963ee
Reviewed-on: https://chromium-review.googlesource.com/c/1354322
Commit-Queue: Jesse McKenna <jessemckenna@google.com>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612517}
parent 0a3e48db
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "base/threading/thread_checker_impl.h" #include "base/threading/thread_checker_impl.h"
#include "base/threading/thread_local_storage.h" #include "base/threading/thread_local_storage.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -69,14 +68,6 @@ constexpr size_t kNumTasksPostedPerThread = 150; ...@@ -69,14 +68,6 @@ constexpr size_t kNumTasksPostedPerThread = 150;
constexpr TimeDelta kReclaimTimeForCleanupTests = constexpr TimeDelta kReclaimTimeForCleanupTests =
TimeDelta::FromMilliseconds(500); TimeDelta::FromMilliseconds(500);
// Waits on |event| in a scope where the blocking observer is null, to avoid
// affecting the max tasks.
void WaitWithoutBlockingObserver(WaitableEvent* event) {
internal::ScopedClearBlockingObserverForTesting clear_blocking_observer;
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
event->Wait();
}
class TaskSchedulerWorkerPoolImplTestBase class TaskSchedulerWorkerPoolImplTestBase
: public SchedulerWorkerPool::Delegate { : public SchedulerWorkerPool::Delegate {
protected: protected:
...@@ -252,7 +243,7 @@ TEST_P(TaskSchedulerWorkerPoolImplTestParam, PostTasksWithOneAvailableWorker) { ...@@ -252,7 +243,7 @@ TEST_P(TaskSchedulerWorkerPoolImplTestParam, PostTasksWithOneAvailableWorker) {
GetParam())); GetParam()));
EXPECT_TRUE(blocked_task_factories.back()->PostTask( EXPECT_TRUE(blocked_task_factories.back()->PostTask(
PostNestedTask::NO, PostNestedTask::NO,
BindOnce(&WaitWithoutBlockingObserver, Unretained(&event)))); BindOnce(&test::WaitWithoutBlockingObserver, Unretained(&event))));
blocked_task_factories.back()->WaitForAllTasksToRun(); blocked_task_factories.back()->WaitForAllTasksToRun();
} }
...@@ -288,7 +279,7 @@ TEST_P(TaskSchedulerWorkerPoolImplTestParam, Saturate) { ...@@ -288,7 +279,7 @@ TEST_P(TaskSchedulerWorkerPoolImplTestParam, Saturate) {
GetParam())); GetParam()));
EXPECT_TRUE(factories.back()->PostTask( EXPECT_TRUE(factories.back()->PostTask(
PostNestedTask::NO, PostNestedTask::NO,
BindOnce(&WaitWithoutBlockingObserver, Unretained(&event)))); BindOnce(&test::WaitWithoutBlockingObserver, Unretained(&event))));
factories.back()->WaitForAllTasksToRun(); factories.back()->WaitForAllTasksToRun();
} }
...@@ -404,7 +395,7 @@ void TaskPostedBeforeStart(PlatformThreadRef* platform_thread_ref, ...@@ -404,7 +395,7 @@ void TaskPostedBeforeStart(PlatformThreadRef* platform_thread_ref,
WaitableEvent* barrier) { WaitableEvent* barrier) {
*platform_thread_ref = PlatformThread::CurrentRef(); *platform_thread_ref = PlatformThread::CurrentRef();
task_running->Signal(); task_running->Signal();
WaitWithoutBlockingObserver(barrier); test::WaitWithoutBlockingObserver(barrier);
} }
} // namespace } // namespace
...@@ -483,7 +474,7 @@ class TaskSchedulerWorkerPoolCheckTlsReuse ...@@ -483,7 +474,7 @@ class TaskSchedulerWorkerPoolCheckTlsReuse
public: public:
void SetTlsValueAndWait() { void SetTlsValueAndWait() {
slot_.Set(reinterpret_cast<void*>(kMagicTlsValue)); slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
WaitWithoutBlockingObserver(&waiter_); test::WaitWithoutBlockingObserver(&waiter_);
} }
void CountZeroTlsValuesAndWait(WaitableEvent* count_waiter) { void CountZeroTlsValuesAndWait(WaitableEvent* count_waiter) {
...@@ -491,7 +482,7 @@ class TaskSchedulerWorkerPoolCheckTlsReuse ...@@ -491,7 +482,7 @@ class TaskSchedulerWorkerPoolCheckTlsReuse
subtle::NoBarrier_AtomicIncrement(&zero_tls_values_, 1); subtle::NoBarrier_AtomicIncrement(&zero_tls_values_, 1);
count_waiter->Signal(); count_waiter->Signal();
WaitWithoutBlockingObserver(&waiter_); test::WaitWithoutBlockingObserver(&waiter_);
} }
protected: protected:
...@@ -596,7 +587,7 @@ class TaskSchedulerWorkerPoolHistogramTest ...@@ -596,7 +587,7 @@ class TaskSchedulerWorkerPoolHistogramTest
BindOnce( BindOnce(
[](OnceClosure on_running, WaitableEvent* continue_event) { [](OnceClosure on_running, WaitableEvent* continue_event) {
std::move(on_running).Run(); std::move(on_running).Run();
WaitWithoutBlockingObserver(continue_event); test::WaitWithoutBlockingObserver(continue_event);
}, },
all_workers_running_barrier, continue_event)); all_workers_running_barrier, continue_event));
} }
...@@ -619,8 +610,8 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { ...@@ -619,8 +610,8 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) {
{WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_); {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
// Post a task. // Post a task.
task_runner->PostTask( task_runner->PostTask(FROM_HERE, BindOnce(&test::WaitWithoutBlockingObserver,
FROM_HERE, BindOnce(&WaitWithoutBlockingObserver, Unretained(&event))); Unretained(&event)));
// Post 2 more tasks while the first task hasn't completed its execution. It // Post 2 more tasks while the first task hasn't completed its execution. It
// is guaranteed that these tasks will run immediately after the first task, // is guaranteed that these tasks will run immediately after the first task,
...@@ -733,7 +724,7 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) { ...@@ -733,7 +724,7 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) {
ASSERT_FALSE(thread_ref->is_null()); ASSERT_FALSE(thread_ref->is_null());
EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef()); EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef());
cleanup_thread_running->Signal(); cleanup_thread_running->Signal();
WaitWithoutBlockingObserver(cleanup_thread_continue); test::WaitWithoutBlockingObserver(cleanup_thread_continue);
}, },
Unretained(&thread_ref), Unretained(&cleanup_thread_running), Unretained(&thread_ref), Unretained(&cleanup_thread_running),
Unretained(&cleanup_thread_continue))); Unretained(&cleanup_thread_continue)));
...@@ -778,7 +769,8 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) { ...@@ -778,7 +769,8 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) {
<< "Worker reused. Worker will not cleanup and the " << "Worker reused. Worker will not cleanup and the "
"histogram value will be wrong."; "histogram value will be wrong.";
top_idle_thread_running->Signal(); top_idle_thread_running->Signal();
WaitWithoutBlockingObserver(top_idle_thread_continue); test::WaitWithoutBlockingObserver(
top_idle_thread_continue);
}, },
thread_ref, Unretained(&top_idle_thread_running), thread_ref, Unretained(&top_idle_thread_running),
Unretained(&top_idle_thread_continue))); Unretained(&top_idle_thread_continue)));
...@@ -842,7 +834,7 @@ TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, VerifyStandbyThread) { ...@@ -842,7 +834,7 @@ TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, VerifyStandbyThread) {
RepeatingClosure thread_blocker = BindLambdaForTesting([&]() { RepeatingClosure thread_blocker = BindLambdaForTesting([&]() {
thread_running.Signal(); thread_running.Signal();
WaitWithoutBlockingObserver(&threads_continue); test::WaitWithoutBlockingObserver(&threads_continue);
}); });
// There should be one idle thread until we reach capacity // There should be one idle thread until we reach capacity
...@@ -932,7 +924,7 @@ TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, OnlyKeepActiveStandbyThreads) { ...@@ -932,7 +924,7 @@ TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, OnlyKeepActiveStandbyThreads) {
RepeatingClosure thread_blocker = BindLambdaForTesting([&]() { RepeatingClosure thread_blocker = BindLambdaForTesting([&]() {
thread_running.Signal(); thread_running.Signal();
WaitWithoutBlockingObserver(&threads_continue); test::WaitWithoutBlockingObserver(&threads_continue);
}); });
for (size_t i = 0; i < kMaxTasks; ++i) { for (size_t i = 0; i < kMaxTasks; ++i) {
...@@ -1054,7 +1046,7 @@ class TaskSchedulerWorkerPoolBlockingTest ...@@ -1054,7 +1046,7 @@ class TaskSchedulerWorkerPoolBlockingTest
NestedScopedBlockingCall nested_scoped_blocking_call( NestedScopedBlockingCall nested_scoped_blocking_call(
nested_blocking_type); nested_blocking_type);
blocking_threads_running_closure->Run(); blocking_threads_running_closure->Run();
WaitWithoutBlockingObserver(blocking_threads_continue_); test::WaitWithoutBlockingObserver(blocking_threads_continue_);
}, },
Unretained(&blocking_threads_running_closure), Unretained(&blocking_threads_running_closure),
Unretained(&blocking_threads_continue_), nested_blocking_type)); Unretained(&blocking_threads_continue_), nested_blocking_type));
...@@ -1130,11 +1122,11 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) { ...@@ -1130,11 +1122,11 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) {
WaitableEvent* thread_running, WaitableEvent* thread_can_block, WaitableEvent* thread_running, WaitableEvent* thread_can_block,
WaitableEvent* threads_continue) { WaitableEvent* threads_continue) {
thread_running->Signal(); thread_running->Signal();
WaitWithoutBlockingObserver(thread_can_block); test::WaitWithoutBlockingObserver(thread_can_block);
NestedScopedBlockingCall nested_scoped_blocking_call( NestedScopedBlockingCall nested_scoped_blocking_call(
nested_blocking_type); nested_blocking_type);
WaitWithoutBlockingObserver(threads_continue); test::WaitWithoutBlockingObserver(threads_continue);
}, },
GetParam(), Unretained(&thread_running), GetParam(), Unretained(&thread_running),
Unretained(&thread_can_block), Unretained(&threads_continue))); Unretained(&thread_can_block), Unretained(&threads_continue)));
...@@ -1157,7 +1149,8 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) { ...@@ -1157,7 +1149,8 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) {
[](Closure* extra_threads_running_barrier, [](Closure* extra_threads_running_barrier,
WaitableEvent* extra_threads_continue) { WaitableEvent* extra_threads_continue) {
extra_threads_running_barrier->Run(); extra_threads_running_barrier->Run();
WaitWithoutBlockingObserver(extra_threads_continue); test::WaitWithoutBlockingObserver(
extra_threads_continue);
}, },
Unretained(&extra_threads_running_barrier), Unretained(&extra_threads_running_barrier),
Unretained(&extra_threads_continue))); Unretained(&extra_threads_continue)));
...@@ -1202,7 +1195,7 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, WorkersIdleWhenOverCapacity) { ...@@ -1202,7 +1195,7 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, WorkersIdleWhenOverCapacity) {
auto callback = BindOnce( auto callback = BindOnce(
[](Closure* threads_running_barrier, WaitableEvent* threads_continue) { [](Closure* threads_running_barrier, WaitableEvent* threads_continue) {
threads_running_barrier->Run(); threads_running_barrier->Run();
WaitWithoutBlockingObserver(threads_continue); test::WaitWithoutBlockingObserver(threads_continue);
}, },
Unretained(&threads_running_barrier), Unretained(&threads_continue)); Unretained(&threads_running_barrier), Unretained(&threads_continue));
task_runner_->PostTask(FROM_HERE, std::move(callback)); task_runner_->PostTask(FROM_HERE, std::move(callback));
...@@ -1302,8 +1295,9 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, ...@@ -1302,8 +1295,9 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest,
// Saturate the pool so that a MAY_BLOCK ScopedBlockingCall would increment // Saturate the pool so that a MAY_BLOCK ScopedBlockingCall would increment
// the max tasks. // the max tasks.
for (size_t i = 0; i < kMaxTasks - 1; ++i) { for (size_t i = 0; i < kMaxTasks - 1; ++i) {
task_runner->PostTask(FROM_HERE, BindOnce(&WaitWithoutBlockingObserver, task_runner->PostTask(
Unretained(&can_return))); FROM_HERE,
BindOnce(&test::WaitWithoutBlockingObserver, Unretained(&can_return)));
} }
WaitableEvent can_instantiate_will_block; WaitableEvent can_instantiate_will_block;
...@@ -1317,10 +1311,10 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, ...@@ -1317,10 +1311,10 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest,
WaitableEvent* did_instantiate_will_block, WaitableEvent* did_instantiate_will_block,
WaitableEvent* can_return) { WaitableEvent* can_return) {
ScopedBlockingCall may_block(BlockingType::MAY_BLOCK); ScopedBlockingCall may_block(BlockingType::MAY_BLOCK);
WaitWithoutBlockingObserver(can_instantiate_will_block); test::WaitWithoutBlockingObserver(can_instantiate_will_block);
ScopedBlockingCall will_block(BlockingType::WILL_BLOCK); ScopedBlockingCall will_block(BlockingType::WILL_BLOCK);
did_instantiate_will_block->Signal(); did_instantiate_will_block->Signal();
WaitWithoutBlockingObserver(can_return); test::WaitWithoutBlockingObserver(can_return);
}, },
Unretained(&can_instantiate_will_block), Unretained(&can_instantiate_will_block),
Unretained(&did_instantiate_will_block), Unretained(&can_return))); Unretained(&did_instantiate_will_block), Unretained(&can_return)));
...@@ -1391,9 +1385,9 @@ TEST_F(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) { ...@@ -1391,9 +1385,9 @@ TEST_F(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) {
threads_running_barrier->Run(); threads_running_barrier->Run();
{ {
ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK); ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
WaitWithoutBlockingObserver(blocked_call_continue); test::WaitWithoutBlockingObserver(blocked_call_continue);
} }
WaitWithoutBlockingObserver(threads_continue); test::WaitWithoutBlockingObserver(threads_continue);
}, },
Unretained(&threads_running_barrier), Unretained(&threads_continue), Unretained(&threads_running_barrier), Unretained(&threads_continue),
Unretained(&blocked_call_continue)); Unretained(&blocked_call_continue));
...@@ -1416,7 +1410,8 @@ TEST_F(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) { ...@@ -1416,7 +1410,8 @@ TEST_F(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) {
[](Closure* extra_threads_running_barrier, [](Closure* extra_threads_running_barrier,
WaitableEvent* extra_threads_continue) { WaitableEvent* extra_threads_continue) {
extra_threads_running_barrier->Run(); extra_threads_running_barrier->Run();
WaitWithoutBlockingObserver(extra_threads_continue); test::WaitWithoutBlockingObserver(
extra_threads_continue);
}, },
Unretained(&extra_threads_running_barrier), Unretained(&extra_threads_running_barrier),
Unretained(&extra_threads_continue))); Unretained(&extra_threads_continue)));
...@@ -1475,7 +1470,8 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) { ...@@ -1475,7 +1470,8 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
ScopedBlockingCall scoped_blocking_call( ScopedBlockingCall scoped_blocking_call(
BlockingType::WILL_BLOCK); BlockingType::WILL_BLOCK);
early_threads_barrier_closure->Run(); early_threads_barrier_closure->Run();
WaitWithoutBlockingObserver(early_release_threads_continue); test::WaitWithoutBlockingObserver(
early_release_threads_continue);
} }
early_threads_finished->Run(); early_threads_finished->Run();
}, },
...@@ -1506,7 +1502,7 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) { ...@@ -1506,7 +1502,7 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
WaitableEvent* late_release_thread_contine) { WaitableEvent* late_release_thread_contine) {
ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK); ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
late_threads_barrier_closure->Run(); late_threads_barrier_closure->Run();
WaitWithoutBlockingObserver(late_release_thread_contine); test::WaitWithoutBlockingObserver(late_release_thread_contine);
}, },
Unretained(&late_threads_barrier_closure), Unretained(&late_threads_barrier_closure),
Unretained(&late_release_thread_contine))); Unretained(&late_release_thread_contine)));
...@@ -1533,7 +1529,7 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) { ...@@ -1533,7 +1529,7 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
BindOnce( BindOnce(
[](Closure* closure, WaitableEvent* final_tasks_continue) { [](Closure* closure, WaitableEvent* final_tasks_continue) {
closure->Run(); closure->Run();
WaitWithoutBlockingObserver(final_tasks_continue); test::WaitWithoutBlockingObserver(final_tasks_continue);
}, },
Unretained(&final_tasks_running_barrier), Unretained(&final_tasks_running_barrier),
Unretained(&final_tasks_continue))); Unretained(&final_tasks_continue)));
...@@ -1572,7 +1568,7 @@ TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, MaxBestEffortTasks) { ...@@ -1572,7 +1568,7 @@ TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, MaxBestEffortTasks) {
background_runner->PostTask( background_runner->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() { FROM_HERE, base::BindLambdaForTesting([&]() {
best_effort_tasks_running_barrier.Run(); best_effort_tasks_running_barrier.Run();
WaitWithoutBlockingObserver(&unblock_best_effort_tasks); test::WaitWithoutBlockingObserver(&unblock_best_effort_tasks);
})); }));
} }
best_effort_tasks_running.Wait(); best_effort_tasks_running.Wait();
...@@ -1651,7 +1647,8 @@ TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBestEffortTasksTest, ...@@ -1651,7 +1647,8 @@ TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
FROM_HERE, base::BindLambdaForTesting([&]() { FROM_HERE, base::BindLambdaForTesting([&]() {
blocking_best_effort_tasks_running_barrier.Run(); blocking_best_effort_tasks_running_barrier.Run();
ScopedBlockingCall scoped_blocking_call(GetParam()); ScopedBlockingCall scoped_blocking_call(GetParam());
WaitWithoutBlockingObserver(&unblock_blocking_best_effort_tasks); test::WaitWithoutBlockingObserver(
&unblock_blocking_best_effort_tasks);
})); }));
} }
blocking_best_effort_tasks_running.Wait(); blocking_best_effort_tasks_running.Wait();
...@@ -1671,7 +1668,7 @@ TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBestEffortTasksTest, ...@@ -1671,7 +1668,7 @@ TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
background_runner->PostTask( background_runner->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() { FROM_HERE, base::BindLambdaForTesting([&]() {
best_effort_tasks_running_barrier.Run(); best_effort_tasks_running_barrier.Run();
WaitWithoutBlockingObserver(&unblock_best_effort_tasks); test::WaitWithoutBlockingObserver(&unblock_best_effort_tasks);
})); }));
} }
best_effort_tasks_running.Wait(); best_effort_tasks_running.Wait();
...@@ -1724,7 +1721,7 @@ TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, RacyCleanup) { ...@@ -1724,7 +1721,7 @@ TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, RacyCleanup) {
BindOnce( BindOnce(
[](OnceClosure on_running, WaitableEvent* unblock_threads) { [](OnceClosure on_running, WaitableEvent* unblock_threads) {
std::move(on_running).Run(); std::move(on_running).Run();
WaitWithoutBlockingObserver(unblock_threads); test::WaitWithoutBlockingObserver(unblock_threads);
}, },
threads_running_barrier, Unretained(&unblock_threads))); threads_running_barrier, Unretained(&unblock_threads)));
} }
......
...@@ -256,6 +256,13 @@ TaskSchedulerImpl::CreateCOMSTATaskRunnerWithTraits( ...@@ -256,6 +256,13 @@ TaskSchedulerImpl::CreateCOMSTATaskRunnerWithTraits(
} }
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
scoped_refptr<UpdateableSequencedTaskRunner>
TaskSchedulerImpl::CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
const TaskTraits& traits) {
const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits);
return MakeRefCounted<SchedulerSequencedTaskRunner>(new_traits, this);
}
std::vector<const HistogramBase*> TaskSchedulerImpl::GetHistograms() const { std::vector<const HistogramBase*> TaskSchedulerImpl::GetHistograms() const {
std::vector<const HistogramBase*> histograms; std::vector<const HistogramBase*> histograms;
for (const auto& worker_pool : worker_pools_) for (const auto& worker_pool : worker_pools_)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "base/task/task_scheduler/task_scheduler.h" #include "base/task/task_scheduler/task_scheduler.h"
#include "base/task/task_scheduler/task_tracker.h" #include "base/task/task_scheduler/task_tracker.h"
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "base/updateable_sequenced_task_runner.h"
#include "build/build_config.h" #include "build/build_config.h"
#if defined(OS_POSIX) && !defined(OS_NACL_SFI) #if defined(OS_POSIX) && !defined(OS_NACL_SFI)
...@@ -93,6 +94,9 @@ class BASE_EXPORT TaskSchedulerImpl : public TaskScheduler, ...@@ -93,6 +94,9 @@ class BASE_EXPORT TaskSchedulerImpl : public TaskScheduler,
const TaskTraits& traits, const TaskTraits& traits,
SingleThreadTaskRunnerThreadMode thread_mode) override; SingleThreadTaskRunnerThreadMode thread_mode) override;
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
scoped_refptr<UpdateableSequencedTaskRunner>
CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
const TaskTraits& traits);
private: private:
// Returns the worker pool that runs Tasks with |traits|. // Returns the worker pool that runs Tasks with |traits|.
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "base/task/task_scheduler/test_task_factory.h" #include "base/task/task_scheduler/test_task_factory.h"
#include "base/task/task_scheduler/test_utils.h" #include "base/task/task_scheduler/test_utils.h"
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "base/test/bind_test_util.h"
#include "base/test/gtest_util.h" #include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
...@@ -35,6 +37,7 @@ ...@@ -35,6 +37,7 @@
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/updateable_sequenced_task_runner.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -159,6 +162,18 @@ void VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits& traits, ...@@ -159,6 +162,18 @@ void VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
event->Signal(); event->Signal();
} }
void VerifyOrderAndTaskEnvironmentAndSignalEvent(
const TaskTraits& traits,
SchedulerState state,
WaitableEvent* expected_previous_event,
WaitableEvent* event) {
DCHECK(event);
if (expected_previous_event)
EXPECT_TRUE(expected_previous_event->IsSignaled());
VerifyTaskEnvironment(traits, state);
event->Signal();
}
scoped_refptr<TaskRunner> CreateTaskRunnerWithTraitsAndExecutionMode( scoped_refptr<TaskRunner> CreateTaskRunnerWithTraitsAndExecutionMode(
TaskScheduler* scheduler, TaskScheduler* scheduler,
const TaskTraits& traits, const TaskTraits& traits,
...@@ -906,5 +921,199 @@ TEST_P(TaskSchedulerImplTest, SchedulerWorkerObserver) { ...@@ -906,5 +921,199 @@ TEST_P(TaskSchedulerImplTest, SchedulerWorkerObserver) {
TearDown(); TearDown();
} }
class TaskSchedulerPriorityUpdateTest : public testing::Test {
protected:
struct PoolBlockingEvents {
PoolBlockingEvents(const TaskTraits& pool_traits)
: pool_traits(pool_traits) {}
const TaskTraits pool_traits;
WaitableEvent scheduled;
WaitableEvent blocked;
};
struct TaskRunnerAndEvents {
TaskRunnerAndEvents(
scoped_refptr<UpdateableSequencedTaskRunner> task_runner,
const TaskPriority updated_priority,
WaitableEvent* expected_previous_event)
: task_runner(std::move(task_runner)),
updated_priority(updated_priority),
expected_previous_event(expected_previous_event) {}
scoped_refptr<UpdateableSequencedTaskRunner> task_runner;
const TaskPriority updated_priority;
WaitableEvent scheduled;
WaitableEvent blocked;
WaitableEvent task_ran;
WaitableEvent* expected_previous_event;
};
TaskSchedulerPriorityUpdateTest() : scheduler_("Test") {}
void StartTaskSchedulerWithNumThreadsPerPool(int threads_per_pool) {
constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30);
scheduler_.Start({{threads_per_pool, kSuggestedReclaimTime},
{threads_per_pool, kSuggestedReclaimTime},
{threads_per_pool, kSuggestedReclaimTime},
{threads_per_pool, kSuggestedReclaimTime}},
nullptr);
}
// Create a series of sample task runners that will post tasks at various
// initial priorities, then update priority.
void CreateTaskRunnersAndEvents() {
// Task runner that will start as USER_VISIBLE and update to USER_BLOCKING.
// Its task is expected to run first.
task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>(
scheduler_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
TaskTraits({TaskPriority::USER_VISIBLE})),
TaskPriority::USER_BLOCKING, nullptr));
// Task runner that will start as BEST_EFFORT and update to USER_VISIBLE.
// Its task is expected to run after the USER_BLOCKING task runner's task.
task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>(
scheduler_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
TaskTraits({TaskPriority::BEST_EFFORT})),
TaskPriority::USER_VISIBLE,
&task_runners_and_events_.back()->task_ran));
// Task runner that will start as USER_BLOCKING and update to BEST_EFFORT.
// Its task is expected to run asynchronously with the other two task
// task runners' tasks if background pools exist, or after the USER_VISIBLE
// task runner's task if not.
task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>(
scheduler_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
TaskTraits({TaskPriority::USER_BLOCKING})),
TaskPriority::BEST_EFFORT,
CanUseBackgroundPriorityForSchedulerWorker()
? nullptr
: &task_runners_and_events_.back()->task_ran));
}
void TearDown() override {
scheduler_.FlushForTesting();
scheduler_.JoinForTesting();
}
TaskSchedulerImpl scheduler_;
std::vector<std::unique_ptr<TaskRunnerAndEvents>> task_runners_and_events_;
DISALLOW_COPY_AND_ASSIGN(TaskSchedulerPriorityUpdateTest);
};
// Update the priority of a sequence when it is not scheduled.
TEST_F(TaskSchedulerPriorityUpdateTest, UpdatePrioritySequenceNotScheduled) {
StartTaskSchedulerWithNumThreadsPerPool(1);
// Schedule blocking tasks on all threads to prevent tasks from being
// scheduled later in the test.
std::vector<std::unique_ptr<PoolBlockingEvents>> pool_blocking_events;
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::USER_BLOCKING})));
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::USER_BLOCKING, MayBlock()})));
if (CanUseBackgroundPriorityForSchedulerWorker()) {
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::BEST_EFFORT})));
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::BEST_EFFORT, MayBlock()})));
}
// When all blocking tasks signal |scheduled|, there is a task blocked in
// each pool.
for (auto& pool_blocking_event : pool_blocking_events) {
scheduler_
.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
pool_blocking_event->pool_traits)
->PostTask(
FROM_HERE, BindLambdaForTesting([&]() {
pool_blocking_event->scheduled.Signal();
test::WaitWithoutBlockingObserver(&pool_blocking_event->blocked);
}));
test::WaitWithoutBlockingObserver(&pool_blocking_event->scheduled);
}
CreateTaskRunnersAndEvents();
// Post tasks to multiple task runners while they are at initial priority.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE,
BindOnce(&VerifyOrderAndTaskEnvironmentAndSignalEvent,
task_runner_and_events->updated_priority,
SchedulerState::kAfterSchedulerStart,
Unretained(task_runner_and_events->expected_previous_event),
Unretained(&task_runner_and_events->task_ran)));
}
// Update the priorities of the task runners that posted the tasks.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->UpdatePriority(
task_runner_and_events->updated_priority);
}
// Unblock the task blocking each pool, allowing the posted tasks to run.
// Each posted task will verify that it has been posted with updated priority
// when it runs.
for (auto& pool_blocking_event : pool_blocking_events) {
pool_blocking_event->blocked.Signal();
}
for (auto& task_runner_and_events : task_runners_and_events_) {
test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran);
}
}
// Update the priority of a sequence when it is scheduled, i.e. not currently
// in a priority queue.
TEST_F(TaskSchedulerPriorityUpdateTest, UpdatePrioritySequenceScheduled) {
StartTaskSchedulerWithNumThreadsPerPool(5);
CreateTaskRunnersAndEvents();
// Post blocking tasks to all task runners to prevent tasks from being
// scheduled later in the test.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE, BindLambdaForTesting([&]() {
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
task_runner_and_events->scheduled.Signal();
test::WaitWithoutBlockingObserver(&task_runner_and_events->blocked);
}));
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
test::WaitWithoutBlockingObserver(&task_runner_and_events->scheduled);
}
// Update the priorities of the task runners while they are scheduled and
// blocked.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->UpdatePriority(
task_runner_and_events->updated_priority);
}
// Post an additional task to each task runner.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE,
BindOnce(&VerifyOrderAndTaskEnvironmentAndSignalEvent,
TaskTraits(task_runner_and_events->updated_priority),
SchedulerState::kAfterSchedulerStart,
Unretained(task_runner_and_events->expected_previous_event),
Unretained(&task_runner_and_events->task_ran)));
}
// Unblock the task blocking each task runner, allowing the additional posted
// tasks to run. Each posted task will verify that it has been posted with
// updated priority when it runs.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->blocked.Signal();
test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran);
}
}
} // namespace internal } // namespace internal
} // namespace base } // namespace base
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/task/task_scheduler/scheduler_parallel_task_runner.h" #include "base/task/task_scheduler/scheduler_parallel_task_runner.h"
#include "base/task/task_scheduler/scheduler_sequenced_task_runner.h" #include "base/task/task_scheduler/scheduler_sequenced_task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_restrictions.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace base { namespace base {
...@@ -59,6 +61,14 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits( ...@@ -59,6 +61,14 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
traits, mock_scheduler_task_runner_delegate); traits, mock_scheduler_task_runner_delegate);
} }
// Waits on |event| in a scope where the blocking observer is null, to avoid
// affecting the max tasks in a worker pool.
void WaitWithoutBlockingObserver(WaitableEvent* event) {
internal::ScopedClearBlockingObserverForTesting clear_blocking_observer;
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
event->Wait();
}
MockSchedulerTaskRunnerDelegate::MockSchedulerTaskRunnerDelegate( MockSchedulerTaskRunnerDelegate::MockSchedulerTaskRunnerDelegate(
TrackedRef<TaskTracker> task_tracker, TrackedRef<TaskTracker> task_tracker,
DelayedTaskManager* delayed_task_manager) DelayedTaskManager* delayed_task_manager)
......
...@@ -80,6 +80,8 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits( ...@@ -80,6 +80,8 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
const TaskTraits& traits, const TaskTraits& traits,
MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate); MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate);
void WaitWithoutBlockingObserver(WaitableEvent* event);
} // namespace test } // namespace test
} // namespace internal } // namespace internal
} // namespace base } // namespace base
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment