// Copyright (c) 2012 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.

#include "base/threading/platform_thread.h"

#import <Foundation/Foundation.h>
#include <dlfcn.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach/thread_policy.h>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/threading/thread_local.h"
#include "base/tracked_objects.h"

namespace base {

namespace {

LazyInstance<ThreadLocalPointer<char> >::Leaky
    current_thread_name = LAZY_INSTANCE_INITIALIZER;

}  // namespace

// If Cocoa is to be used on more than one thread, it must know that the
// application is multithreaded.  Since it's possible to enter Cocoa code
// from threads created by pthread_thread_create, Cocoa won't necessarily
// be aware that the application is multithreaded.  Spawning an NSThread is
// enough to get Cocoa to set up for multithreaded operation, so this is done
// if necessary before pthread_thread_create spawns any threads.
//
// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html
void InitThreading() {
  static BOOL multithreaded = [NSThread isMultiThreaded];
  if (!multithreaded) {
    // +[NSObject class] is idempotent.
    [NSThread detachNewThreadSelector:@selector(class)
                             toTarget:[NSObject class]
                           withObject:nil];
    multithreaded = YES;

    DCHECK([NSThread isMultiThreaded]);
  }
}

// static
void PlatformThread::SetName(const char* name) {
  current_thread_name.Pointer()->Set(const_cast<char*>(name));
  tracked_objects::ThreadData::InitializeThreadContext(name);

  // pthread_setname_np is only available in 10.6 or later, so test
  // for it at runtime.
  int (*dynamic_pthread_setname_np)(const char*);
  *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
      dlsym(RTLD_DEFAULT, "pthread_setname_np");
  if (!dynamic_pthread_setname_np)
    return;

  // Mac OS X does not expose the length limit of the name, so
  // hardcode it.
  const int kMaxNameLength = 63;
  std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
  // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
  // See http://crbug.com/47058
  dynamic_pthread_setname_np(shortened_name.c_str());
}

// static
const char* PlatformThread::GetName() {
  return current_thread_name.Pointer()->Get();
}

namespace {

void SetPriorityNormal(mach_port_t mach_thread_id) {
  // Make thread standard policy.
  // Please note that this call could fail in rare cases depending
  // on runtime conditions.
  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);

  if (result != KERN_SUCCESS)
    DVLOG(1) << "thread_policy_set() failure: " << 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.

  // Please note that the thread_policy_set() calls may fail in
  // rare cases if the kernel decides the system is under heavy load
  // and is unable to handle boosting the thread priority.
  // In these cases we just return early and go on with life.

  // 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);
  if (result != KERN_SUCCESS) {
    DVLOG(1) << "thread_policy_set() failure: " << result;
    return;
  }

  // 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);
  if (result != KERN_SUCCESS) {
    DVLOG(1) << "thread_policy_set() failure: " << result;
    return;
  }

  // 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);
  if (result != KERN_SUCCESS)
    DVLOG(1) << "thread_policy_set() failure: " << result;

  return;
}

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