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: 30 TrivialThread() : run_event_(WaitableEvent::ResetPolicy::MANUAL, 31 WaitableEvent::InitialState::NOT_SIGNALED) {} 32 33 void ThreadMain() override { run_event_.Signal(); } 34 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 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 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. 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 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: 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) {} 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. 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 135 PlatformThreadId thread_id() const { 136 EXPECT_TRUE(termination_ready_.IsSignaled()) << "Thread ID still unknown"; 137 return thread_id_; 138 } 139 140 bool IsRunning() const { 141 return termination_ready_.IsSignaled() && !done_; 142 } 143 144 // Blocks until this thread is started and ready to be terminated. 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). 149 void MarkForTermination() { terminate_thread_.Signal(); } 150 151 private: 152 // Runs an optional test on the newly created thread. 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 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 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 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: 251 explicit ThreadPriorityTestThread(ThreadPriority priority) 252 : priority_(priority) {} 253 ~ThreadPriorityTestThread() override = default; 254 255 private: 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). 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) 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