diff options
author | gab <gab@chromium.org> | 2015-04-01 10:10:06 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-01 17:10:45 +0000 |
commit | f1921cb37b83bce16c07ca93975cded2b2863dd0 (patch) | |
tree | d5e331b67961b40f2c2504422d473d3bd13aba64 /base/threading | |
parent | 5656ae68841a3e3ddaac75cf2983d9052d71d0d5 (diff) | |
download | chromium_src-f1921cb37b83bce16c07ca93975cded2b2863dd0.zip chromium_src-f1921cb37b83bce16c07ca93975cded2b2863dd0.tar.gz chromium_src-f1921cb37b83bce16c07ca93975cded2b2863dd0.tar.bz2 |
Add full SetThreadPriority support to Windows.
Also introducing the cross-platform GetThreadPriority() method to allow for
cross-platform tests for this code.
Enhanced PlatformThreadTests.
Discovering issue 468793 in the process where it appears that the POSIX priority
manipulation code doesn't actually work in practice...
BUG=456903, 468793, 338961, 468932
Review URL: https://codereview.chromium.org/1006933003
Cr-Commit-Position: refs/heads/master@{#323266}
Diffstat (limited to 'base/threading')
-rw-r--r-- | base/threading/platform_thread.h | 13 | ||||
-rw-r--r-- | base/threading/platform_thread_android.cc | 10 | ||||
-rw-r--r-- | base/threading/platform_thread_freebsd.cc | 24 | ||||
-rw-r--r-- | base/threading/platform_thread_internal_posix.cc | 10 | ||||
-rw-r--r-- | base/threading/platform_thread_internal_posix.h | 14 | ||||
-rw-r--r-- | base/threading/platform_thread_linux.cc | 24 | ||||
-rw-r--r-- | base/threading/platform_thread_mac.mm | 6 | ||||
-rw-r--r-- | base/threading/platform_thread_posix.cc | 39 | ||||
-rw-r--r-- | base/threading/platform_thread_unittest.cc | 180 | ||||
-rw-r--r-- | base/threading/platform_thread_win.cc | 50 |
10 files changed, 335 insertions, 35 deletions
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h index 2874314..f90a9a2 100644 --- a/base/threading/platform_thread.h +++ b/base/threading/platform_thread.h @@ -111,7 +111,7 @@ class PlatformThreadHandle { const PlatformThreadId kInvalidThreadId(0); // Valid values for SetThreadPriority() -enum ThreadPriority{ +enum ThreadPriority { kThreadPriority_Normal, // Suitable for low-latency, glitch-resistant audio. kThreadPriority_RealtimeAudio, @@ -141,7 +141,10 @@ class BASE_EXPORT PlatformThread { // we're on the right thread quickly. static PlatformThreadRef CurrentRef(); - // Get the current handle. + // Get the handle representing the current thread. On Windows, this is a + // pseudo handle constant which will always represent the thread using it and + // hence should not be shared with other threads nor be used to differentiate + // the current thread from another. static PlatformThreadHandle CurrentHandle(); // Yield the current thread so another thread can be scheduled. @@ -171,9 +174,7 @@ class BASE_EXPORT PlatformThread { // CreateWithPriority() does the same thing as Create() except the priority of // the thread is set based on |priority|. Can be used in place of Create() - // followed by SetThreadPriority(). SetThreadPriority() has not been - // implemented on the Linux platform yet, this is the only way to get a high - // priority thread on Linux. + // followed by SetThreadPriority(). static bool CreateWithPriority(size_t stack_size, Delegate* delegate, PlatformThreadHandle* thread_handle, ThreadPriority priority); @@ -191,6 +192,8 @@ class BASE_EXPORT PlatformThread { static void SetThreadPriority(PlatformThreadHandle handle, ThreadPriority priority); + static ThreadPriority GetThreadPriority(PlatformThreadHandle handle); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); }; diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc index aab4c19..be4ccbe 100644 --- a/base/threading/platform_thread_android.cc +++ b/base/threading/platform_thread_android.cc @@ -44,8 +44,8 @@ const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { {kThreadPriority_Display, -6}, }; -bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority) { +bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority priority) { // On Android, we set the Audio priority through JNI as Audio priority // will also allow the process to run while it is backgrounded. if (priority == kThreadPriority_RealtimeAudio) { @@ -56,6 +56,12 @@ bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, return false; } +bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority* priority) { + NOTIMPLEMENTED(); + return false; +} + } // namespace internal void PlatformThread::SetName(const char* name) { diff --git a/base/threading/platform_thread_freebsd.cc b/base/threading/platform_thread_freebsd.cc index a163f65..dc5d34b 100644 --- a/base/threading/platform_thread_freebsd.cc +++ b/base/threading/platform_thread_freebsd.cc @@ -36,9 +36,11 @@ const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { { kThreadPriority_Display, -6 }, } -bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority) { +bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority priority) { #if !defined(OS_NACL) + // TODO(gab): Assess the correctness of using |pthread_self()| below instead + // of |handle|. http://crbug.com/468793. return priority == kThreadPriority_RealtimeAudio && pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; #else @@ -46,6 +48,24 @@ bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, #endif } +bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority* priority) { +#if !defined(OS_NACL) + // TODO(gab): Assess the correctness of using |pthread_self()| below instead + // of |handle|. http://crbug.com/468793. + int maybe_sched_rr = 0; + struct sched_param maybe_realtime_prio = {0}; + if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, + &maybe_realtime_prio) == 0 && + maybe_sched_rr == SCHED_RR && + maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { + *priority = kThreadPriority_RealtimeAudio; + return true; + } +#endif + return false; +} + } // namespace internal // static diff --git a/base/threading/platform_thread_internal_posix.cc b/base/threading/platform_thread_internal_posix.cc index 7e6604b..841a44a 100644 --- a/base/threading/platform_thread_internal_posix.cc +++ b/base/threading/platform_thread_internal_posix.cc @@ -20,6 +20,16 @@ int ThreadPriorityToNiceValue(ThreadPriority priority) { return 0; } +ThreadPriority NiceValueToThreadPriority(int nice_value) { + for (const ThreadPriorityToNiceValuePair& pair : + kThreadPriorityToNiceValueMap) { + if (pair.nice_value == nice_value) + return pair.priority; + } + NOTREACHED() << "Unknown nice value"; + return kThreadPriority_Normal; +} + } // namespace internal } // namespace base diff --git a/base/threading/platform_thread_internal_posix.h b/base/threading/platform_thread_internal_posix.h index 1ae968f..62006ce 100644 --- a/base/threading/platform_thread_internal_posix.h +++ b/base/threading/platform_thread_internal_posix.h @@ -21,12 +21,22 @@ extern const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4]; // implementation of kThreadPriorityToNiceValueMap. int ThreadPriorityToNiceValue(ThreadPriority priority); +// Returns the ThreadPrioirty matching |nice_value| based on the platform- +// specific implementation of kThreadPriorityToNiceValueMap. +ThreadPriority NiceValueToThreadPriority(int nice_value); + // Allows platform specific tweaks to the generic POSIX solution for // SetThreadPriority. Returns true if the platform-specific implementation // handled this |priority| change, false if the generic implementation should // instead proceed. -bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority); +bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority priority); + +// Returns true if there is a platform-specific ThreadPriority set on |handle| +// (and returns the actual ThreadPriority via |priority|). Returns false +// otherwise, leaving |priority| untouched. +bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority* priority); } // namespace internal diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc index 623a3de..67dbca6 100644 --- a/base/threading/platform_thread_linux.cc +++ b/base/threading/platform_thread_linux.cc @@ -37,9 +37,11 @@ const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { {kThreadPriority_Display, -6}, }; -bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, - ThreadPriority priority) { +bool SetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority priority) { #if !defined(OS_NACL) + // TODO(gab): Assess the correctness of using |pthread_self()| below instead + // of |handle|. http://crbug.com/468793. return priority == kThreadPriority_RealtimeAudio && pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; #else @@ -47,6 +49,24 @@ bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle, #endif } +bool GetThreadPriorityForPlatform(PlatformThreadHandle handle, + ThreadPriority* priority) { +#if !defined(OS_NACL) + int maybe_sched_rr = 0; + struct sched_param maybe_realtime_prio = {0}; + // TODO(gab): Assess the correctness of using |pthread_self()| below instead + // of |handle|. http://crbug.com/468793. + if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, + &maybe_realtime_prio) == 0 && + maybe_sched_rr == SCHED_RR && + maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { + *priority = kThreadPriority_RealtimeAudio; + return true; + } +#endif + return false; +} + } // namespace internal // static diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm index 147e625..59345b0 100644 --- a/base/threading/platform_thread_mac.mm +++ b/base/threading/platform_thread_mac.mm @@ -173,6 +173,12 @@ void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, } } +// static +ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) { + NOTIMPLEMENTED(); + return kThreadPriority_Normal; +} + size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { #if defined(OS_IOS) return 0; diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc index 5c5023b..600c5ce9 100644 --- a/base/threading/platform_thread_posix.cc +++ b/base/threading/platform_thread_posix.cc @@ -232,13 +232,16 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { CHECK_EQ(0, pthread_join(thread_handle.handle_, NULL)); } -// Mac has its own SetThreadPriority() implementation. +// Mac has its own Set/GetThreadPriority() implementations. #if !defined(OS_MACOSX) + // static void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, ThreadPriority priority) { -#if !defined(OS_NACL) - if (internal::HandleSetThreadPriorityForPlatform(handle, priority)) +#if defined(OS_NACL) + NOTIMPLEMENTED(); +#else + if (internal::SetThreadPriorityForPlatform(handle, priority)) return; // setpriority(2) should change the whole thread group's (i.e. process) @@ -255,8 +258,38 @@ void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, DVPLOG(1) << "Failed to set nice value of thread (" << handle.id_ << ") to " << nice_setting; } +#endif // defined(OS_NACL) +} + +// static +ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) { +#if defined(OS_NACL) + NOTIMPLEMENTED(); + return kThreadPriority_Normal; +#else + // Mirrors SetThreadPriority()'s implementation. + ThreadPriority platform_specific_priority; + if (internal::GetThreadPriorityForPlatform(handle, + &platform_specific_priority)) { + return platform_specific_priority; + } + + DCHECK_NE(handle.id_, kInvalidThreadId); + const PlatformThreadId current_id = PlatformThread::CurrentId(); + // Need to clear errno before calling getpriority(): + // http://man7.org/linux/man-pages/man2/getpriority.2.html + errno = 0; + int nice_value = + getpriority(PRIO_PROCESS, handle.id_ == current_id ? 0 : handle.id_); + if (errno != 0) { + DVPLOG(1) << "Failed to get nice value of thread (" << handle.id_ << ")"; + return kThreadPriority_Normal; + } + + return internal::NiceValueToThreadPriority(nice_value); #endif // !defined(OS_NACL) } + #endif // !defined(OS_MACOSX) } // namespace base diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc index 21260e5..6e5605e 100644 --- a/base/threading/platform_thread_unittest.cc +++ b/base/threading/platform_thread_unittest.cc @@ -3,10 +3,15 @@ // found in the LICENSE file. #include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" - #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_WIN) +#include <windows.h> +#endif + namespace base { // Trivial tests that thread runs and doesn't crash on create and join --------- @@ -51,26 +56,59 @@ TEST(PlatformThreadTest, TrivialTimesTen) { // Tests of basic thread functions --------------------------------------------- -class FunctionTestThread : public TrivialThread { +class FunctionTestThread : public PlatformThread::Delegate { public: - FunctionTestThread() : thread_id_(0) {} + FunctionTestThread() + : thread_id_(kInvalidThreadId), + thread_started_(true, false), + terminate_thread_(true, false), + done_(false) {} + ~FunctionTestThread() override { + EXPECT_TRUE(terminate_thread_.IsSignaled()) + << "Need to mark thread for termination and join the underlying thread " + << "before destroying a FunctionTestThread as it owns the " + << "WaitableEvent blocking the underlying thread's main."; + } + // Grabs |thread_id_|, signals |thread_started_|, and then waits for + // |terminate_thread_| to be signaled before exiting. void ThreadMain() override { thread_id_ = PlatformThread::CurrentId(); - PlatformThread::YieldCurrentThread(); - PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); + EXPECT_NE(thread_id_, kInvalidThreadId); // Make sure that the thread ID is the same across calls. EXPECT_EQ(thread_id_, PlatformThread::CurrentId()); - TrivialThread::ThreadMain(); + thread_started_.Signal(); + + terminate_thread_.Wait(); + + done_ = true; + } + + PlatformThreadId thread_id() const { + EXPECT_TRUE(thread_started_.IsSignaled()) << "Thread ID still unknown"; + return thread_id_; } - PlatformThreadId thread_id() const { return thread_id_; } + bool IsRunning() const { + return thread_started_.IsSignaled() && !done_; + } + + // Blocks until this thread is started. + void WaitForThreadStart() { thread_started_.Wait(); } + + // Mark this thread for termination (callers must then join this thread to be + // guaranteed of termination). + void MarkForTermination() { terminate_thread_.Signal(); } private: PlatformThreadId thread_id_; + mutable WaitableEvent thread_started_; + WaitableEvent terminate_thread_; + bool done_; + DISALLOW_COPY_AND_ASSIGN(FunctionTestThread); }; @@ -80,12 +118,16 @@ TEST(PlatformThreadTest, Function) { FunctionTestThread thread; PlatformThreadHandle handle; - ASSERT_FALSE(thread.did_run()); + ASSERT_FALSE(thread.IsRunning()); ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); - PlatformThread::Join(handle); - ASSERT_TRUE(thread.did_run()); + thread.WaitForThreadStart(); + ASSERT_TRUE(thread.IsRunning()); EXPECT_NE(thread.thread_id(), main_thread_id); + thread.MarkForTermination(); + PlatformThread::Join(handle); + ASSERT_FALSE(thread.IsRunning()); + // Make sure that the thread ID is the same across calls. EXPECT_EQ(main_thread_id, PlatformThread::CurrentId()); } @@ -97,13 +139,15 @@ TEST(PlatformThreadTest, FunctionTimesTen) { PlatformThreadHandle handle[arraysize(thread)]; for (size_t n = 0; n < arraysize(thread); n++) - ASSERT_FALSE(thread[n].did_run()); + ASSERT_FALSE(thread[n].IsRunning()); + for (size_t n = 0; n < arraysize(thread); n++) ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n])); for (size_t n = 0; n < arraysize(thread); n++) - PlatformThread::Join(handle[n]); + thread[n].WaitForThreadStart(); + for (size_t n = 0; n < arraysize(thread); n++) { - ASSERT_TRUE(thread[n].did_run()); + ASSERT_TRUE(thread[n].IsRunning()); EXPECT_NE(thread[n].thread_id(), main_thread_id); // Make sure no two threads get the same ID. @@ -112,8 +156,118 @@ TEST(PlatformThreadTest, FunctionTimesTen) { } } + for (size_t n = 0; n < arraysize(thread); n++) + thread[n].MarkForTermination(); + for (size_t n = 0; n < arraysize(thread); n++) + PlatformThread::Join(handle[n]); + for (size_t n = 0; n < arraysize(thread); n++) + ASSERT_FALSE(thread[n].IsRunning()); + // Make sure that the thread ID is the same across calls. EXPECT_EQ(main_thread_id, PlatformThread::CurrentId()); } +namespace { + +const ThreadPriority kThreadPriorityTestValues[] = { +// Disable non-normal priority toggling on POSIX as it appears to be broken +// (http://crbug.com/468793). This is prefered to disabling the tests altogether +// on POSIX as it at least provides coverage for running this code under +// "normal" priority. +#if !defined(OS_POSIX) + kThreadPriority_RealtimeAudio, + kThreadPriority_Display, + kThreadPriority_Background, +#endif // !defined(OS_POSIX) + // Keep normal last to test unbackgrounding. + kThreadPriority_Normal +}; + +} // namespace + +// Test changing another thread's priority. +// NOTE: This test is partially disabled on POSIX, see note above and +// http://crbug.com/468793. +TEST(PlatformThreadTest, ThreadPriorityOtherThread) { + PlatformThreadHandle current_handle(PlatformThread::CurrentHandle()); + + // Confirm that the current thread's priority is as expected. + EXPECT_EQ(kThreadPriority_Normal, + PlatformThread::GetThreadPriority(current_handle)); + + // Create a test thread. + FunctionTestThread thread; + PlatformThreadHandle handle; + ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); + thread.WaitForThreadStart(); + EXPECT_NE(thread.thread_id(), kInvalidThreadId); + EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId()); + + // New threads should get normal priority by default. + EXPECT_EQ(kThreadPriority_Normal, PlatformThread::GetThreadPriority(handle)); + + // Toggle each supported priority on the test thread and confirm it only + // affects it (and not the current thread). + for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { + SCOPED_TRACE(i); + + // Alter and verify the test thread's priority. + PlatformThread::SetThreadPriority(handle, kThreadPriorityTestValues[i]); + EXPECT_EQ(kThreadPriorityTestValues[i], + PlatformThread::GetThreadPriority(handle)); + + // Make sure the current thread was otherwise unaffected. + EXPECT_EQ(kThreadPriority_Normal, + PlatformThread::GetThreadPriority(current_handle)); + } + + thread.MarkForTermination(); + PlatformThread::Join(handle); +} + +// Test changing the current thread's priority (which has different semantics on +// some platforms). +// NOTE: This test is partially disabled on POSIX, see note above and +// http://crbug.com/468793. +TEST(PlatformThreadTest, ThreadPriorityCurrentThread) { + PlatformThreadHandle current_handle(PlatformThread::CurrentHandle()); + + // Confirm that the current thread's priority is as expected. + EXPECT_EQ(kThreadPriority_Normal, + PlatformThread::GetThreadPriority(current_handle)); + + // Create a test thread for verification purposes only. + FunctionTestThread thread; + PlatformThreadHandle handle; + ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); + thread.WaitForThreadStart(); + EXPECT_NE(thread.thread_id(), kInvalidThreadId); + EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId()); + + // Confirm that the new thread's priority is as expected. + EXPECT_EQ(kThreadPriority_Normal, PlatformThread::GetThreadPriority(handle)); + + // Toggle each supported priority on the current thread and confirm it only + // affects it (and not the test thread). + for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { + SCOPED_TRACE(i); + + // Alter and verify the current thread's priority. + PlatformThread::SetThreadPriority(current_handle, + kThreadPriorityTestValues[i]); + EXPECT_EQ(kThreadPriorityTestValues[i], + PlatformThread::GetThreadPriority(current_handle)); + + // Make sure the test thread was otherwise unaffected. + EXPECT_EQ(kThreadPriority_Normal, + PlatformThread::GetThreadPriority(handle)); + } + + // Restore current thread priority for follow-up tests. + PlatformThread::SetThreadPriority(current_handle, kThreadPriority_Normal); + + thread.MarkForTermination(); + PlatformThread::Join(handle); +} + } // namespace base diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc index 3df3719..df44ec2 100644 --- a/base/threading/platform_thread_win.cc +++ b/base/threading/platform_thread_win.cc @@ -126,18 +126,17 @@ bool CreateThreadInternal(size_t stack_size, // static PlatformThreadId PlatformThread::CurrentId() { - return GetCurrentThreadId(); + return ::GetCurrentThreadId(); } // static PlatformThreadRef PlatformThread::CurrentRef() { - return PlatformThreadRef(GetCurrentThreadId()); + return PlatformThreadRef(::GetCurrentThreadId()); } // static PlatformThreadHandle PlatformThread::CurrentHandle() { - NOTIMPLEMENTED(); // See OpenThread() - return PlatformThreadHandle(); + return PlatformThreadHandle(::GetCurrentThread()); } // static @@ -234,17 +233,56 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { // static void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, ThreadPriority priority) { + DCHECK(!handle.is_null()); + + int desired_priority = THREAD_PRIORITY_ERROR_RETURN; switch (priority) { case kThreadPriority_Normal: - ::SetThreadPriority(handle.handle_, THREAD_PRIORITY_NORMAL); + desired_priority = THREAD_PRIORITY_NORMAL; break; case kThreadPriority_RealtimeAudio: - ::SetThreadPriority(handle.handle_, THREAD_PRIORITY_TIME_CRITICAL); + desired_priority = THREAD_PRIORITY_TIME_CRITICAL; + break; + case kThreadPriority_Display: + desired_priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case kThreadPriority_Background: + desired_priority = THREAD_PRIORITY_LOWEST; break; default: NOTREACHED() << "Unknown priority."; break; } + DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN); + +#ifndef NDEBUG + const BOOL success = +#endif + ::SetThreadPriority(handle.handle_, desired_priority); + DPLOG_IF(ERROR, !success) << "Failed to set thread priority to " + << desired_priority; +} + +// static +ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) { + DCHECK(!handle.is_null()); + + int priority = ::GetThreadPriority(handle.handle_); + switch (priority) { + case THREAD_PRIORITY_NORMAL: + return kThreadPriority_Normal; + case THREAD_PRIORITY_TIME_CRITICAL: + return kThreadPriority_RealtimeAudio; + case THREAD_PRIORITY_ABOVE_NORMAL: + return kThreadPriority_Display; + case THREAD_PRIORITY_LOWEST: + return kThreadPriority_Background; + case THREAD_PRIORITY_ERROR_RETURN: + DPCHECK(false) << "GetThreadPriority error"; // Falls through. + default: + NOTREACHED() << "Unexpected priority: " << priority; + return kThreadPriority_Normal; + } } } // namespace base |