1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <memory>
8*635a8641SAndroid Build Coastguard Worker #include <vector>
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include "base/at_exit.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/atomic_sequence_num.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/atomicops.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/barrier_closure.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/sys_info.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/time/time.h"
20*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
21*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker namespace {
24*635a8641SAndroid Build Coastguard Worker
25*635a8641SAndroid Build Coastguard Worker base::AtomicSequenceNumber constructed_seq_;
26*635a8641SAndroid Build Coastguard Worker base::AtomicSequenceNumber destructed_seq_;
27*635a8641SAndroid Build Coastguard Worker
28*635a8641SAndroid Build Coastguard Worker class ConstructAndDestructLogger {
29*635a8641SAndroid Build Coastguard Worker public:
ConstructAndDestructLogger()30*635a8641SAndroid Build Coastguard Worker ConstructAndDestructLogger() {
31*635a8641SAndroid Build Coastguard Worker constructed_seq_.GetNext();
32*635a8641SAndroid Build Coastguard Worker }
~ConstructAndDestructLogger()33*635a8641SAndroid Build Coastguard Worker ~ConstructAndDestructLogger() {
34*635a8641SAndroid Build Coastguard Worker destructed_seq_.GetNext();
35*635a8641SAndroid Build Coastguard Worker }
36*635a8641SAndroid Build Coastguard Worker
37*635a8641SAndroid Build Coastguard Worker private:
38*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ConstructAndDestructLogger);
39*635a8641SAndroid Build Coastguard Worker };
40*635a8641SAndroid Build Coastguard Worker
41*635a8641SAndroid Build Coastguard Worker class SlowConstructor {
42*635a8641SAndroid Build Coastguard Worker public:
SlowConstructor()43*635a8641SAndroid Build Coastguard Worker SlowConstructor() : some_int_(0) {
44*635a8641SAndroid Build Coastguard Worker // Sleep for 1 second to try to cause a race.
45*635a8641SAndroid Build Coastguard Worker base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
46*635a8641SAndroid Build Coastguard Worker ++constructed;
47*635a8641SAndroid Build Coastguard Worker some_int_ = 12;
48*635a8641SAndroid Build Coastguard Worker }
some_int() const49*635a8641SAndroid Build Coastguard Worker int some_int() const { return some_int_; }
50*635a8641SAndroid Build Coastguard Worker
51*635a8641SAndroid Build Coastguard Worker static int constructed;
52*635a8641SAndroid Build Coastguard Worker private:
53*635a8641SAndroid Build Coastguard Worker int some_int_;
54*635a8641SAndroid Build Coastguard Worker
55*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SlowConstructor);
56*635a8641SAndroid Build Coastguard Worker };
57*635a8641SAndroid Build Coastguard Worker
58*635a8641SAndroid Build Coastguard Worker // static
59*635a8641SAndroid Build Coastguard Worker int SlowConstructor::constructed = 0;
60*635a8641SAndroid Build Coastguard Worker
61*635a8641SAndroid Build Coastguard Worker class SlowDelegate : public base::DelegateSimpleThread::Delegate {
62*635a8641SAndroid Build Coastguard Worker public:
SlowDelegate(base::LazyInstance<SlowConstructor>::DestructorAtExit * lazy)63*635a8641SAndroid Build Coastguard Worker explicit SlowDelegate(
64*635a8641SAndroid Build Coastguard Worker base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy)
65*635a8641SAndroid Build Coastguard Worker : lazy_(lazy) {}
66*635a8641SAndroid Build Coastguard Worker
Run()67*635a8641SAndroid Build Coastguard Worker void Run() override {
68*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(12, lazy_->Get().some_int());
69*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(12, lazy_->Pointer()->some_int());
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker
72*635a8641SAndroid Build Coastguard Worker private:
73*635a8641SAndroid Build Coastguard Worker base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy_;
74*635a8641SAndroid Build Coastguard Worker
75*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SlowDelegate);
76*635a8641SAndroid Build Coastguard Worker };
77*635a8641SAndroid Build Coastguard Worker
78*635a8641SAndroid Build Coastguard Worker } // namespace
79*635a8641SAndroid Build Coastguard Worker
80*635a8641SAndroid Build Coastguard Worker base::LazyInstance<ConstructAndDestructLogger>::DestructorAtExit lazy_logger =
81*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
82*635a8641SAndroid Build Coastguard Worker
TEST(LazyInstanceTest,Basic)83*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, Basic) {
84*635a8641SAndroid Build Coastguard Worker {
85*635a8641SAndroid Build Coastguard Worker base::ShadowingAtExitManager shadow;
86*635a8641SAndroid Build Coastguard Worker
87*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(lazy_logger.IsCreated());
88*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, constructed_seq_.GetNext());
89*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, destructed_seq_.GetNext());
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker lazy_logger.Get();
92*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(lazy_logger.IsCreated());
93*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(2, constructed_seq_.GetNext());
94*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, destructed_seq_.GetNext());
95*635a8641SAndroid Build Coastguard Worker
96*635a8641SAndroid Build Coastguard Worker lazy_logger.Pointer();
97*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(lazy_logger.IsCreated());
98*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(3, constructed_seq_.GetNext());
99*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(2, destructed_seq_.GetNext());
100*635a8641SAndroid Build Coastguard Worker }
101*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(lazy_logger.IsCreated());
102*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(4, constructed_seq_.GetNext());
103*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(4, destructed_seq_.GetNext());
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
106*635a8641SAndroid Build Coastguard Worker base::LazyInstance<SlowConstructor>::DestructorAtExit lazy_slow =
107*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
108*635a8641SAndroid Build Coastguard Worker
TEST(LazyInstanceTest,ConstructorThreadSafety)109*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, ConstructorThreadSafety) {
110*635a8641SAndroid Build Coastguard Worker {
111*635a8641SAndroid Build Coastguard Worker base::ShadowingAtExitManager shadow;
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker SlowDelegate delegate(&lazy_slow);
114*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, SlowConstructor::constructed);
115*635a8641SAndroid Build Coastguard Worker
116*635a8641SAndroid Build Coastguard Worker base::DelegateSimpleThreadPool pool("lazy_instance_cons", 5);
117*635a8641SAndroid Build Coastguard Worker pool.AddWork(&delegate, 20);
118*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, SlowConstructor::constructed);
119*635a8641SAndroid Build Coastguard Worker
120*635a8641SAndroid Build Coastguard Worker pool.Start();
121*635a8641SAndroid Build Coastguard Worker pool.JoinAll();
122*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, SlowConstructor::constructed);
123*635a8641SAndroid Build Coastguard Worker }
124*635a8641SAndroid Build Coastguard Worker }
125*635a8641SAndroid Build Coastguard Worker
126*635a8641SAndroid Build Coastguard Worker namespace {
127*635a8641SAndroid Build Coastguard Worker
128*635a8641SAndroid Build Coastguard Worker // DeleteLogger is an object which sets a flag when it's destroyed.
129*635a8641SAndroid Build Coastguard Worker // It accepts a bool* and sets the bool to true when the dtor runs.
130*635a8641SAndroid Build Coastguard Worker class DeleteLogger {
131*635a8641SAndroid Build Coastguard Worker public:
DeleteLogger()132*635a8641SAndroid Build Coastguard Worker DeleteLogger() : deleted_(nullptr) {}
~DeleteLogger()133*635a8641SAndroid Build Coastguard Worker ~DeleteLogger() { *deleted_ = true; }
134*635a8641SAndroid Build Coastguard Worker
SetDeletedPtr(bool * deleted)135*635a8641SAndroid Build Coastguard Worker void SetDeletedPtr(bool* deleted) {
136*635a8641SAndroid Build Coastguard Worker deleted_ = deleted;
137*635a8641SAndroid Build Coastguard Worker }
138*635a8641SAndroid Build Coastguard Worker
139*635a8641SAndroid Build Coastguard Worker private:
140*635a8641SAndroid Build Coastguard Worker bool* deleted_;
141*635a8641SAndroid Build Coastguard Worker };
142*635a8641SAndroid Build Coastguard Worker
143*635a8641SAndroid Build Coastguard Worker } // anonymous namespace
144*635a8641SAndroid Build Coastguard Worker
TEST(LazyInstanceTest,LeakyLazyInstance)145*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, LeakyLazyInstance) {
146*635a8641SAndroid Build Coastguard Worker // Check that using a plain LazyInstance causes the dtor to run
147*635a8641SAndroid Build Coastguard Worker // when the AtExitManager finishes.
148*635a8641SAndroid Build Coastguard Worker bool deleted1 = false;
149*635a8641SAndroid Build Coastguard Worker {
150*635a8641SAndroid Build Coastguard Worker base::ShadowingAtExitManager shadow;
151*635a8641SAndroid Build Coastguard Worker static base::LazyInstance<DeleteLogger>::DestructorAtExit test =
152*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
153*635a8641SAndroid Build Coastguard Worker test.Get().SetDeletedPtr(&deleted1);
154*635a8641SAndroid Build Coastguard Worker }
155*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(deleted1);
156*635a8641SAndroid Build Coastguard Worker
157*635a8641SAndroid Build Coastguard Worker // Check that using a *leaky* LazyInstance makes the dtor not run
158*635a8641SAndroid Build Coastguard Worker // when the AtExitManager finishes.
159*635a8641SAndroid Build Coastguard Worker bool deleted2 = false;
160*635a8641SAndroid Build Coastguard Worker {
161*635a8641SAndroid Build Coastguard Worker base::ShadowingAtExitManager shadow;
162*635a8641SAndroid Build Coastguard Worker static base::LazyInstance<DeleteLogger>::Leaky
163*635a8641SAndroid Build Coastguard Worker test = LAZY_INSTANCE_INITIALIZER;
164*635a8641SAndroid Build Coastguard Worker test.Get().SetDeletedPtr(&deleted2);
165*635a8641SAndroid Build Coastguard Worker }
166*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(deleted2);
167*635a8641SAndroid Build Coastguard Worker }
168*635a8641SAndroid Build Coastguard Worker
169*635a8641SAndroid Build Coastguard Worker namespace {
170*635a8641SAndroid Build Coastguard Worker
171*635a8641SAndroid Build Coastguard Worker template <size_t alignment>
172*635a8641SAndroid Build Coastguard Worker class AlignedData {
173*635a8641SAndroid Build Coastguard Worker public:
174*635a8641SAndroid Build Coastguard Worker AlignedData() = default;
175*635a8641SAndroid Build Coastguard Worker ~AlignedData() = default;
176*635a8641SAndroid Build Coastguard Worker alignas(alignment) char data_[alignment];
177*635a8641SAndroid Build Coastguard Worker };
178*635a8641SAndroid Build Coastguard Worker
179*635a8641SAndroid Build Coastguard Worker } // namespace
180*635a8641SAndroid Build Coastguard Worker
181*635a8641SAndroid Build Coastguard Worker #define EXPECT_ALIGNED(ptr, align) \
182*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
183*635a8641SAndroid Build Coastguard Worker
TEST(LazyInstanceTest,Alignment)184*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, Alignment) {
185*635a8641SAndroid Build Coastguard Worker using base::LazyInstance;
186*635a8641SAndroid Build Coastguard Worker
187*635a8641SAndroid Build Coastguard Worker // Create some static instances with increasing sizes and alignment
188*635a8641SAndroid Build Coastguard Worker // requirements. By ordering this way, the linker will need to do some work to
189*635a8641SAndroid Build Coastguard Worker // ensure proper alignment of the static data.
190*635a8641SAndroid Build Coastguard Worker static LazyInstance<AlignedData<4>>::DestructorAtExit align4 =
191*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
192*635a8641SAndroid Build Coastguard Worker static LazyInstance<AlignedData<32>>::DestructorAtExit align32 =
193*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
194*635a8641SAndroid Build Coastguard Worker static LazyInstance<AlignedData<4096>>::DestructorAtExit align4096 =
195*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
196*635a8641SAndroid Build Coastguard Worker
197*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align4.Pointer(), 4);
198*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align32.Pointer(), 32);
199*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align4096.Pointer(), 4096);
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker
202*635a8641SAndroid Build Coastguard Worker namespace {
203*635a8641SAndroid Build Coastguard Worker
204*635a8641SAndroid Build Coastguard Worker // A class whose constructor busy-loops until it is told to complete
205*635a8641SAndroid Build Coastguard Worker // construction.
206*635a8641SAndroid Build Coastguard Worker class BlockingConstructor {
207*635a8641SAndroid Build Coastguard Worker public:
BlockingConstructor()208*635a8641SAndroid Build Coastguard Worker BlockingConstructor() {
209*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(WasConstructorCalled());
210*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_Store(&constructor_called_, 1);
211*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(WasConstructorCalled());
212*635a8641SAndroid Build Coastguard Worker while (!base::subtle::NoBarrier_Load(&complete_construction_))
213*635a8641SAndroid Build Coastguard Worker base::PlatformThread::YieldCurrentThread();
214*635a8641SAndroid Build Coastguard Worker done_construction_ = true;
215*635a8641SAndroid Build Coastguard Worker }
216*635a8641SAndroid Build Coastguard Worker
~BlockingConstructor()217*635a8641SAndroid Build Coastguard Worker ~BlockingConstructor() {
218*635a8641SAndroid Build Coastguard Worker // Restore static state for the next test.
219*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_Store(&constructor_called_, 0);
220*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_Store(&complete_construction_, 0);
221*635a8641SAndroid Build Coastguard Worker }
222*635a8641SAndroid Build Coastguard Worker
223*635a8641SAndroid Build Coastguard Worker // Returns true if BlockingConstructor() was entered.
WasConstructorCalled()224*635a8641SAndroid Build Coastguard Worker static bool WasConstructorCalled() {
225*635a8641SAndroid Build Coastguard Worker return base::subtle::NoBarrier_Load(&constructor_called_);
226*635a8641SAndroid Build Coastguard Worker }
227*635a8641SAndroid Build Coastguard Worker
228*635a8641SAndroid Build Coastguard Worker // Instructs BlockingConstructor() that it may now unblock its construction.
CompleteConstructionNow()229*635a8641SAndroid Build Coastguard Worker static void CompleteConstructionNow() {
230*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_Store(&complete_construction_, 1);
231*635a8641SAndroid Build Coastguard Worker }
232*635a8641SAndroid Build Coastguard Worker
done_construction()233*635a8641SAndroid Build Coastguard Worker bool done_construction() { return done_construction_; }
234*635a8641SAndroid Build Coastguard Worker
235*635a8641SAndroid Build Coastguard Worker private:
236*635a8641SAndroid Build Coastguard Worker // Use Atomic32 instead of AtomicFlag for them to be trivially initialized.
237*635a8641SAndroid Build Coastguard Worker static base::subtle::Atomic32 constructor_called_;
238*635a8641SAndroid Build Coastguard Worker static base::subtle::Atomic32 complete_construction_;
239*635a8641SAndroid Build Coastguard Worker
240*635a8641SAndroid Build Coastguard Worker bool done_construction_ = false;
241*635a8641SAndroid Build Coastguard Worker
242*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(BlockingConstructor);
243*635a8641SAndroid Build Coastguard Worker };
244*635a8641SAndroid Build Coastguard Worker
245*635a8641SAndroid Build Coastguard Worker // A SimpleThread running at |thread_priority| which invokes |before_get|
246*635a8641SAndroid Build Coastguard Worker // (optional) and then invokes Get() on the LazyInstance it's assigned.
247*635a8641SAndroid Build Coastguard Worker class BlockingConstructorThread : public base::SimpleThread {
248*635a8641SAndroid Build Coastguard Worker public:
BlockingConstructorThread(base::ThreadPriority thread_priority,base::LazyInstance<BlockingConstructor>::DestructorAtExit * lazy,base::OnceClosure before_get)249*635a8641SAndroid Build Coastguard Worker BlockingConstructorThread(
250*635a8641SAndroid Build Coastguard Worker base::ThreadPriority thread_priority,
251*635a8641SAndroid Build Coastguard Worker base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy,
252*635a8641SAndroid Build Coastguard Worker base::OnceClosure before_get)
253*635a8641SAndroid Build Coastguard Worker : SimpleThread("BlockingConstructorThread", Options(thread_priority)),
254*635a8641SAndroid Build Coastguard Worker lazy_(lazy),
255*635a8641SAndroid Build Coastguard Worker before_get_(std::move(before_get)) {}
256*635a8641SAndroid Build Coastguard Worker
Run()257*635a8641SAndroid Build Coastguard Worker void Run() override {
258*635a8641SAndroid Build Coastguard Worker if (before_get_)
259*635a8641SAndroid Build Coastguard Worker std::move(before_get_).Run();
260*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(lazy_->Get().done_construction());
261*635a8641SAndroid Build Coastguard Worker }
262*635a8641SAndroid Build Coastguard Worker
263*635a8641SAndroid Build Coastguard Worker private:
264*635a8641SAndroid Build Coastguard Worker base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy_;
265*635a8641SAndroid Build Coastguard Worker base::OnceClosure before_get_;
266*635a8641SAndroid Build Coastguard Worker
267*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(BlockingConstructorThread);
268*635a8641SAndroid Build Coastguard Worker };
269*635a8641SAndroid Build Coastguard Worker
270*635a8641SAndroid Build Coastguard Worker // static
271*635a8641SAndroid Build Coastguard Worker base::subtle::Atomic32 BlockingConstructor::constructor_called_ = 0;
272*635a8641SAndroid Build Coastguard Worker // static
273*635a8641SAndroid Build Coastguard Worker base::subtle::Atomic32 BlockingConstructor::complete_construction_ = 0;
274*635a8641SAndroid Build Coastguard Worker
275*635a8641SAndroid Build Coastguard Worker base::LazyInstance<BlockingConstructor>::DestructorAtExit lazy_blocking =
276*635a8641SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
277*635a8641SAndroid Build Coastguard Worker
278*635a8641SAndroid Build Coastguard Worker } // namespace
279*635a8641SAndroid Build Coastguard Worker
280*635a8641SAndroid Build Coastguard Worker // Tests that if the thread assigned to construct the LazyInstance runs at
281*635a8641SAndroid Build Coastguard Worker // background priority : the foreground threads will yield to it enough for it
282*635a8641SAndroid Build Coastguard Worker // to eventually complete construction.
283*635a8641SAndroid Build Coastguard Worker // This is a regression test for https://crbug.com/797129.
TEST(LazyInstanceTest,PriorityInversionAtInitializationResolves)284*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, PriorityInversionAtInitializationResolves) {
285*635a8641SAndroid Build Coastguard Worker base::TimeTicks test_begin = base::TimeTicks::Now();
286*635a8641SAndroid Build Coastguard Worker
287*635a8641SAndroid Build Coastguard Worker // Construct BlockingConstructor from a background thread.
288*635a8641SAndroid Build Coastguard Worker BlockingConstructorThread background_getter(
289*635a8641SAndroid Build Coastguard Worker base::ThreadPriority::BACKGROUND, &lazy_blocking, base::OnceClosure());
290*635a8641SAndroid Build Coastguard Worker background_getter.Start();
291*635a8641SAndroid Build Coastguard Worker
292*635a8641SAndroid Build Coastguard Worker while (!BlockingConstructor::WasConstructorCalled())
293*635a8641SAndroid Build Coastguard Worker base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
294*635a8641SAndroid Build Coastguard Worker
295*635a8641SAndroid Build Coastguard Worker // Spin 4 foreground thread per core contending to get the already under
296*635a8641SAndroid Build Coastguard Worker // construction LazyInstance. When they are all running and poking at it :
297*635a8641SAndroid Build Coastguard Worker // allow the background thread to complete its work.
298*635a8641SAndroid Build Coastguard Worker const int kNumForegroundThreads = 4 * base::SysInfo::NumberOfProcessors();
299*635a8641SAndroid Build Coastguard Worker std::vector<std::unique_ptr<base::SimpleThread>> foreground_threads;
300*635a8641SAndroid Build Coastguard Worker base::RepeatingClosure foreground_thread_ready_callback =
301*635a8641SAndroid Build Coastguard Worker base::BarrierClosure(
302*635a8641SAndroid Build Coastguard Worker kNumForegroundThreads,
303*635a8641SAndroid Build Coastguard Worker base::BindOnce(&BlockingConstructor::CompleteConstructionNow));
304*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < kNumForegroundThreads; ++i) {
305*635a8641SAndroid Build Coastguard Worker foreground_threads.push_back(std::make_unique<BlockingConstructorThread>(
306*635a8641SAndroid Build Coastguard Worker base::ThreadPriority::NORMAL, &lazy_blocking,
307*635a8641SAndroid Build Coastguard Worker foreground_thread_ready_callback));
308*635a8641SAndroid Build Coastguard Worker foreground_threads.back()->Start();
309*635a8641SAndroid Build Coastguard Worker }
310*635a8641SAndroid Build Coastguard Worker
311*635a8641SAndroid Build Coastguard Worker // This test will hang if the foreground threads become stuck in
312*635a8641SAndroid Build Coastguard Worker // LazyInstance::Get() per the background thread never being scheduled to
313*635a8641SAndroid Build Coastguard Worker // complete construction.
314*635a8641SAndroid Build Coastguard Worker for (auto& foreground_thread : foreground_threads)
315*635a8641SAndroid Build Coastguard Worker foreground_thread->Join();
316*635a8641SAndroid Build Coastguard Worker background_getter.Join();
317*635a8641SAndroid Build Coastguard Worker
318*635a8641SAndroid Build Coastguard Worker // Fail if this test takes more than 5 seconds (it takes 5-10 seconds on a
319*635a8641SAndroid Build Coastguard Worker // Z840 without r527445 but is expected to be fast (~30ms) with the fix).
320*635a8641SAndroid Build Coastguard Worker EXPECT_LT(base::TimeTicks::Now() - test_begin,
321*635a8641SAndroid Build Coastguard Worker base::TimeDelta::FromSeconds(5));
322*635a8641SAndroid Build Coastguard Worker }
323