diff options
Diffstat (limited to 'base/threading/platform_thread_mac.mm')
-rw-r--r-- | base/threading/platform_thread_mac.mm | 104 |
1 files changed, 103 insertions, 1 deletions
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 |