summaryrefslogtreecommitdiffstats
path: root/base/threading
diff options
context:
space:
mode:
authorgab <gab@chromium.org>2015-04-01 10:10:06 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-01 17:10:45 +0000
commitf1921cb37b83bce16c07ca93975cded2b2863dd0 (patch)
treed5e331b67961b40f2c2504422d473d3bd13aba64 /base/threading
parent5656ae68841a3e3ddaac75cf2983d9052d71d0d5 (diff)
downloadchromium_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.h13
-rw-r--r--base/threading/platform_thread_android.cc10
-rw-r--r--base/threading/platform_thread_freebsd.cc24
-rw-r--r--base/threading/platform_thread_internal_posix.cc10
-rw-r--r--base/threading/platform_thread_internal_posix.h14
-rw-r--r--base/threading/platform_thread_linux.cc24
-rw-r--r--base/threading/platform_thread_mac.mm6
-rw-r--r--base/threading/platform_thread_posix.cc39
-rw-r--r--base/threading/platform_thread_unittest.cc180
-rw-r--r--base/threading/platform_thread_win.cc50
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