• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/task/thread_pool/thread_pool_impl.h"
6 
7 #include <stddef.h>
8 
9 #include <atomic>
10 #include <memory>
11 #include <string>
12 #include <tuple>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/base_switches.h"
17 #include "base/cfi_buildflags.h"
18 #include "base/containers/span.h"
19 #include "base/debug/stack_trace.h"
20 #include "base/functional/bind.h"
21 #include "base/functional/callback.h"
22 #include "base/functional/callback_helpers.h"
23 #include "base/memory/raw_ptr.h"
24 #include "base/message_loop/message_pump_type.h"
25 #include "base/metrics/field_trial.h"
26 #include "base/metrics/field_trial_params.h"
27 #include "base/strings/strcat.h"
28 #include "base/system/sys_info.h"
29 #include "base/task/post_job.h"
30 #include "base/task/task_features.h"
31 #include "base/task/task_traits.h"
32 #include "base/task/thread_pool/environment_config.h"
33 #include "base/task/thread_pool/test_task_factory.h"
34 #include "base/task/thread_pool/test_utils.h"
35 #include "base/task/thread_pool/worker_thread_observer.h"
36 #include "base/task/updateable_sequenced_task_runner.h"
37 #include "base/test/bind.h"
38 #include "base/test/gtest_util.h"
39 #include "base/test/scoped_feature_list.h"
40 #include "base/test/test_timeouts.h"
41 #include "base/test/test_waitable_event.h"
42 #include "base/threading/platform_thread.h"
43 #include "base/threading/sequence_local_storage_slot.h"
44 #include "base/threading/simple_thread.h"
45 #include "base/threading/thread.h"
46 #include "base/threading/thread_restrictions.h"
47 #include "base/time/time.h"
48 #include "build/build_config.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 
51 #if BUILDFLAG(IS_POSIX)
52 #include <unistd.h>
53 
54 #include "base/debug/leak_annotations.h"
55 #include "base/files/file_descriptor_watcher_posix.h"
56 #include "base/files/file_util.h"
57 #include "base/posix/eintr_wrapper.h"
58 #endif  // BUILDFLAG(IS_POSIX)
59 
60 #if BUILDFLAG(IS_WIN)
61 #include "base/win/com_init_util.h"
62 #endif  // BUILDFLAG(IS_WIN)
63 
64 namespace base {
65 namespace internal {
66 
67 namespace {
68 
69 constexpr size_t kMaxNumForegroundThreads = 4;
70 constexpr size_t kMaxNumUtilityThreads = 2;
71 
72 struct TraitsExecutionModePair {
TraitsExecutionModePairbase::internal::__anonf5bd97a00111::TraitsExecutionModePair73   TraitsExecutionModePair(const TaskTraits& traits,
74                           TaskSourceExecutionMode execution_mode)
75       : traits(traits), execution_mode(execution_mode) {}
76 
77   TaskTraits traits;
78   TaskSourceExecutionMode execution_mode;
79 };
80 
81 // Returns true if a task with |traits| could run at background thread priority
82 // on this platform. Even if this returns true, it is possible that the task
83 // won't run at background thread priority if a native thread group is used.
TraitsSupportBackgroundThreadType(const TaskTraits & traits)84 bool TraitsSupportBackgroundThreadType(const TaskTraits& traits) {
85   return traits.priority() == TaskPriority::BEST_EFFORT &&
86          traits.thread_policy() == ThreadPolicy::PREFER_BACKGROUND &&
87          CanUseBackgroundThreadTypeForWorkerThread();
88 }
89 
90 // Returns true if a task with |traits| could run at utility thread
91 // type on this platform. Even if this returns true, it is possible that the
92 // task won't run at efficient thread priority if a native thread group is used
93 // or the utility thread group is disabled.
TraitsSupportUtilityThreadType(const TaskTraits & traits)94 bool TraitsSupportUtilityThreadType(const TaskTraits& traits) {
95   return traits.priority() <= TaskPriority::USER_VISIBLE &&
96          traits.thread_policy() == ThreadPolicy::PREFER_BACKGROUND &&
97          CanUseUtilityThreadTypeForWorkerThread();
98 }
99 
100 // Verify that the current thread type and I/O restrictions are appropriate to
101 // run a Task with |traits|.
102 // Note: ExecutionMode is verified inside TestTaskFactory.
VerifyTaskEnvironment(const TaskTraits & traits,bool use_resource_efficient_group)103 void VerifyTaskEnvironment(const TaskTraits& traits,
104                            bool use_resource_efficient_group) {
105   const std::string thread_name(PlatformThread::GetName());
106   const bool is_single_threaded =
107       (thread_name.find("SingleThread") != std::string::npos);
108 
109   const bool expect_background_thread_type =
110       TraitsSupportBackgroundThreadType(traits);
111 
112   const bool expect_utility_thread_type =
113       !TraitsSupportBackgroundThreadType(traits) &&
114       TraitsSupportUtilityThreadType(traits) && use_resource_efficient_group;
115 
116   EXPECT_EQ(expect_background_thread_type ? ThreadType::kBackground
117             : expect_utility_thread_type  ? ThreadType::kUtility
118                                           : ThreadType::kDefault,
119             PlatformThread::GetCurrentThreadType());
120 
121   if (traits.may_block())
122     internal::AssertBlockingAllowed();
123   else
124     internal::AssertBlockingDisallowedForTesting();
125 
126   // Verify that the thread the task is running on is named as expected.
127   EXPECT_THAT(thread_name, ::testing::HasSubstr("ThreadPool"));
128 
129   EXPECT_THAT(thread_name, ::testing::HasSubstr(
130                                expect_background_thread_type ? "Background"
131                                : expect_utility_thread_type  ? "Utility"
132                                                              : "Foreground"));
133 
134   if (is_single_threaded) {
135     // SingleThread workers discriminate blocking/non-blocking tasks.
136     if (traits.may_block()) {
137       EXPECT_THAT(thread_name, ::testing::HasSubstr("Blocking"));
138     } else {
139       EXPECT_THAT(thread_name,
140                   ::testing::Not(::testing::HasSubstr("Blocking")));
141     }
142   } else {
143     EXPECT_THAT(thread_name, ::testing::Not(::testing::HasSubstr("Blocking")));
144   }
145 }
146 
VerifyTaskEnvironmentAndSignalEvent(const TaskTraits & traits,bool use_resource_efficient_group,TestWaitableEvent * event)147 void VerifyTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
148                                          bool use_resource_efficient_group,
149                                          TestWaitableEvent* event) {
150   DCHECK(event);
151   VerifyTaskEnvironment(traits, use_resource_efficient_group);
152   event->Signal();
153 }
154 
VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits & traits,bool use_resource_efficient_group,TimeTicks expected_time,TestWaitableEvent * event)155 void VerifyTimeAndTaskEnvironmentAndSignalEvent(
156     const TaskTraits& traits,
157     bool use_resource_efficient_group,
158     TimeTicks expected_time,
159     TestWaitableEvent* event) {
160   DCHECK(event);
161   EXPECT_LE(expected_time, TimeTicks::Now());
162   VerifyTaskEnvironment(traits, use_resource_efficient_group);
163   event->Signal();
164 }
165 
VerifyOrderAndTaskEnvironmentAndSignalEvent(const TaskTraits & traits,bool use_resource_efficient_group,TestWaitableEvent * expected_previous_event,TestWaitableEvent * event)166 void VerifyOrderAndTaskEnvironmentAndSignalEvent(
167     const TaskTraits& traits,
168     bool use_resource_efficient_group,
169     TestWaitableEvent* expected_previous_event,
170     TestWaitableEvent* event) {
171   DCHECK(event);
172   if (expected_previous_event)
173     EXPECT_TRUE(expected_previous_event->IsSignaled());
174   VerifyTaskEnvironment(traits, use_resource_efficient_group);
175   event->Signal();
176 }
177 
CreateTaskRunnerAndExecutionMode(ThreadPoolImpl * thread_pool,const TaskTraits & traits,TaskSourceExecutionMode execution_mode,SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode=SingleThreadTaskRunnerThreadMode::SHARED)178 scoped_refptr<TaskRunner> CreateTaskRunnerAndExecutionMode(
179     ThreadPoolImpl* thread_pool,
180     const TaskTraits& traits,
181     TaskSourceExecutionMode execution_mode,
182     SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
183         SingleThreadTaskRunnerThreadMode::SHARED) {
184   switch (execution_mode) {
185     case TaskSourceExecutionMode::kParallel:
186       return thread_pool->CreateTaskRunner(traits);
187     case TaskSourceExecutionMode::kSequenced:
188       return thread_pool->CreateSequencedTaskRunner(traits);
189     case TaskSourceExecutionMode::kSingleThread: {
190       return thread_pool->CreateSingleThreadTaskRunner(
191           traits, default_single_thread_task_runner_mode);
192     }
193     case TaskSourceExecutionMode::kJob:
194       break;
195   }
196   ADD_FAILURE() << "Unknown ExecutionMode";
197   return nullptr;
198 }
199 
200 class ThreadPostingTasks : public SimpleThread {
201  public:
202   // Creates a thread that posts Tasks to |thread_pool| with |traits| and
203   // |execution_mode|.
ThreadPostingTasks(ThreadPoolImpl * thread_pool,const TaskTraits & traits,bool use_resource_efficient_group,TaskSourceExecutionMode execution_mode)204   ThreadPostingTasks(ThreadPoolImpl* thread_pool,
205                      const TaskTraits& traits,
206                      bool use_resource_efficient_group,
207                      TaskSourceExecutionMode execution_mode)
208       : SimpleThread("ThreadPostingTasks"),
209         traits_(traits),
210         use_resource_efficient_group_(use_resource_efficient_group),
211         factory_(CreateTaskRunnerAndExecutionMode(thread_pool,
212                                                   traits,
213                                                   execution_mode),
214                  execution_mode) {}
215 
216   ThreadPostingTasks(const ThreadPostingTasks&) = delete;
217   ThreadPostingTasks& operator=(const ThreadPostingTasks&) = delete;
218 
WaitForAllTasksToRun()219   void WaitForAllTasksToRun() { factory_.WaitForAllTasksToRun(); }
220 
221  private:
Run()222   void Run() override {
223     const size_t kNumTasksPerThread = 150;
224     for (size_t i = 0; i < kNumTasksPerThread; ++i) {
225       factory_.PostTask(test::TestTaskFactory::PostNestedTask::NO,
226                         BindOnce(&VerifyTaskEnvironment, traits_,
227                                  use_resource_efficient_group_));
228     }
229   }
230 
231   const TaskTraits traits_;
232   bool use_resource_efficient_group_;
233   test::TestTaskFactory factory_;
234 };
235 
236 // Returns a vector with a TraitsExecutionModePair for each valid combination of
237 // {ExecutionMode, TaskPriority, ThreadPolicy, MayBlock()}.
GetTraitsExecutionModePairs()238 std::vector<TraitsExecutionModePair> GetTraitsExecutionModePairs() {
239   std::vector<TraitsExecutionModePair> params;
240 
241   constexpr TaskSourceExecutionMode execution_modes[] = {
242       TaskSourceExecutionMode::kParallel, TaskSourceExecutionMode::kSequenced,
243       TaskSourceExecutionMode::kSingleThread};
244   constexpr ThreadPolicy thread_policies[] = {
245       ThreadPolicy::PREFER_BACKGROUND, ThreadPolicy::MUST_USE_FOREGROUND};
246 
247   for (TaskSourceExecutionMode execution_mode : execution_modes) {
248     for (ThreadPolicy thread_policy : thread_policies) {
249       for (size_t priority_index = static_cast<size_t>(TaskPriority::LOWEST);
250            priority_index <= static_cast<size_t>(TaskPriority::HIGHEST);
251            ++priority_index) {
252         const TaskPriority priority = static_cast<TaskPriority>(priority_index);
253         params.push_back(
254             TraitsExecutionModePair({priority, thread_policy}, execution_mode));
255         params.push_back(TraitsExecutionModePair(
256             {priority, thread_policy, MayBlock()}, execution_mode));
257       }
258     }
259   }
260 
261   return params;
262 }
263 
264 // Returns a vector with enough TraitsExecutionModePairs to cover all valid
265 // combinations of task destination (background/foreground ThreadGroup,
266 // single-thread) and whether the task is affected by a BEST_EFFORT fence.
267 std::vector<TraitsExecutionModePair>
GetTraitsExecutionModePairsToCoverAllSchedulingOptions()268 GetTraitsExecutionModePairsToCoverAllSchedulingOptions() {
269   return {TraitsExecutionModePair({TaskPriority::BEST_EFFORT},
270                                   TaskSourceExecutionMode::kSequenced),
271           TraitsExecutionModePair({TaskPriority::USER_VISIBLE},
272                                   TaskSourceExecutionMode::kSequenced),
273           TraitsExecutionModePair({TaskPriority::USER_BLOCKING},
274                                   TaskSourceExecutionMode::kSequenced),
275           TraitsExecutionModePair({TaskPriority::BEST_EFFORT},
276                                   TaskSourceExecutionMode::kSingleThread),
277           TraitsExecutionModePair({TaskPriority::USER_VISIBLE},
278                                   TaskSourceExecutionMode::kSingleThread),
279           TraitsExecutionModePair({TaskPriority::USER_BLOCKING},
280                                   TaskSourceExecutionMode::kSingleThread)};
281 }
282 
283 class ThreadPoolImplTestBase : public testing::Test {
284  public:
ThreadPoolImplTestBase()285   ThreadPoolImplTestBase()
286       : thread_pool_(std::make_unique<ThreadPoolImpl>("Test")),
287         service_thread_("ServiceThread") {
288     Thread::Options service_thread_options;
289     service_thread_options.message_pump_type = MessagePumpType::IO;
290     service_thread_.StartWithOptions(std::move(service_thread_options));
291   }
292 
293   ThreadPoolImplTestBase(const ThreadPoolImplTestBase&) = delete;
294   ThreadPoolImplTestBase& operator=(const ThreadPoolImplTestBase&) = delete;
295 
296   virtual bool GetUseResourceEfficientThreadGroup() const = 0;
297   virtual bool GetUseNewJobImplementation() const = 0;
298 
set_worker_thread_observer(std::unique_ptr<WorkerThreadObserver> worker_thread_observer)299   void set_worker_thread_observer(
300       std::unique_ptr<WorkerThreadObserver> worker_thread_observer) {
301     worker_thread_observer_ = std::move(worker_thread_observer);
302   }
303 
StartThreadPool(size_t max_num_foreground_threads=kMaxNumForegroundThreads,size_t max_num_utility_threads=kMaxNumUtilityThreads,TimeDelta reclaim_time=Seconds (30))304   void StartThreadPool(
305       size_t max_num_foreground_threads = kMaxNumForegroundThreads,
306       size_t max_num_utility_threads = kMaxNumUtilityThreads,
307       TimeDelta reclaim_time = Seconds(30)) {
308     SetupFeatures();
309 
310     ThreadPoolInstance::InitParams init_params(max_num_foreground_threads,
311                                                max_num_utility_threads);
312     init_params.suggested_reclaim_time = reclaim_time;
313 
314     thread_pool_->Start(init_params, worker_thread_observer_.get());
315   }
316 
TearDown()317   void TearDown() override {
318     if (did_tear_down_)
319       return;
320 
321     if (thread_pool_) {
322       thread_pool_->FlushForTesting();
323       thread_pool_->JoinForTesting();
324       thread_pool_.reset();
325     }
326     did_tear_down_ = true;
327   }
328 
329   std::unique_ptr<ThreadPoolImpl> thread_pool_;
330   Thread service_thread_;
331 
332  private:
SetupFeatures()333   void SetupFeatures() {
334     std::vector<base::test::FeatureRef> enabled_features;
335     std::vector<base::test::FeatureRef> disabled_features;
336 
337     if (GetUseResourceEfficientThreadGroup()) {
338       enabled_features.push_back(kUseUtilityThreadGroup);
339     } else {
340       disabled_features.push_back(kUseUtilityThreadGroup);
341     }
342 
343     if (GetUseNewJobImplementation()) {
344       enabled_features.push_back(kUseNewJobImplementation);
345     } else {
346       disabled_features.push_back(kUseNewJobImplementation);
347     }
348 
349     feature_list_.InitWithFeatures(enabled_features, disabled_features);
350   }
351 
352   base::test::ScopedFeatureList feature_list_;
353   std::unique_ptr<WorkerThreadObserver> worker_thread_observer_;
354   bool did_tear_down_ = false;
355 };
356 
357 class ThreadPoolImplTest
358     : public ThreadPoolImplTestBase,
359       public testing::WithParamInterface<
360           std::pair<bool, /* use_resource_efficient_thread_group */
361                     bool /* use_new_job_implementation */>> {
362  public:
GetUseResourceEfficientThreadGroup() const363   bool GetUseResourceEfficientThreadGroup() const override {
364     return GetParam().first;
365   }
366 
GetUseNewJobImplementation() const367   bool GetUseNewJobImplementation() const override { return GetParam().second; }
368 };
369 
370 // Tests run for enough traits and execution mode combinations to cover all
371 // valid combinations of task destination (background/foreground ThreadGroup,
372 // single-thread) and whether the task is affected by a BEST_EFFORT fence.
373 class ThreadPoolImplTest_CoverAllSchedulingOptions
374     : public ThreadPoolImplTestBase,
375       public testing::WithParamInterface<
376           std::tuple<bool /* use_resource_efficient_thread_group */,
377                      TraitsExecutionModePair>> {
378  public:
379   ThreadPoolImplTest_CoverAllSchedulingOptions() = default;
380   ThreadPoolImplTest_CoverAllSchedulingOptions(
381       const ThreadPoolImplTest_CoverAllSchedulingOptions&) = delete;
382   ThreadPoolImplTest_CoverAllSchedulingOptions& operator=(
383       const ThreadPoolImplTest_CoverAllSchedulingOptions&) = delete;
384 
GetUseResourceEfficientThreadGroup() const385   bool GetUseResourceEfficientThreadGroup() const override {
386     return std::get<0>(GetParam());
387   }
GetUseNewJobImplementation() const388   bool GetUseNewJobImplementation() const override { return true; }
GetTraits() const389   TaskTraits GetTraits() const { return std::get<1>(GetParam()).traits; }
GetExecutionMode() const390   TaskSourceExecutionMode GetExecutionMode() const {
391     return std::get<1>(GetParam()).execution_mode;
392   }
393 };
394 
395 }  // namespace
396 
397 // Verifies that a Task posted via PostDelayedTask with parameterized TaskTraits
398 // and no delay runs on a thread with the expected priority and I/O
399 // restrictions. The ExecutionMode parameter is ignored by this test.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskNoDelay)400 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskNoDelay) {
401   StartThreadPool();
402   TestWaitableEvent task_ran;
403   thread_pool_->PostDelayedTask(
404       FROM_HERE, GetTraits(),
405       BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetTraits(),
406                GetUseResourceEfficientThreadGroup(), Unretained(&task_ran)),
407       TimeDelta());
408   task_ran.Wait();
409 }
410 
411 // Verifies that a Task posted via PostDelayedTask with parameterized
412 // TaskTraits and a non-zero delay runs on a thread with the expected priority
413 // and I/O restrictions after the delay expires. The ExecutionMode parameter is
414 // ignored by this test.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskWithDelay)415 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskWithDelay) {
416   StartThreadPool();
417   TestWaitableEvent task_ran;
418   thread_pool_->PostDelayedTask(
419       FROM_HERE, GetTraits(),
420       BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetTraits(),
421                GetUseResourceEfficientThreadGroup(),
422                TimeTicks::Now() + TestTimeouts::tiny_timeout(),
423                Unretained(&task_ran)),
424       TestTimeouts::tiny_timeout());
425   task_ran.Wait();
426 }
427 
428 namespace {
429 
CreateSequencedTaskRunnerAndExecutionMode(ThreadPoolImpl * thread_pool,const TaskTraits & traits,TaskSourceExecutionMode execution_mode,SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode=SingleThreadTaskRunnerThreadMode::SHARED)430 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerAndExecutionMode(
431     ThreadPoolImpl* thread_pool,
432     const TaskTraits& traits,
433     TaskSourceExecutionMode execution_mode,
434     SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
435         SingleThreadTaskRunnerThreadMode::SHARED) {
436   switch (execution_mode) {
437     case TaskSourceExecutionMode::kSequenced:
438       return thread_pool->CreateSequencedTaskRunner(traits);
439     case TaskSourceExecutionMode::kSingleThread: {
440       return thread_pool->CreateSingleThreadTaskRunner(
441           traits, default_single_thread_task_runner_mode);
442     }
443     case TaskSourceExecutionMode::kParallel:
444     case TaskSourceExecutionMode::kJob:
445       ADD_FAILURE() << "Tests below don't cover these modes";
446       return nullptr;
447   }
448   ADD_FAILURE() << "Unknown ExecutionMode";
449   return nullptr;
450 }
451 
452 }  // namespace
453 
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskAtViaTaskRunner)454 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
455        PostDelayedTaskAtViaTaskRunner) {
456   StartThreadPool();
457   TestWaitableEvent task_ran;
458   // Only runs for kSequenced and kSingleThread.
459   auto handle =
460       CreateSequencedTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
461                                                 GetExecutionMode())
462           ->PostCancelableDelayedTaskAt(
463               subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
464               BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetTraits(),
465                        GetUseResourceEfficientThreadGroup(),
466                        TimeTicks::Now() + TestTimeouts::tiny_timeout(),
467                        Unretained(&task_ran)),
468               TimeTicks::Now() + TestTimeouts::tiny_timeout(),
469               subtle::DelayPolicy::kFlexibleNoSooner);
470   task_ran.Wait();
471 }
472 
473 // Verifies that Tasks posted via a TaskRunner with parameterized TaskTraits and
474 // ExecutionMode run on a thread with the expected priority and I/O restrictions
475 // and respect the characteristics of their ExecutionMode.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostTasksViaTaskRunner)476 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTasksViaTaskRunner) {
477   StartThreadPool();
478   test::TestTaskFactory factory(
479       CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
480                                        GetExecutionMode()),
481       GetExecutionMode());
482 
483   const size_t kNumTasksPerTest = 150;
484   for (size_t i = 0; i < kNumTasksPerTest; ++i) {
485     factory.PostTask(test::TestTaskFactory::PostNestedTask::NO,
486                      BindOnce(&VerifyTaskEnvironment, GetTraits(),
487                               GetUseResourceEfficientThreadGroup()));
488   }
489 
490   factory.WaitForAllTasksToRun();
491 }
492 
493 // Verifies that a task posted via PostDelayedTask without a delay doesn't run
494 // before Start() is called.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskNoDelayBeforeStart)495 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
496        PostDelayedTaskNoDelayBeforeStart) {
497   TestWaitableEvent task_running;
498   thread_pool_->PostDelayedTask(
499       FROM_HERE, GetTraits(),
500       BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetTraits(),
501                GetUseResourceEfficientThreadGroup(), Unretained(&task_running)),
502       TimeDelta());
503 
504   // Wait a little bit to make sure that the task doesn't run before Start().
505   // Note: This test won't catch a case where the task runs just after the check
506   // and before Start(). However, we expect the test to be flaky if the tested
507   // code allows that to happen.
508   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
509   EXPECT_FALSE(task_running.IsSignaled());
510 
511   StartThreadPool();
512   task_running.Wait();
513 }
514 
515 // Verifies that a task posted via PostDelayedTask with a delay doesn't run
516 // before Start() is called.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskWithDelayBeforeStart)517 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
518        PostDelayedTaskWithDelayBeforeStart) {
519   TestWaitableEvent task_running;
520   thread_pool_->PostDelayedTask(
521       FROM_HERE, GetTraits(),
522       BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetTraits(),
523                GetUseResourceEfficientThreadGroup(),
524                TimeTicks::Now() + TestTimeouts::tiny_timeout(),
525                Unretained(&task_running)),
526       TestTimeouts::tiny_timeout());
527 
528   // Wait a little bit to make sure that the task doesn't run before Start().
529   // Note: This test won't catch a case where the task runs just after the check
530   // and before Start(). However, we expect the test to be flaky if the tested
531   // code allows that to happen.
532   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
533   EXPECT_FALSE(task_running.IsSignaled());
534 
535   StartThreadPool();
536   task_running.Wait();
537 }
538 
539 // Verifies that a task posted via a TaskRunner doesn't run before Start() is
540 // called.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostTaskViaTaskRunnerBeforeStart)541 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
542        PostTaskViaTaskRunnerBeforeStart) {
543   bool use_resource_efficient_thread_group =
544       GetUseResourceEfficientThreadGroup();
545   // The worker_thread of SingleThreadTaskRunner is selected before
546   // kUseUtilityThreadGroup feature is set up at StartThreadPool().
547   if (GetExecutionMode() == TaskSourceExecutionMode::kSingleThread) {
548     use_resource_efficient_thread_group = false;
549   }
550   TestWaitableEvent task_running;
551   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
552                                    GetExecutionMode())
553       ->PostTask(FROM_HERE,
554                  BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetTraits(),
555                           use_resource_efficient_thread_group,
556                           Unretained(&task_running)));
557 
558   // Wait a little bit to make sure that the task doesn't run before Start().
559   // Note: This test won't catch a case where the task runs just after the check
560   // and before Start(). However, we expect the test to be flaky if the tested
561   // code allows that to happen.
562   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
563   EXPECT_FALSE(task_running.IsSignaled());
564 
565   StartThreadPool();
566 
567   // This should not hang if the task runs after Start().
568   task_running.Wait();
569 }
570 
571 // Verify that posting tasks after the thread pool was destroyed fails but
572 // doesn't crash.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostTaskAfterDestroy)573 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTaskAfterDestroy) {
574   StartThreadPool();
575 
576   auto task_runner = CreateTaskRunnerAndExecutionMode(
577       thread_pool_.get(), GetTraits(), GetExecutionMode());
578   EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
579   thread_pool_->JoinForTesting();
580   thread_pool_.reset();
581 
582   EXPECT_FALSE(
583       task_runner->PostTask(FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
584 }
585 
586 // Verifies that FlushAsyncForTesting() calls back correctly for all trait and
587 // execution mode pairs.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,FlushAsyncForTestingSimple)588 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
589        FlushAsyncForTestingSimple) {
590   StartThreadPool();
591 
592   TestWaitableEvent unblock_task;
593   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
594                                    GetExecutionMode(),
595                                    SingleThreadTaskRunnerThreadMode::DEDICATED)
596       ->PostTask(FROM_HERE,
597                  BindOnce(&TestWaitableEvent::Wait, Unretained(&unblock_task)));
598 
599   TestWaitableEvent flush_event;
600   thread_pool_->FlushAsyncForTesting(
601       BindOnce(&TestWaitableEvent::Signal, Unretained(&flush_event)));
602   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
603   EXPECT_FALSE(flush_event.IsSignaled());
604 
605   unblock_task.Signal();
606 
607   flush_event.Wait();
608 }
609 
610 // Verifies that BEST_EFFORT tasks don't run when the
611 // --disable-best-effort-tasks command-line switch is specified.
612 //
613 // Not using the same fixture as other tests because we want to append a command
614 // line switch before creating the pool.
TEST(ThreadPoolImplTest_Switch,DisableBestEffortTasksSwitch)615 TEST(ThreadPoolImplTest_Switch, DisableBestEffortTasksSwitch) {
616   CommandLine::ForCurrentProcess()->AppendSwitch(
617       switches::kDisableBestEffortTasks);
618 
619   ThreadPoolImpl thread_pool("Test");
620   ThreadPoolInstance::InitParams init_params(kMaxNumForegroundThreads,
621                                              kMaxNumUtilityThreads);
622   thread_pool.Start(init_params, nullptr);
623 
624   AtomicFlag best_effort_can_run;
625   TestWaitableEvent best_effort_did_run;
626   thread_pool.PostDelayedTask(
627       FROM_HERE,
628       {TaskPriority::BEST_EFFORT, TaskShutdownBehavior::BLOCK_SHUTDOWN},
629       BindLambdaForTesting([&]() {
630         EXPECT_TRUE(best_effort_can_run.IsSet());
631         best_effort_did_run.Signal();
632       }),
633       TimeDelta());
634 
635   TestWaitableEvent user_blocking_did_run;
636   thread_pool.PostDelayedTask(
637       FROM_HERE, {TaskPriority::USER_BLOCKING},
638       BindLambdaForTesting([&]() { user_blocking_did_run.Signal(); }),
639       TimeDelta());
640 
641   // The USER_BLOCKING task should run.
642   user_blocking_did_run.Wait();
643 
644   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
645 
646   // The BEST_EFFORT task should not run when a BEST_EFFORT fence is deleted.
647   thread_pool.BeginBestEffortFence();
648   thread_pool.EndBestEffortFence();
649 
650   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
651 
652   // The BEST_EFFORT task should only run during shutdown.
653   best_effort_can_run.Set();
654   thread_pool.Shutdown();
655   EXPECT_TRUE(best_effort_did_run.IsSignaled());
656   thread_pool.JoinForTesting();
657 }
658 
659 // Verifies that tasks only run when allowed by fences.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,Fence)660 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, Fence) {
661   StartThreadPool();
662 
663   AtomicFlag can_run;
664   TestWaitableEvent did_run;
665   thread_pool_->BeginFence();
666 
667   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
668                                    GetExecutionMode())
669       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
670                    EXPECT_TRUE(can_run.IsSet());
671                    did_run.Signal();
672                  }));
673 
674   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
675 
676   can_run.Set();
677   thread_pool_->EndFence();
678   did_run.Wait();
679 }
680 
681 // Verifies that multiple fences can exist at the same time.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,MultipleFences)682 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleFences) {
683   StartThreadPool();
684 
685   AtomicFlag can_run;
686   TestWaitableEvent did_run;
687   thread_pool_->BeginFence();
688   thread_pool_->BeginFence();
689 
690   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
691                                    GetExecutionMode())
692       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
693                    EXPECT_TRUE(can_run.IsSet());
694                    did_run.Signal();
695                  }));
696 
697   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
698 
699   thread_pool_->EndFence();
700   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
701 
702   // The task can only run when both fences are removed.
703   can_run.Set();
704   thread_pool_->EndFence();
705 
706   did_run.Wait();
707 }
708 
709 // Verifies that a call to BeginFence() before Start() is honored.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,FenceBeforeStart)710 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FenceBeforeStart) {
711   thread_pool_->BeginFence();
712   StartThreadPool();
713 
714   AtomicFlag can_run;
715   TestWaitableEvent did_run;
716 
717   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
718                                    GetExecutionMode())
719       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
720                    EXPECT_TRUE(can_run.IsSet());
721                    did_run.Signal();
722                  }));
723 
724   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
725 
726   can_run.Set();
727   thread_pool_->EndFence();
728   did_run.Wait();
729 }
730 
731 // Verifies that tasks only run when allowed by BEST_EFFORT fences.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,BestEffortFence)732 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, BestEffortFence) {
733   StartThreadPool();
734 
735   AtomicFlag can_run;
736   TestWaitableEvent did_run;
737   thread_pool_->BeginBestEffortFence();
738 
739   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
740                                    GetExecutionMode())
741       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
742                    if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
743                      EXPECT_TRUE(can_run.IsSet());
744                    did_run.Signal();
745                  }));
746 
747   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
748 
749   can_run.Set();
750   thread_pool_->EndBestEffortFence();
751   did_run.Wait();
752 }
753 
754 // Verifies that multiple BEST_EFFORT fences can exist at the same time.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,MultipleBestEffortFences)755 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleBestEffortFences) {
756   StartThreadPool();
757 
758   AtomicFlag can_run;
759   TestWaitableEvent did_run;
760   thread_pool_->BeginBestEffortFence();
761   thread_pool_->BeginBestEffortFence();
762 
763   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
764                                    GetExecutionMode())
765       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
766                    if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
767                      EXPECT_TRUE(can_run.IsSet());
768                    did_run.Signal();
769                  }));
770 
771   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
772 
773   thread_pool_->EndBestEffortFence();
774   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
775 
776   // The task can only run when both fences are removed.
777   can_run.Set();
778   thread_pool_->EndBestEffortFence();
779 
780   did_run.Wait();
781 }
782 
783 // Verifies that a call to BeginBestEffortFence() before Start() is honored.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,BestEffortFenceBeforeStart)784 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
785        BestEffortFenceBeforeStart) {
786   thread_pool_->BeginBestEffortFence();
787   StartThreadPool();
788 
789   AtomicFlag can_run;
790   TestWaitableEvent did_run;
791 
792   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
793                                    GetExecutionMode())
794       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
795                    if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
796                      EXPECT_TRUE(can_run.IsSet());
797                    did_run.Signal();
798                  }));
799 
800   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
801 
802   can_run.Set();
803   thread_pool_->EndBestEffortFence();
804   did_run.Wait();
805 }
806 
807 // Spawns threads that simultaneously post Tasks to TaskRunners with various
808 // TaskTraits and ExecutionModes. Verifies that each Task runs on a thread with
809 // the expected priority and I/O restrictions and respects the characteristics
810 // of its ExecutionMode.
TEST_P(ThreadPoolImplTest,MultipleTraitsExecutionModePair)811 TEST_P(ThreadPoolImplTest, MultipleTraitsExecutionModePair) {
812   StartThreadPool();
813   std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
814   for (const auto& test_params : GetTraitsExecutionModePairs()) {
815     threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
816         thread_pool_.get(), test_params.traits,
817         GetUseResourceEfficientThreadGroup(), test_params.execution_mode));
818     threads_posting_tasks.back()->Start();
819   }
820 
821   for (const auto& thread : threads_posting_tasks) {
822     thread->WaitForAllTasksToRun();
823     thread->Join();
824   }
825 }
826 
TEST_P(ThreadPoolImplTest,GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated)827 TEST_P(ThreadPoolImplTest,
828        GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated) {
829   StartThreadPool();
830 
831   // GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() does not support
832   // TaskPriority::BEST_EFFORT.
833   GTEST_FLAG_SET(death_test_style, "threadsafe");
834   EXPECT_DCHECK_DEATH({
835     thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
836         {TaskPriority::BEST_EFFORT});
837   });
838   EXPECT_DCHECK_DEATH({
839     thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
840         {MayBlock(), TaskPriority::BEST_EFFORT});
841   });
842 
843   EXPECT_EQ(GetUseResourceEfficientThreadGroup() &&
844                     CanUseUtilityThreadTypeForWorkerThread()
845                 ? kMaxNumUtilityThreads
846                 : kMaxNumForegroundThreads,
847             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
848                 {TaskPriority::USER_VISIBLE}));
849   EXPECT_EQ(GetUseResourceEfficientThreadGroup() &&
850                     CanUseUtilityThreadTypeForWorkerThread()
851                 ? kMaxNumUtilityThreads
852                 : kMaxNumForegroundThreads,
853             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
854                 {MayBlock(), TaskPriority::USER_VISIBLE}));
855   EXPECT_EQ(kMaxNumForegroundThreads,
856             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
857                 {TaskPriority::USER_BLOCKING}));
858   EXPECT_EQ(kMaxNumForegroundThreads,
859             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
860                 {MayBlock(), TaskPriority::USER_BLOCKING}));
861 }
862 
863 // Verify that the RunsTasksInCurrentSequence() method of a SequencedTaskRunner
864 // returns false when called from a task that isn't part of the sequence.
TEST_P(ThreadPoolImplTest,SequencedRunsTasksInCurrentSequence)865 TEST_P(ThreadPoolImplTest, SequencedRunsTasksInCurrentSequence) {
866   StartThreadPool();
867   auto single_thread_task_runner = thread_pool_->CreateSingleThreadTaskRunner(
868       {}, SingleThreadTaskRunnerThreadMode::SHARED);
869   auto sequenced_task_runner = thread_pool_->CreateSequencedTaskRunner({});
870 
871   TestWaitableEvent task_ran;
872   single_thread_task_runner->PostTask(
873       FROM_HERE,
874       BindOnce(
875           [](scoped_refptr<SequencedTaskRunner> sequenced_task_runner,
876              TestWaitableEvent* task_ran) {
877             EXPECT_FALSE(sequenced_task_runner->RunsTasksInCurrentSequence());
878             task_ran->Signal();
879           },
880           sequenced_task_runner, Unretained(&task_ran)));
881   task_ran.Wait();
882 }
883 
884 // Verify that the RunsTasksInCurrentSequence() method of a
885 // SingleThreadTaskRunner returns false when called from a task that isn't part
886 // of the sequence.
TEST_P(ThreadPoolImplTest,SingleThreadRunsTasksInCurrentSequence)887 TEST_P(ThreadPoolImplTest, SingleThreadRunsTasksInCurrentSequence) {
888   StartThreadPool();
889   auto sequenced_task_runner = thread_pool_->CreateSequencedTaskRunner({});
890   auto single_thread_task_runner = thread_pool_->CreateSingleThreadTaskRunner(
891       {}, SingleThreadTaskRunnerThreadMode::SHARED);
892 
893   TestWaitableEvent task_ran;
894   sequenced_task_runner->PostTask(
895       FROM_HERE,
896       BindOnce(
897           [](scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner,
898              TestWaitableEvent* task_ran) {
899             EXPECT_FALSE(
900                 single_thread_task_runner->RunsTasksInCurrentSequence());
901             task_ran->Signal();
902           },
903           single_thread_task_runner, Unretained(&task_ran)));
904   task_ran.Wait();
905 }
906 
907 #if BUILDFLAG(IS_WIN)
TEST_P(ThreadPoolImplTest,COMSTATaskRunnersRunWithCOMSTA)908 TEST_P(ThreadPoolImplTest, COMSTATaskRunnersRunWithCOMSTA) {
909   StartThreadPool();
910   auto com_sta_task_runner = thread_pool_->CreateCOMSTATaskRunner(
911       {}, SingleThreadTaskRunnerThreadMode::SHARED);
912 
913   TestWaitableEvent task_ran;
914   com_sta_task_runner->PostTask(
915       FROM_HERE, BindOnce(
916                      [](TestWaitableEvent* task_ran) {
917                        win::AssertComApartmentType(win::ComApartmentType::STA);
918                        task_ran->Signal();
919                      },
920                      Unretained(&task_ran)));
921   task_ran.Wait();
922 }
923 #endif  // BUILDFLAG(IS_WIN)
924 
TEST_P(ThreadPoolImplTest,DelayedTasksNotRunAfterShutdown)925 TEST_P(ThreadPoolImplTest, DelayedTasksNotRunAfterShutdown) {
926   StartThreadPool();
927   // As with delayed tasks in general, this is racy. If the task does happen to
928   // run after Shutdown within the timeout, it will fail this test.
929   //
930   // The timeout should be set sufficiently long enough to ensure that the
931   // delayed task did not run. 2x is generally good enough.
932   //
933   // A non-racy way to do this would be to post two sequenced tasks:
934   // 1) Regular Post Task: A WaitableEvent.Wait
935   // 2) Delayed Task: ADD_FAILURE()
936   // and signalling the WaitableEvent after Shutdown() on a different thread
937   // since Shutdown() will block. However, the cost of managing this extra
938   // thread was deemed to be too great for the unlikely race.
939   thread_pool_->PostDelayedTask(FROM_HERE, {},
940                                 BindOnce([]() { ADD_FAILURE(); }),
941                                 TestTimeouts::tiny_timeout());
942   thread_pool_->Shutdown();
943   PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 2);
944 }
945 
946 #if BUILDFLAG(IS_POSIX)
947 
TEST_P(ThreadPoolImplTest,FileDescriptorWatcherNoOpsAfterShutdown)948 TEST_P(ThreadPoolImplTest, FileDescriptorWatcherNoOpsAfterShutdown) {
949   StartThreadPool();
950 
951   int pipes[2];
952   ASSERT_EQ(0, pipe(pipes));
953 
954   scoped_refptr<TaskRunner> blocking_task_runner =
955       thread_pool_->CreateSequencedTaskRunner(
956           {TaskShutdownBehavior::BLOCK_SHUTDOWN});
957   blocking_task_runner->PostTask(
958       FROM_HERE,
959       BindOnce(
960           [](int read_fd) {
961             std::unique_ptr<FileDescriptorWatcher::Controller> controller =
962                 FileDescriptorWatcher::WatchReadable(
963                     read_fd, BindRepeating([]() { NOTREACHED(); }));
964 
965             // This test is for components that intentionally leak their
966             // watchers at shutdown. We can't clean |controller| up because its
967             // destructor will assert that it's being called from the correct
968             // sequence. After the thread pool is shutdown, it is not
969             // possible to run tasks on this sequence.
970             //
971             // Note: Do not inline the controller.release() call into the
972             //       ANNOTATE_LEAKING_OBJECT_PTR as the annotation is removed
973             //       by the preprocessor in non-LEAK_SANITIZER builds,
974             //       effectively breaking this test.
975             ANNOTATE_LEAKING_OBJECT_PTR(controller.get());
976             controller.release();
977           },
978           pipes[0]));
979 
980   thread_pool_->Shutdown();
981 
982   constexpr char kByte = '!';
983   ASSERT_TRUE(WriteFileDescriptor(pipes[1], as_bytes(make_span(&kByte, 1u))));
984 
985   // Give a chance for the file watcher to fire before closing the handles.
986   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
987 
988   EXPECT_EQ(0, IGNORE_EINTR(close(pipes[0])));
989   EXPECT_EQ(0, IGNORE_EINTR(close(pipes[1])));
990 }
991 #endif  // BUILDFLAG(IS_POSIX)
992 
993 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)
994 
995 // Verify that FileDescriptorWatcher::WatchReadable() can be called from task
996 // running on a task_runner with GetExecutionMode() without a crash.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,FileDescriptorWatcher)997 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FileDescriptorWatcher) {
998   StartThreadPool();
999 
1000   int fds[2];
1001   ASSERT_EQ(0, pipe(fds));
1002 
1003   auto task_runner = CreateTaskRunnerAndExecutionMode(
1004       thread_pool_.get(), GetTraits(), GetExecutionMode());
1005 
1006   EXPECT_TRUE(task_runner->PostTask(
1007       FROM_HERE, BindOnce(IgnoreResult(&FileDescriptorWatcher::WatchReadable),
1008                           fds[0], DoNothing())));
1009 
1010   thread_pool_->FlushForTesting();
1011 
1012   EXPECT_EQ(0, IGNORE_EINTR(close(fds[0])));
1013   EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
1014 }
1015 
1016 #endif
1017 
1018 // Verify that tasks posted on the same sequence access the same values on
1019 // SequenceLocalStorage, and tasks on different sequences see different values.
TEST_P(ThreadPoolImplTest,SequenceLocalStorage)1020 TEST_P(ThreadPoolImplTest, SequenceLocalStorage) {
1021   StartThreadPool();
1022 
1023   SequenceLocalStorageSlot<int> slot;
1024   auto sequenced_task_runner1 = thread_pool_->CreateSequencedTaskRunner({});
1025   auto sequenced_task_runner2 = thread_pool_->CreateSequencedTaskRunner({});
1026 
1027   sequenced_task_runner1->PostTask(
1028       FROM_HERE,
1029       BindOnce([](SequenceLocalStorageSlot<int>* slot) { slot->emplace(11); },
1030                &slot));
1031 
1032   sequenced_task_runner1->PostTask(
1033       FROM_HERE, BindOnce(
1034                      [](SequenceLocalStorageSlot<int>* slot) {
1035                        EXPECT_EQ(slot->GetOrCreateValue(), 11);
1036                      },
1037                      &slot));
1038 
1039   sequenced_task_runner2->PostTask(
1040       FROM_HERE, BindOnce(
1041                      [](SequenceLocalStorageSlot<int>* slot) {
1042                        EXPECT_NE(slot->GetOrCreateValue(), 11);
1043                      },
1044                      &slot));
1045 
1046   thread_pool_->FlushForTesting();
1047 }
1048 
TEST_P(ThreadPoolImplTest,FlushAsyncNoTasks)1049 TEST_P(ThreadPoolImplTest, FlushAsyncNoTasks) {
1050   StartThreadPool();
1051   bool called_back = false;
1052   thread_pool_->FlushAsyncForTesting(
1053       BindOnce([](bool* called_back) { *called_back = true; },
1054                Unretained(&called_back)));
1055   EXPECT_TRUE(called_back);
1056 }
1057 
1058 namespace {
1059 
1060 // Verifies that all strings passed as argument are found on the current stack.
1061 // Ignores failures if this configuration doesn't have symbols.
VerifyHasStringsOnStack(const std::string & pool_str,const std::string & shutdown_behavior_str)1062 void VerifyHasStringsOnStack(const std::string& pool_str,
1063                              const std::string& shutdown_behavior_str) {
1064   const std::string stack = debug::StackTrace().ToString();
1065   SCOPED_TRACE(stack);
1066   const bool stack_has_symbols =
1067       stack.find("WorkerThread") != std::string::npos;
1068   if (!stack_has_symbols)
1069     return;
1070 
1071   EXPECT_THAT(stack, ::testing::HasSubstr(pool_str));
1072   EXPECT_THAT(stack, ::testing::HasSubstr(shutdown_behavior_str));
1073 }
1074 
1075 }  // namespace
1076 
1077 #if BUILDFLAG(IS_POSIX)
1078 // Many POSIX bots flakily crash on |debug::StackTrace().ToString()|,
1079 // https://crbug.com/840429.
1080 #define MAYBE_IdentifiableStacks DISABLED_IdentifiableStacks
1081 #elif BUILDFLAG(IS_WIN) && \
1082     (defined(ADDRESS_SANITIZER) || BUILDFLAG(CFI_CAST_CHECK))
1083 // Hangs on WinASan and WinCFI (grabbing StackTrace() too slow?),
1084 // https://crbug.com/845010#c7.
1085 #define MAYBE_IdentifiableStacks DISABLED_IdentifiableStacks
1086 #else
1087 #define MAYBE_IdentifiableStacks IdentifiableStacks
1088 #endif
1089 
1090 // Integration test that verifies that workers have a frame on their stacks
1091 // which easily identifies the type of worker and shutdown behavior (useful to
1092 // diagnose issues from logs without memory dumps).
TEST_P(ThreadPoolImplTest,MAYBE_IdentifiableStacks)1093 TEST_P(ThreadPoolImplTest, MAYBE_IdentifiableStacks) {
1094   StartThreadPool();
1095 
1096   // Shutdown behaviors and expected stack frames.
1097   constexpr std::pair<TaskShutdownBehavior, const char*> shutdown_behaviors[] =
1098       {{TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, "RunContinueOnShutdown"},
1099        {TaskShutdownBehavior::SKIP_ON_SHUTDOWN, "RunSkipOnShutdown"},
1100        {TaskShutdownBehavior::BLOCK_SHUTDOWN, "RunBlockShutdown"}};
1101 
1102   for (const auto& shutdown_behavior : shutdown_behaviors) {
1103     const TaskTraits traits = {shutdown_behavior.first};
1104     const TaskTraits best_effort_traits = {shutdown_behavior.first,
1105                                            TaskPriority::BEST_EFFORT};
1106 
1107     thread_pool_->CreateSequencedTaskRunner(traits)->PostTask(
1108         FROM_HERE, BindOnce(&VerifyHasStringsOnStack, "RunPooledWorker",
1109                             shutdown_behavior.second));
1110     thread_pool_->CreateSequencedTaskRunner(best_effort_traits)
1111         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1112                                        "RunBackgroundPooledWorker",
1113                                        shutdown_behavior.second));
1114 
1115     thread_pool_
1116         ->CreateSingleThreadTaskRunner(traits,
1117                                        SingleThreadTaskRunnerThreadMode::SHARED)
1118         ->PostTask(FROM_HERE,
1119                    BindOnce(&VerifyHasStringsOnStack, "RunSharedWorker",
1120                             shutdown_behavior.second));
1121     thread_pool_
1122         ->CreateSingleThreadTaskRunner(best_effort_traits,
1123                                        SingleThreadTaskRunnerThreadMode::SHARED)
1124         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1125                                        "RunBackgroundSharedWorker",
1126                                        shutdown_behavior.second));
1127 
1128     thread_pool_
1129         ->CreateSingleThreadTaskRunner(
1130             traits, SingleThreadTaskRunnerThreadMode::DEDICATED)
1131         ->PostTask(FROM_HERE,
1132                    BindOnce(&VerifyHasStringsOnStack, "RunDedicatedWorker",
1133                             shutdown_behavior.second));
1134     thread_pool_
1135         ->CreateSingleThreadTaskRunner(
1136             best_effort_traits, SingleThreadTaskRunnerThreadMode::DEDICATED)
1137         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1138                                        "RunBackgroundDedicatedWorker",
1139                                        shutdown_behavior.second));
1140 
1141 #if BUILDFLAG(IS_WIN)
1142     thread_pool_
1143         ->CreateCOMSTATaskRunner(traits,
1144                                  SingleThreadTaskRunnerThreadMode::SHARED)
1145         ->PostTask(FROM_HERE,
1146                    BindOnce(&VerifyHasStringsOnStack, "RunSharedCOMWorker",
1147                             shutdown_behavior.second));
1148     thread_pool_
1149         ->CreateCOMSTATaskRunner(best_effort_traits,
1150                                  SingleThreadTaskRunnerThreadMode::SHARED)
1151         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1152                                        "RunBackgroundSharedCOMWorker",
1153                                        shutdown_behavior.second));
1154 
1155     thread_pool_
1156         ->CreateCOMSTATaskRunner(traits,
1157                                  SingleThreadTaskRunnerThreadMode::DEDICATED)
1158         ->PostTask(FROM_HERE,
1159                    BindOnce(&VerifyHasStringsOnStack, "RunDedicatedCOMWorker",
1160                             shutdown_behavior.second));
1161     thread_pool_
1162         ->CreateCOMSTATaskRunner(best_effort_traits,
1163                                  SingleThreadTaskRunnerThreadMode::DEDICATED)
1164         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1165                                        "RunBackgroundDedicatedCOMWorker",
1166                                        shutdown_behavior.second));
1167 #endif  // BUILDFLAG(IS_WIN)
1168   }
1169 
1170   thread_pool_->FlushForTesting();
1171 }
1172 
TEST_P(ThreadPoolImplTest,WorkerThreadObserver)1173 TEST_P(ThreadPoolImplTest, WorkerThreadObserver) {
1174   auto owned_observer =
1175       std::make_unique<testing::StrictMock<test::MockWorkerThreadObserver>>();
1176   auto* observer = owned_observer.get();
1177   set_worker_thread_observer(std::move(owned_observer));
1178 
1179   // A worker should be created for each thread group. After that, 4 threads
1180   // should be created for each SingleThreadTaskRunnerThreadMode (8 on Windows).
1181   const int kExpectedNumForegroundPoolWorkers = 1;
1182   const int kExpectedNumUtilityPoolWorkers =
1183       GetUseResourceEfficientThreadGroup() &&
1184               CanUseUtilityThreadTypeForWorkerThread()
1185           ? 1
1186           : 0;
1187   const int kExpectedNumBackgroundPoolWorkers =
1188       CanUseBackgroundThreadTypeForWorkerThread() ? 1 : 0;
1189   const int kExpectedNumPoolWorkers = kExpectedNumForegroundPoolWorkers +
1190                                       kExpectedNumUtilityPoolWorkers +
1191                                       kExpectedNumBackgroundPoolWorkers;
1192   const int kExpectedNumSharedSingleThreadedForegroundWorkers = 2;
1193   const int kExpectedNumSharedSingleThreadedUtilityWorkers =
1194       GetUseResourceEfficientThreadGroup() &&
1195               CanUseUtilityThreadTypeForWorkerThread()
1196           ? 2
1197           : 0;
1198   const int kExpectedNumSharedSingleThreadedBackgroundWorkers =
1199       CanUseBackgroundThreadTypeForWorkerThread() ? 2 : 0;
1200   const int kExpectedNumSharedSingleThreadedWorkers =
1201       kExpectedNumSharedSingleThreadedForegroundWorkers +
1202       kExpectedNumSharedSingleThreadedUtilityWorkers +
1203       kExpectedNumSharedSingleThreadedBackgroundWorkers;
1204   const int kExpectedNumDedicatedSingleThreadedWorkers = 6;
1205 
1206   const int kExpectedNumCOMSharedSingleThreadedWorkers =
1207 #if BUILDFLAG(IS_WIN)
1208       kExpectedNumSharedSingleThreadedWorkers;
1209 #else
1210       0;
1211 #endif
1212   const int kExpectedNumCOMDedicatedSingleThreadedWorkers =
1213 #if BUILDFLAG(IS_WIN)
1214       kExpectedNumDedicatedSingleThreadedWorkers;
1215 #else
1216       0;
1217 #endif
1218 
1219   EXPECT_CALL(*observer, OnWorkerThreadMainEntry())
1220       .Times(kExpectedNumPoolWorkers + kExpectedNumSharedSingleThreadedWorkers +
1221              kExpectedNumDedicatedSingleThreadedWorkers +
1222              kExpectedNumCOMSharedSingleThreadedWorkers +
1223              kExpectedNumCOMDedicatedSingleThreadedWorkers);
1224 
1225   // Infinite detach time to prevent workers from invoking
1226   // OnWorkerThreadMainExit() earlier than expected.
1227   StartThreadPool(kMaxNumForegroundThreads, kMaxNumUtilityThreads,
1228                   TimeDelta::Max());
1229 
1230   std::vector<scoped_refptr<SingleThreadTaskRunner>> task_runners;
1231 
1232   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1233       {TaskPriority::BEST_EFFORT}, SingleThreadTaskRunnerThreadMode::SHARED));
1234   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1235       {TaskPriority::BEST_EFFORT, MayBlock()},
1236       SingleThreadTaskRunnerThreadMode::SHARED));
1237   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1238       {TaskPriority::USER_VISIBLE}, SingleThreadTaskRunnerThreadMode::SHARED));
1239   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1240       {TaskPriority::USER_VISIBLE, MayBlock()},
1241       SingleThreadTaskRunnerThreadMode::SHARED));
1242   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1243       {TaskPriority::USER_BLOCKING}, SingleThreadTaskRunnerThreadMode::SHARED));
1244   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1245       {TaskPriority::USER_BLOCKING, MayBlock()},
1246       SingleThreadTaskRunnerThreadMode::SHARED));
1247 
1248   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1249       {TaskPriority::BEST_EFFORT},
1250       SingleThreadTaskRunnerThreadMode::DEDICATED));
1251   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1252       {TaskPriority::BEST_EFFORT, MayBlock()},
1253       SingleThreadTaskRunnerThreadMode::DEDICATED));
1254   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1255       {TaskPriority::USER_VISIBLE},
1256       SingleThreadTaskRunnerThreadMode::DEDICATED));
1257   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1258       {TaskPriority::USER_VISIBLE, MayBlock()},
1259       SingleThreadTaskRunnerThreadMode::DEDICATED));
1260   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1261       {TaskPriority::USER_BLOCKING},
1262       SingleThreadTaskRunnerThreadMode::DEDICATED));
1263   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1264       {TaskPriority::USER_BLOCKING, MayBlock()},
1265       SingleThreadTaskRunnerThreadMode::DEDICATED));
1266 
1267 #if BUILDFLAG(IS_WIN)
1268   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1269       {TaskPriority::BEST_EFFORT}, SingleThreadTaskRunnerThreadMode::SHARED));
1270   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1271       {TaskPriority::BEST_EFFORT, MayBlock()},
1272       SingleThreadTaskRunnerThreadMode::SHARED));
1273   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1274       {TaskPriority::USER_VISIBLE}, SingleThreadTaskRunnerThreadMode::SHARED));
1275   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1276       {TaskPriority::USER_VISIBLE, MayBlock()},
1277       SingleThreadTaskRunnerThreadMode::SHARED));
1278   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1279       {TaskPriority::USER_BLOCKING}, SingleThreadTaskRunnerThreadMode::SHARED));
1280   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1281       {TaskPriority::USER_BLOCKING, MayBlock()},
1282       SingleThreadTaskRunnerThreadMode::SHARED));
1283 
1284   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1285       {TaskPriority::BEST_EFFORT},
1286       SingleThreadTaskRunnerThreadMode::DEDICATED));
1287   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1288       {TaskPriority::BEST_EFFORT, MayBlock()},
1289       SingleThreadTaskRunnerThreadMode::DEDICATED));
1290   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1291       {TaskPriority::USER_VISIBLE},
1292       SingleThreadTaskRunnerThreadMode::DEDICATED));
1293   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1294       {TaskPriority::USER_VISIBLE, MayBlock()},
1295       SingleThreadTaskRunnerThreadMode::DEDICATED));
1296   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1297       {TaskPriority::USER_BLOCKING},
1298       SingleThreadTaskRunnerThreadMode::DEDICATED));
1299   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1300       {TaskPriority::USER_BLOCKING, MayBlock()},
1301       SingleThreadTaskRunnerThreadMode::DEDICATED));
1302 #endif
1303 
1304   for (auto& task_runner : task_runners)
1305     task_runner->PostTask(FROM_HERE, DoNothing());
1306 
1307   // Release single-threaded workers. This should cause dedicated workers to
1308   // invoke OnWorkerThreadMainExit().
1309   observer->AllowCallsOnMainExit(kExpectedNumDedicatedSingleThreadedWorkers +
1310                                  kExpectedNumCOMDedicatedSingleThreadedWorkers);
1311   task_runners.clear();
1312   observer->WaitCallsOnMainExit();
1313 
1314   // Join all remaining workers. This should cause shared single-threaded
1315   // workers and thread pool workers to invoke OnWorkerThreadMainExit().
1316   observer->AllowCallsOnMainExit(kExpectedNumPoolWorkers +
1317                                  kExpectedNumSharedSingleThreadedWorkers +
1318                                  kExpectedNumCOMSharedSingleThreadedWorkers);
1319   TearDown();
1320   observer->WaitCallsOnMainExit();
1321 }
1322 
1323 // Verify that a basic NotifyConcurrencyIncrease() runs the worker task.
TEST_P(ThreadPoolImplTest,BasicJob)1324 TEST_P(ThreadPoolImplTest, BasicJob) {
1325   StartThreadPool();
1326 
1327   TestWaitableEvent threads_running;
1328 
1329   auto job_task = base::MakeRefCounted<test::MockJobTask>(
1330       BindLambdaForTesting(
1331           [&threads_running](JobDelegate*) { threads_running.Signal(); }),
1332       /* num_tasks_to_run */ 1);
1333   scoped_refptr<JobTaskSource> task_source =
1334       job_task->GetJobTaskSource(FROM_HERE, {}, thread_pool_.get());
1335   task_source->NotifyConcurrencyIncrease();
1336 
1337   threads_running.Wait();
1338 }
1339 
1340 // Verify that max concurrency is eventually reached, but not exceeded, when
1341 // concurrency is increased from many workers.
TEST_P(ThreadPoolImplTest,ParallelJob)1342 TEST_P(ThreadPoolImplTest, ParallelJob) {
1343   constexpr size_t kTargetMaxConcurrency = 14;
1344   constexpr size_t kLargeThreadPoolSize = 15;
1345   StartThreadPool(/* max_num_foreground_threads=*/kLargeThreadPoolSize,
1346                   kLargeThreadPoolSize);
1347 
1348   // This test times out with the old job implementation.
1349   // Note: Exit after starting the Thread Pool since TearDown() expects the
1350   // ThreadPool to be started.
1351   if (!GetUseNewJobImplementation()) {
1352     return;
1353   }
1354 
1355   std::atomic_size_t max_concurrency = 2;
1356   std::atomic_size_t num_workers = 0;
1357 
1358   auto worker_task = BindLambdaForTesting([&](JobDelegate* delegate) {
1359     // Increase max concurrency if target is not reached.
1360     size_t current_max_concurrency =
1361         max_concurrency.load(std::memory_order_relaxed);
1362     while (current_max_concurrency < kTargetMaxConcurrency) {
1363       if (max_concurrency.compare_exchange_weak(current_max_concurrency,
1364                                                 current_max_concurrency + 1,
1365                                                 std::memory_order_relaxed)) {
1366         delegate->NotifyConcurrencyIncrease();
1367         break;
1368       }
1369     }
1370 
1371     // Increase number of workers and verify that target max concurrency is not
1372     // exceeded.
1373     size_t current_num_workers =
1374         num_workers.fetch_add(1, std::memory_order_relaxed);
1375     EXPECT_LT(current_num_workers, kTargetMaxConcurrency);
1376 
1377     // Busy wait until the target number of workers is reached.
1378     while (num_workers.load(std::memory_order_relaxed) <
1379            kTargetMaxConcurrency) {
1380     }
1381 
1382     // Sleep to detect if too many workers run the worker task.
1383     PlatformThread::Sleep(TestTimeouts::tiny_timeout());
1384 
1385     // Force the job to exit by setting max concurrency to 0.
1386     max_concurrency.store(0, std::memory_order_relaxed);
1387   });
1388 
1389   auto max_concurrency_callback =
1390       BindLambdaForTesting([&](size_t worker_count) {
1391         return max_concurrency.load(std::memory_order_relaxed);
1392       });
1393 
1394   auto task_source = internal::CreateJobTaskSource(
1395       FROM_HERE, TaskTraits(), worker_task, max_concurrency_callback,
1396       thread_pool_.get());
1397   task_source->NotifyConcurrencyIncrease();
1398   thread_pool_->FlushForTesting();
1399 
1400   EXPECT_EQ(num_workers, kTargetMaxConcurrency);
1401 }
1402 
1403 // Verify that calling ShouldYield() returns true for a job task source that
1404 // needs to change thread group because of a priority update.
TEST_P(ThreadPoolImplTest,ThreadGroupChangeShouldYield)1405 TEST_P(ThreadPoolImplTest, ThreadGroupChangeShouldYield) {
1406   StartThreadPool();
1407 
1408   TestWaitableEvent threads_running;
1409   TestWaitableEvent threads_continue;
1410 
1411   auto job_task = base::MakeRefCounted<test::MockJobTask>(
1412       BindLambdaForTesting(
1413           [&threads_running, &threads_continue](JobDelegate* delegate) {
1414             EXPECT_FALSE(delegate->ShouldYield());
1415 
1416             threads_running.Signal();
1417             threads_continue.Wait();
1418 
1419             // The task source needs to yield if background thread groups exist.
1420             EXPECT_EQ(delegate->ShouldYield(),
1421                       CanUseBackgroundThreadTypeForWorkerThread());
1422           }),
1423       /* num_tasks_to_run */ 1);
1424   scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource(
1425       FROM_HERE, {TaskPriority::USER_VISIBLE}, thread_pool_.get());
1426   task_source->NotifyConcurrencyIncrease();
1427 
1428   threads_running.Wait();
1429   thread_pool_->UpdatePriority(task_source, TaskPriority::BEST_EFFORT);
1430   threads_continue.Signal();
1431 
1432   // Flush the task tracker to be sure that no local variables are accessed by
1433   // tasks after the end of the scope.
1434   thread_pool_->FlushForTesting();
1435 }
1436 
1437 namespace {
1438 
1439 class MustBeDestroyed {
1440  public:
MustBeDestroyed(bool * was_destroyed)1441   explicit MustBeDestroyed(bool* was_destroyed)
1442       : was_destroyed_(was_destroyed) {}
1443   MustBeDestroyed(const MustBeDestroyed&) = delete;
1444   MustBeDestroyed& operator=(const MustBeDestroyed&) = delete;
~MustBeDestroyed()1445   ~MustBeDestroyed() { *was_destroyed_ = true; }
1446 
1447  private:
1448   const raw_ptr<bool> was_destroyed_;
1449 };
1450 
1451 }  // namespace
1452 
1453 // Regression test for https://crbug.com/945087.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,NoLeakWhenPostingNestedTask)1454 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
1455        NoLeakWhenPostingNestedTask) {
1456   StartThreadPool();
1457 
1458   SequenceLocalStorageSlot<std::unique_ptr<MustBeDestroyed>> sls;
1459 
1460   bool was_destroyed = false;
1461   auto must_be_destroyed = std::make_unique<MustBeDestroyed>(&was_destroyed);
1462 
1463   auto task_runner = CreateTaskRunnerAndExecutionMode(
1464       thread_pool_.get(), GetTraits(), GetExecutionMode());
1465 
1466   task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&] {
1467                           sls.emplace(std::move(must_be_destroyed));
1468                           task_runner->PostTask(FROM_HERE, DoNothing());
1469                         }));
1470 
1471   TearDown();
1472 
1473   // The TaskRunner should be deleted along with the Sequence and its
1474   // SequenceLocalStorage when dropping this reference.
1475   task_runner = nullptr;
1476 
1477   EXPECT_TRUE(was_destroyed);
1478 }
1479 
1480 namespace {
1481 
1482 struct TaskRunnerAndEvents {
TaskRunnerAndEventsbase::internal::__anonf5bd97a01c11::TaskRunnerAndEvents1483   TaskRunnerAndEvents(scoped_refptr<UpdateableSequencedTaskRunner> task_runner,
1484                       const TaskPriority updated_priority,
1485                       TestWaitableEvent* expected_previous_event)
1486       : task_runner(std::move(task_runner)),
1487         updated_priority(updated_priority),
1488         expected_previous_event(expected_previous_event) {}
1489 
1490   // The UpdateableSequencedTaskRunner.
1491   scoped_refptr<UpdateableSequencedTaskRunner> task_runner;
1492 
1493   // The priority to use in UpdatePriority().
1494   const TaskPriority updated_priority;
1495 
1496   // Signaled when a task blocking |task_runner| is scheduled.
1497   TestWaitableEvent scheduled;
1498 
1499   // Signaled to release the task blocking |task_runner|.
1500   TestWaitableEvent blocked;
1501 
1502   // Signaled in the task that runs following the priority update.
1503   TestWaitableEvent task_ran;
1504 
1505   // An event that should be signaled before the task following the priority
1506   // update runs.
1507   raw_ptr<TestWaitableEvent> expected_previous_event;
1508 };
1509 
1510 // Create a series of sample task runners that will post tasks at various
1511 // initial priorities, then update priority.
CreateTaskRunnersAndEvents(ThreadPoolImplTest * test,ThreadPolicy thread_policy)1512 std::vector<std::unique_ptr<TaskRunnerAndEvents>> CreateTaskRunnersAndEvents(
1513     ThreadPoolImplTest* test,
1514     ThreadPolicy thread_policy) {
1515   ThreadPoolImpl* thread_pool = test->thread_pool_.get();
1516   std::vector<std::unique_ptr<TaskRunnerAndEvents>> task_runners_and_events;
1517 
1518   // -----
1519   // Task runner that will start as USER_VISIBLE and update to USER_BLOCKING.
1520   // Its task is expected to run first.
1521   task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>(
1522       thread_pool->CreateUpdateableSequencedTaskRunner(
1523           TaskTraits({TaskPriority::USER_VISIBLE, thread_policy})),
1524       TaskPriority::USER_BLOCKING, nullptr));
1525 
1526   // -----
1527   // Task runner that will start as BEST_EFFORT and update to USER_VISIBLE.
1528   // Its task is expected to run after the USER_BLOCKING task runner's task,
1529   // unless resource-efficient thread group exists, in which case they will run
1530   // asynchronously.
1531   TestWaitableEvent* expected_previous_event =
1532       test->GetUseResourceEfficientThreadGroup()
1533           ? nullptr
1534           : &task_runners_and_events.back()->task_ran;
1535   task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>(
1536       thread_pool->CreateUpdateableSequencedTaskRunner(
1537           {TaskPriority::BEST_EFFORT, thread_policy}),
1538       TaskPriority::USER_VISIBLE, expected_previous_event));
1539 
1540   // -----
1541   // Task runner that will start as USER_BLOCKING and update to BEST_EFFORT. Its
1542   // task is expected to run asynchronously with the other two task runners'
1543   // tasks if background thread groups exist, or after the USER_VISIBLE task
1544   // runner's task if not.
1545   //
1546   // If the task following the priority update is expected to run in the
1547   // foreground group, it should be after the task posted to the TaskRunner
1548   // whose priority is updated to USER_VISIBLE.
1549   expected_previous_event =
1550       CanUseBackgroundThreadTypeForWorkerThread() ||
1551               (test->GetUseResourceEfficientThreadGroup() &&
1552                CanUseUtilityThreadTypeForWorkerThread())
1553           ? nullptr
1554           : &task_runners_and_events.back()->task_ran;
1555 
1556   task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>(
1557       thread_pool->CreateUpdateableSequencedTaskRunner(
1558           TaskTraits({TaskPriority::USER_BLOCKING, thread_policy})),
1559       TaskPriority::BEST_EFFORT, expected_previous_event));
1560 
1561   return task_runners_and_events;
1562 }
1563 
1564 // Update the priority of a sequence when it is not scheduled.
TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest * test,ThreadPolicy thread_policy)1565 void TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest* test,
1566                                             ThreadPolicy thread_policy) {
1567   // This test verifies that tasks run in priority order. With more than 1
1568   // thread per pool, it is possible that tasks don't run in order even if
1569   // threads got tasks from the PriorityQueue in order. Therefore, enforce a
1570   // maximum of 1 thread per pool.
1571   constexpr size_t kLocalMaxNumForegroundThreads = 1;
1572 
1573   test->StartThreadPool(kLocalMaxNumForegroundThreads);
1574   auto task_runners_and_events =
1575       CreateTaskRunnersAndEvents(test, thread_policy);
1576 
1577   // Prevent tasks from running.
1578   test->thread_pool_->BeginFence();
1579 
1580   // Post tasks to multiple task runners while they are at initial priority.
1581   // They won't run immediately because of the call to BeginFence() above.
1582   for (auto& task_runner_and_events : task_runners_and_events) {
1583     task_runner_and_events->task_runner->PostTask(
1584         FROM_HERE,
1585         BindOnce(
1586             &VerifyOrderAndTaskEnvironmentAndSignalEvent,
1587             TaskTraits{task_runner_and_events->updated_priority, thread_policy},
1588             test->GetUseResourceEfficientThreadGroup(),
1589             Unretained(task_runner_and_events->expected_previous_event.get()),
1590             Unretained(&task_runner_and_events->task_ran)));
1591   }
1592 
1593   // Update the priorities of the task runners that posted the tasks.
1594   for (auto& task_runner_and_events : task_runners_and_events) {
1595     task_runner_and_events->task_runner->UpdatePriority(
1596         task_runner_and_events->updated_priority);
1597   }
1598 
1599   // Allow tasks to run.
1600   test->thread_pool_->EndFence();
1601 
1602   for (auto& task_runner_and_events : task_runners_and_events)
1603     task_runner_and_events->task_ran.Wait();
1604 }
1605 
1606 // Update the priority of a sequence when it is scheduled, i.e. not currently
1607 // in a priority queue.
TestUpdatePrioritySequenceScheduled(ThreadPoolImplTest * test,ThreadPolicy thread_policy)1608 void TestUpdatePrioritySequenceScheduled(ThreadPoolImplTest* test,
1609                                          ThreadPolicy thread_policy) {
1610   test->StartThreadPool();
1611   auto task_runners_and_events =
1612       CreateTaskRunnersAndEvents(test, thread_policy);
1613 
1614   // Post blocking tasks to all task runners to prevent tasks from being
1615   // scheduled later in the test.
1616   for (auto& task_runner_and_events : task_runners_and_events) {
1617     task_runner_and_events->task_runner->PostTask(
1618         FROM_HERE, BindLambdaForTesting([&]() {
1619           task_runner_and_events->scheduled.Signal();
1620           task_runner_and_events->blocked.Wait();
1621         }));
1622 
1623     task_runner_and_events->scheduled.Wait();
1624   }
1625 
1626   // Update the priorities of the task runners while they are scheduled and
1627   // blocked.
1628   for (auto& task_runner_and_events : task_runners_and_events) {
1629     task_runner_and_events->task_runner->UpdatePriority(
1630         task_runner_and_events->updated_priority);
1631   }
1632 
1633   // Post an additional task to each task runner.
1634   for (auto& task_runner_and_events : task_runners_and_events) {
1635     task_runner_and_events->task_runner->PostTask(
1636         FROM_HERE,
1637         BindOnce(
1638             &VerifyOrderAndTaskEnvironmentAndSignalEvent,
1639             TaskTraits{task_runner_and_events->updated_priority, thread_policy},
1640             test->GetUseResourceEfficientThreadGroup(),
1641             Unretained(task_runner_and_events->expected_previous_event),
1642             Unretained(&task_runner_and_events->task_ran)));
1643   }
1644 
1645   // Unblock the task blocking each task runner, allowing the additional posted
1646   // tasks to run. Each posted task will verify that it has been posted with
1647   // updated priority when it runs.
1648   for (auto& task_runner_and_events : task_runners_and_events) {
1649     task_runner_and_events->blocked.Signal();
1650     task_runner_and_events->task_ran.Wait();
1651   }
1652 }
1653 
1654 }  // namespace
1655 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceNotScheduled_PreferBackground)1656 TEST_P(ThreadPoolImplTest,
1657        UpdatePrioritySequenceNotScheduled_PreferBackground) {
1658   TestUpdatePrioritySequenceNotScheduled(this, ThreadPolicy::PREFER_BACKGROUND);
1659 }
1660 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceNotScheduled_MustUseForeground)1661 TEST_P(ThreadPoolImplTest,
1662        UpdatePrioritySequenceNotScheduled_MustUseForeground) {
1663   TestUpdatePrioritySequenceNotScheduled(this,
1664                                          ThreadPolicy::MUST_USE_FOREGROUND);
1665 }
1666 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceScheduled_PreferBackground)1667 TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled_PreferBackground) {
1668   TestUpdatePrioritySequenceScheduled(this, ThreadPolicy::PREFER_BACKGROUND);
1669 }
1670 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceScheduled_MustUseForeground)1671 TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled_MustUseForeground) {
1672   TestUpdatePrioritySequenceScheduled(this, ThreadPolicy::MUST_USE_FOREGROUND);
1673 }
1674 
1675 // Verify that a ThreadPolicy has to be specified in TaskTraits to increase
1676 // TaskPriority from BEST_EFFORT.
TEST_P(ThreadPoolImplTest,UpdatePriorityFromBestEffortNoThreadPolicy)1677 TEST_P(ThreadPoolImplTest, UpdatePriorityFromBestEffortNoThreadPolicy) {
1678   GTEST_FLAG_SET(death_test_style, "threadsafe");
1679   StartThreadPool();
1680   {
1681     auto task_runner = thread_pool_->CreateUpdateableSequencedTaskRunner(
1682         {TaskPriority::BEST_EFFORT});
1683     EXPECT_DCHECK_DEATH(
1684         { task_runner->UpdatePriority(TaskPriority::USER_VISIBLE); });
1685   }
1686   {
1687     auto task_runner = thread_pool_->CreateUpdateableSequencedTaskRunner(
1688         {TaskPriority::BEST_EFFORT});
1689     EXPECT_DCHECK_DEATH(
1690         { task_runner->UpdatePriority(TaskPriority::USER_BLOCKING); });
1691   }
1692 }
1693 
1694 INSTANTIATE_TEST_SUITE_P(
1695     ,
1696     ThreadPoolImplTest,
1697     ::testing::Values(
1698         // Param 1: Use resource efficient thread group.
1699         // Param 2: Use new job implementation.
1700         std::make_pair(true, false),
1701         std::make_pair(false, false),
1702         std::make_pair(false, true)),
__anonf5bd97a01e02(const testing::TestParamInfo<std::pair<bool, bool>>& info) 1703     [](const testing::TestParamInfo<std::pair<bool, bool>>& info) {
1704       return base::StrCat(
1705           {info.param.first ? "EfficientThreadGroup" : "NoEfficientThreadGroup",
1706            info.param.second ? "NewJob" : "OldJob"});
1707     });
1708 
1709 INSTANTIATE_TEST_SUITE_P(
1710     All,
1711     ThreadPoolImplTest_CoverAllSchedulingOptions,
1712     ::testing::Combine(
1713         ::testing::Bool(),
1714         ::testing::ValuesIn(
1715             GetTraitsExecutionModePairsToCoverAllSchedulingOptions())));
1716 
1717 }  // namespace internal
1718 }  // namespace base
1719