diff options
author | crogers@google.com <crogers@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-17 20:01:25 +0000 |
---|---|---|
committer | crogers@google.com <crogers@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-17 20:01:25 +0000 |
commit | abb9efae9c9aec7df42c499025a06ac2524d5322 (patch) | |
tree | 10e2c6e65a992f2e3d96aa8acb9e21b9f95fef74 /base/threading | |
parent | 35a85c05edb0047a99610f94857d974af1082977 (diff) | |
download | chromium_src-abb9efae9c9aec7df42c499025a06ac2524d5322.zip chromium_src-abb9efae9c9aec7df42c499025a06ac2524d5322.tar.gz chromium_src-abb9efae9c9aec7df42c499025a06ac2524d5322.tar.bz2 |
Add support for real-time audio threads.
BUG=none
TEST=none
(tested locally on Mac OS X)
Review URL: http://codereview.chromium.org/6949009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85663 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/threading')
-rw-r--r-- | base/threading/platform_thread.h | 10 | ||||
-rw-r--r-- | base/threading/platform_thread_mac.mm | 104 | ||||
-rw-r--r-- | base/threading/platform_thread_posix.cc | 10 | ||||
-rw-r--r-- | base/threading/platform_thread_win.cc | 8 | ||||
-rw-r--r-- | base/threading/simple_thread.h | 6 |
5 files changed, 136 insertions, 2 deletions
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h index 40d445f..230d209 100644 --- a/base/threading/platform_thread.h +++ b/base/threading/platform_thread.h @@ -47,6 +47,13 @@ typedef pid_t PlatformThreadId; const PlatformThreadId kInvalidThreadId = 0; +// Valid values for SetThreadPriority() +enum ThreadPriority{ + kThreadPriority_Normal, + // Suitable for low-latency, glitch-resistant audio. + kThreadPriority_RealtimeAudio +}; + // A namespace for low-level thread functions. class BASE_API PlatformThread { public: @@ -91,6 +98,9 @@ class BASE_API PlatformThread { // |thread_handle|. static void Join(PlatformThreadHandle thread_handle); + static void SetThreadPriority(PlatformThreadHandle handle, + ThreadPriority priority); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); }; diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm index d77307c5..7d59064 100644 --- a/base/threading/platform_thread_mac.mm +++ b/base/threading/platform_thread_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,9 @@ #import <Foundation/Foundation.h> #include <dlfcn.h> +#include <mach/mach.h> +#include <mach/mach_time.h> +#include <mach/thread_policy.h> #include "base/logging.h" @@ -51,4 +54,103 @@ void PlatformThread::SetName(const char* name) { dynamic_pthread_setname_np(shortened_name.c_str()); } +namespace { + +void SetPriorityNormal(mach_port_t mach_thread_id) { + // Make thread standard policy. + thread_standard_policy policy; + kern_return_t result = thread_policy_set(mach_thread_id, + THREAD_STANDARD_POLICY, + (thread_policy_t)&policy, + THREAD_STANDARD_POLICY_COUNT); + + DCHECK_EQ(KERN_SUCCESS, result); +} + +// Enables time-contraint policy and priority suitable for low-latency, +// glitch-resistant audio. +void SetPriorityRealtimeAudio(mach_port_t mach_thread_id) { + kern_return_t result; + + // Increase thread priority to real-time. + + // Make thread fixed priority. + thread_extended_policy_data_t policy; + policy.timeshare = 0; // Set to 1 for a non-fixed thread. + result = thread_policy_set(mach_thread_id, + THREAD_EXTENDED_POLICY, + (thread_policy_t)&policy, + THREAD_EXTENDED_POLICY_COUNT); + + DCHECK_EQ(KERN_SUCCESS, result); + + // Set to relatively high priority. + thread_precedence_policy_data_t precedence; + precedence.importance = 63; + result = thread_policy_set(mach_thread_id, + THREAD_PRECEDENCE_POLICY, + (thread_policy_t)&precedence, + THREAD_PRECEDENCE_POLICY_COUNT); + DCHECK_EQ(KERN_SUCCESS, result); + + // Most important, set real-time constraints. + + // Define the guaranteed and max fraction of time for the audio thread. + // These "duty cycle" values can range from 0 to 1. A value of 0.5 + // means the scheduler would give half the time to the thread. + // These values have empirically been found to yield good behavior. + // Good means that audio performance is high and other threads won't starve. + const double kGuaranteedAudioDutyCycle = 0.75; + const double kMaxAudioDutyCycle = 0.85; + + // Define constants determining how much time the audio thread can + // use in a given time quantum. All times are in milliseconds. + + // About 128 frames @44.1KHz + const double kTimeQuantum = 2.9; + + // Time guaranteed each quantum. + const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum; + + // Maximum time each quantum. + const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum; + + // Get the conversion factor from milliseconds to absolute time + // which is what the time-constraints call needs. + mach_timebase_info_data_t tb_info; + mach_timebase_info(&tb_info); + double ms_to_abs_time = + ((double)tb_info.denom / (double)tb_info.numer) * 1000000; + + thread_time_constraint_policy_data_t time_constraints; + time_constraints.period = kTimeQuantum * ms_to_abs_time; + time_constraints.computation = kAudioTimeNeeded * ms_to_abs_time; + time_constraints.constraint = kMaxTimeAllowed * ms_to_abs_time; + time_constraints.preemptible = 0; + + result = thread_policy_set(mach_thread_id, + THREAD_TIME_CONSTRAINT_POLICY, + (thread_policy_t)&time_constraints, + THREAD_TIME_CONSTRAINT_POLICY_COUNT); + DCHECK_EQ(KERN_SUCCESS, result); +} + +} // anonymous namespace + +// static +void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, + ThreadPriority priority) { + // Convert from pthread_t to mach thread identifier. + mach_port_t mach_thread_id = pthread_mach_thread_np(handle); + + switch (priority) { + case kThreadPriority_Normal: + SetPriorityNormal(mach_thread_id); + break; + case kThreadPriority_RealtimeAudio: + SetPriorityRealtimeAudio(mach_thread_id); + break; + } +} + } // namespace base diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc index e880222..526e782 100644 --- a/base/threading/platform_thread_posix.cc +++ b/base/threading/platform_thread_posix.cc @@ -222,4 +222,14 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { pthread_join(thread_handle, NULL); } +#if !defined(OS_MACOSX) +// Mac OS X uses lower-level mach APIs + +// static +void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) { + // TODO(crogers): implement + NOTIMPLEMENTED(); +} +#endif + } // namespace base diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc index 734f404..56d7381 100644 --- a/base/threading/platform_thread_win.cc +++ b/base/threading/platform_thread_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -144,4 +144,10 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { CloseHandle(thread_handle); } +// static +void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) { + // TODO(crogers): implement + NOTIMPLEMENTED(); +} + } // namespace base diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h index f1b644b..5d8c458 100644 --- a/base/threading/simple_thread.h +++ b/base/threading/simple_thread.h @@ -104,6 +104,12 @@ class BASE_API SimpleThread : public PlatformThread::Delegate { // Overridden from PlatformThread::Delegate: virtual void ThreadMain(); + // Only set priorities with a careful understanding of the consequences. + // This is meant for very limited use cases. + void SetThreadPriority(ThreadPriority priority) { + PlatformThread::SetThreadPriority(thread_, priority); + } + private: const std::string name_prefix_; std::string name_; |