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