| 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
|
|
|