Index: base/threading/platform_thread_mac.mm |
=================================================================== |
--- base/threading/platform_thread_mac.mm (revision 85324) |
+++ base/threading/platform_thread_mac.mm (working copy) |
@@ -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 @@ |
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 |