1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 <stddef.h>
6 
7 #include "base/compiler_specific.h"
8 #include "base/macros.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/threading/platform_thread.h"
11 #include "build/build_config.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 #if defined(OS_POSIX)
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include "base/threading/platform_thread_internal_posix.h"
18 #elif defined(OS_WIN)
19 #include <windows.h>
20 #endif
21 
22 namespace base {
23 
24 // Trivial tests that thread runs and doesn't crash on create, join, or detach -
25 
26 namespace {
27 
28 class TrivialThread : public PlatformThread::Delegate {
29  public:
TrivialThread()30   TrivialThread() : run_event_(WaitableEvent::ResetPolicy::MANUAL,
31                                WaitableEvent::InitialState::NOT_SIGNALED) {}
32 
ThreadMain()33   void ThreadMain() override { run_event_.Signal(); }
34 
run_event()35   WaitableEvent& run_event() { return run_event_; }
36 
37  private:
38   WaitableEvent run_event_;
39 
40   DISALLOW_COPY_AND_ASSIGN(TrivialThread);
41 };
42 
43 }  // namespace
44 
TEST(PlatformThreadTest,TrivialJoin)45 TEST(PlatformThreadTest, TrivialJoin) {
46   TrivialThread thread;
47   PlatformThreadHandle handle;
48 
49   ASSERT_FALSE(thread.run_event().IsSignaled());
50   ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
51   PlatformThread::Join(handle);
52   ASSERT_TRUE(thread.run_event().IsSignaled());
53 }
54 
TEST(PlatformThreadTest,TrivialJoinTimesTen)55 TEST(PlatformThreadTest, TrivialJoinTimesTen) {
56   TrivialThread thread[10];
57   PlatformThreadHandle handle[arraysize(thread)];
58 
59   for (size_t n = 0; n < arraysize(thread); n++)
60     ASSERT_FALSE(thread[n].run_event().IsSignaled());
61   for (size_t n = 0; n < arraysize(thread); n++)
62     ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
63   for (size_t n = 0; n < arraysize(thread); n++)
64     PlatformThread::Join(handle[n]);
65   for (size_t n = 0; n < arraysize(thread); n++)
66     ASSERT_TRUE(thread[n].run_event().IsSignaled());
67 }
68 
69 // The following detach tests are by nature racy. The run_event approximates the
70 // end and termination of the thread, but threads could persist shortly after
71 // the test completes.
TEST(PlatformThreadTest,TrivialDetach)72 TEST(PlatformThreadTest, TrivialDetach) {
73   TrivialThread thread;
74   PlatformThreadHandle handle;
75 
76   ASSERT_FALSE(thread.run_event().IsSignaled());
77   ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
78   PlatformThread::Detach(handle);
79   thread.run_event().Wait();
80 }
81 
TEST(PlatformThreadTest,TrivialDetachTimesTen)82 TEST(PlatformThreadTest, TrivialDetachTimesTen) {
83   TrivialThread thread[10];
84   PlatformThreadHandle handle[arraysize(thread)];
85 
86   for (size_t n = 0; n < arraysize(thread); n++)
87     ASSERT_FALSE(thread[n].run_event().IsSignaled());
88   for (size_t n = 0; n < arraysize(thread); n++) {
89     ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
90     PlatformThread::Detach(handle[n]);
91   }
92   for (size_t n = 0; n < arraysize(thread); n++)
93     thread[n].run_event().Wait();
94 }
95 
96 // Tests of basic thread functions ---------------------------------------------
97 
98 namespace {
99 
100 class FunctionTestThread : public PlatformThread::Delegate {
101  public:
FunctionTestThread()102   FunctionTestThread()
103       : thread_id_(kInvalidThreadId),
104         termination_ready_(WaitableEvent::ResetPolicy::MANUAL,
105                            WaitableEvent::InitialState::NOT_SIGNALED),
106         terminate_thread_(WaitableEvent::ResetPolicy::MANUAL,
107                           WaitableEvent::InitialState::NOT_SIGNALED),
108         done_(false) {}
~FunctionTestThread()109   ~FunctionTestThread() override {
110     EXPECT_TRUE(terminate_thread_.IsSignaled())
111         << "Need to mark thread for termination and join the underlying thread "
112         << "before destroying a FunctionTestThread as it owns the "
113         << "WaitableEvent blocking the underlying thread's main.";
114   }
115 
116   // Grabs |thread_id_|, runs an optional test on that thread, signals
117   // |termination_ready_|, and then waits for |terminate_thread_| to be
118   // signaled before exiting.
ThreadMain()119   void ThreadMain() override {
120     thread_id_ = PlatformThread::CurrentId();
121     EXPECT_NE(thread_id_, kInvalidThreadId);
122 
123     // Make sure that the thread ID is the same across calls.
124     EXPECT_EQ(thread_id_, PlatformThread::CurrentId());
125 
126     // Run extra tests.
127     RunTest();
128 
129     termination_ready_.Signal();
130     terminate_thread_.Wait();
131 
132     done_ = true;
133   }
134 
thread_id() const135   PlatformThreadId thread_id() const {
136     EXPECT_TRUE(termination_ready_.IsSignaled()) << "Thread ID still unknown";
137     return thread_id_;
138   }
139 
IsRunning() const140   bool IsRunning() const {
141     return termination_ready_.IsSignaled() && !done_;
142   }
143 
144   // Blocks until this thread is started and ready to be terminated.
WaitForTerminationReady()145   void WaitForTerminationReady() { termination_ready_.Wait(); }
146 
147   // Marks this thread for termination (callers must then join this thread to be
148   // guaranteed of termination).
MarkForTermination()149   void MarkForTermination() { terminate_thread_.Signal(); }
150 
151  private:
152   // Runs an optional test on the newly created thread.
RunTest()153   virtual void RunTest() {}
154 
155   PlatformThreadId thread_id_;
156 
157   mutable WaitableEvent termination_ready_;
158   WaitableEvent terminate_thread_;
159   bool done_;
160 
161   DISALLOW_COPY_AND_ASSIGN(FunctionTestThread);
162 };
163 
164 }  // namespace
165 
TEST(PlatformThreadTest,Function)166 TEST(PlatformThreadTest, Function) {
167   PlatformThreadId main_thread_id = PlatformThread::CurrentId();
168 
169   FunctionTestThread thread;
170   PlatformThreadHandle handle;
171 
172   ASSERT_FALSE(thread.IsRunning());
173   ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
174   thread.WaitForTerminationReady();
175   ASSERT_TRUE(thread.IsRunning());
176   EXPECT_NE(thread.thread_id(), main_thread_id);
177 
178   thread.MarkForTermination();
179   PlatformThread::Join(handle);
180   ASSERT_FALSE(thread.IsRunning());
181 
182   // Make sure that the thread ID is the same across calls.
183   EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
184 }
185 
TEST(PlatformThreadTest,FunctionTimesTen)186 TEST(PlatformThreadTest, FunctionTimesTen) {
187   PlatformThreadId main_thread_id = PlatformThread::CurrentId();
188 
189   FunctionTestThread thread[10];
190   PlatformThreadHandle handle[arraysize(thread)];
191 
192   for (size_t n = 0; n < arraysize(thread); n++)
193     ASSERT_FALSE(thread[n].IsRunning());
194 
195   for (size_t n = 0; n < arraysize(thread); n++)
196     ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
197   for (size_t n = 0; n < arraysize(thread); n++)
198     thread[n].WaitForTerminationReady();
199 
200   for (size_t n = 0; n < arraysize(thread); n++) {
201     ASSERT_TRUE(thread[n].IsRunning());
202     EXPECT_NE(thread[n].thread_id(), main_thread_id);
203 
204     // Make sure no two threads get the same ID.
205     for (size_t i = 0; i < n; ++i) {
206       EXPECT_NE(thread[i].thread_id(), thread[n].thread_id());
207     }
208   }
209 
210   for (size_t n = 0; n < arraysize(thread); n++)
211     thread[n].MarkForTermination();
212   for (size_t n = 0; n < arraysize(thread); n++)
213     PlatformThread::Join(handle[n]);
214   for (size_t n = 0; n < arraysize(thread); n++)
215     ASSERT_FALSE(thread[n].IsRunning());
216 
217   // Make sure that the thread ID is the same across calls.
218   EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
219 }
220 
221 namespace {
222 
223 const ThreadPriority kThreadPriorityTestValues[] = {
224 // The order should be higher to lower to cover as much cases as possible on
225 // Linux trybots running without CAP_SYS_NICE permission.
226 #if !defined(OS_ANDROID)
227     // PlatformThread::GetCurrentThreadPriority() on Android does not support
228     // REALTIME_AUDIO case. See http://crbug.com/505474.
229     ThreadPriority::REALTIME_AUDIO,
230 #endif
231     ThreadPriority::DISPLAY,
232     // This redundant BACKGROUND priority is to test backgrounding from other
233     // priorities, and unbackgrounding.
234     ThreadPriority::BACKGROUND,
235     ThreadPriority::NORMAL,
236     ThreadPriority::BACKGROUND};
237 
IsBumpingPriorityAllowed()238 bool IsBumpingPriorityAllowed() {
239 #if defined(OS_POSIX)
240   // Only root can raise thread priority on POSIX environment. On Linux, users
241   // who have CAP_SYS_NICE permission also can raise the thread priority, but
242   // libcap.so would be needed to check the capability.
243   return geteuid() == 0;
244 #else
245   return true;
246 #endif
247 }
248 
249 class ThreadPriorityTestThread : public FunctionTestThread {
250  public:
ThreadPriorityTestThread(ThreadPriority priority)251   explicit ThreadPriorityTestThread(ThreadPriority priority)
252       : priority_(priority) {}
253   ~ThreadPriorityTestThread() override = default;
254 
255  private:
RunTest()256   void RunTest() override {
257     // Confirm that the current thread's priority is as expected.
258     EXPECT_EQ(ThreadPriority::NORMAL,
259               PlatformThread::GetCurrentThreadPriority());
260 
261     // Alter and verify the current thread's priority.
262     PlatformThread::SetCurrentThreadPriority(priority_);
263     EXPECT_EQ(priority_, PlatformThread::GetCurrentThreadPriority());
264   }
265 
266   const ThreadPriority priority_;
267 
268   DISALLOW_COPY_AND_ASSIGN(ThreadPriorityTestThread);
269 };
270 
271 }  // namespace
272 
273 // Test changing a created thread's priority (which has different semantics on
274 // some platforms).
TEST(PlatformThreadTest,ThreadPriorityCurrentThread)275 TEST(PlatformThreadTest, ThreadPriorityCurrentThread) {
276   const bool bumping_priority_allowed = IsBumpingPriorityAllowed();
277   if (bumping_priority_allowed) {
278     // Bump the priority in order to verify that new threads are started with
279     // normal priority.
280     PlatformThread::SetCurrentThreadPriority(ThreadPriority::DISPLAY);
281   }
282 
283   // Toggle each supported priority on the thread and confirm it affects it.
284   for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
285     if (!bumping_priority_allowed &&
286         kThreadPriorityTestValues[i] >
287             PlatformThread::GetCurrentThreadPriority()) {
288       continue;
289     }
290 
291     ThreadPriorityTestThread thread(kThreadPriorityTestValues[i]);
292     PlatformThreadHandle handle;
293 
294     ASSERT_FALSE(thread.IsRunning());
295     ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
296     thread.WaitForTerminationReady();
297     ASSERT_TRUE(thread.IsRunning());
298 
299     thread.MarkForTermination();
300     PlatformThread::Join(handle);
301     ASSERT_FALSE(thread.IsRunning());
302   }
303 }
304 
305 // Test for a function defined in platform_thread_internal_posix.cc. On OSX and
306 // iOS, platform_thread_internal_posix.cc is not compiled, so these platforms
307 // are excluded here, too.
308 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
TEST(PlatformThreadTest,GetNiceValueToThreadPriority)309 TEST(PlatformThreadTest, GetNiceValueToThreadPriority) {
310   using internal::NiceValueToThreadPriority;
311   using internal::kThreadPriorityToNiceValueMap;
312 
313   EXPECT_EQ(ThreadPriority::BACKGROUND,
314             kThreadPriorityToNiceValueMap[0].priority);
315   EXPECT_EQ(ThreadPriority::NORMAL,
316             kThreadPriorityToNiceValueMap[1].priority);
317   EXPECT_EQ(ThreadPriority::DISPLAY,
318             kThreadPriorityToNiceValueMap[2].priority);
319   EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
320             kThreadPriorityToNiceValueMap[3].priority);
321 
322   static const int kBackgroundNiceValue =
323       kThreadPriorityToNiceValueMap[0].nice_value;
324   static const int kNormalNiceValue =
325       kThreadPriorityToNiceValueMap[1].nice_value;
326   static const int kDisplayNiceValue =
327       kThreadPriorityToNiceValueMap[2].nice_value;
328   static const int kRealtimeAudioNiceValue =
329       kThreadPriorityToNiceValueMap[3].nice_value;
330 
331   // The tests below assume the nice values specified in the map are within
332   // the range below (both ends exclusive).
333   static const int kHighestNiceValue = 19;
334   static const int kLowestNiceValue = -20;
335 
336   EXPECT_GT(kHighestNiceValue, kBackgroundNiceValue);
337   EXPECT_GT(kBackgroundNiceValue, kNormalNiceValue);
338   EXPECT_GT(kNormalNiceValue, kDisplayNiceValue);
339   EXPECT_GT(kDisplayNiceValue, kRealtimeAudioNiceValue);
340   EXPECT_GT(kRealtimeAudioNiceValue, kLowestNiceValue);
341 
342   EXPECT_EQ(ThreadPriority::BACKGROUND,
343             NiceValueToThreadPriority(kHighestNiceValue));
344   EXPECT_EQ(ThreadPriority::BACKGROUND,
345             NiceValueToThreadPriority(kBackgroundNiceValue + 1));
346   EXPECT_EQ(ThreadPriority::BACKGROUND,
347             NiceValueToThreadPriority(kBackgroundNiceValue));
348   EXPECT_EQ(ThreadPriority::BACKGROUND,
349             NiceValueToThreadPriority(kNormalNiceValue + 1));
350   EXPECT_EQ(ThreadPriority::NORMAL,
351             NiceValueToThreadPriority(kNormalNiceValue));
352   EXPECT_EQ(ThreadPriority::NORMAL,
353             NiceValueToThreadPriority(kDisplayNiceValue + 1));
354   EXPECT_EQ(ThreadPriority::DISPLAY,
355             NiceValueToThreadPriority(kDisplayNiceValue));
356   EXPECT_EQ(ThreadPriority::DISPLAY,
357             NiceValueToThreadPriority(kRealtimeAudioNiceValue + 1));
358   EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
359             NiceValueToThreadPriority(kRealtimeAudioNiceValue));
360   EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
361             NiceValueToThreadPriority(kLowestNiceValue));
362 }
363 #endif
364 
365 }  // namespace base
366