platform_thread_mac.mm revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import <Foundation/Foundation.h>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <algorithm>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/mach.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/mach_time.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/thread_policy.h>
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/resource.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread_id_name_manager.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If Cocoa is to be used on more than one thread, it must know that the
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// application is multithreaded.  Since it's possible to enter Cocoa code
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from threads created by pthread_thread_create, Cocoa won't necessarily
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be aware that the application is multithreaded.  Spawning an NSThread is
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enough to get Cocoa to set up for multithreaded operation, so this is done
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if necessary before pthread_thread_create spawns any threads.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitThreading() {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BOOL multithreaded = [NSThread isMultiThreaded];
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!multithreaded) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // +[NSObject class] is idempotent.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [NSThread detachNewThreadSelector:@selector(class)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             toTarget:[NSObject class]
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           withObject:nil];
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    multithreaded = YES;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK([NSThread isMultiThreaded]);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PlatformThread::SetName(const char* name) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracked_objects::ThreadData::InitializeThreadContext(name);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pthread_setname_np is only available in 10.6 or later, so test
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for it at runtime.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int (*dynamic_pthread_setname_np)(const char*);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dlsym(RTLD_DEFAULT, "pthread_setname_np");
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dynamic_pthread_setname_np)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mac OS X does not expose the length limit of the name, so
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hardcode it.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kMaxNameLength = 63;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://crbug.com/47058
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dynamic_pthread_setname_np(shortened_name.c_str());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetPriorityNormal(mach_port_t mach_thread_id) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make thread standard policy.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Please note that this call could fail in rare cases depending
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on runtime conditions.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_standard_policy policy;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kern_return_t result = thread_policy_set(mach_thread_id,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           THREAD_STANDARD_POLICY,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           (thread_policy_t)&policy,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           THREAD_STANDARD_POLICY_COUNT);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != KERN_SUCCESS)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "thread_policy_set() failure: " << result;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Enables time-contraint policy and priority suitable for low-latency,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// glitch-resistant audio.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kern_return_t result;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increase thread priority to real-time.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Please note that the thread_policy_set() calls may fail in
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rare cases if the kernel decides the system is under heavy load
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and is unable to handle boosting the thread priority.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In these cases we just return early and go on with life.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make thread fixed priority.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_extended_policy_data_t policy;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  policy.timeshare = 0;  // Set to 1 for a non-fixed thread.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = thread_policy_set(mach_thread_id,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             THREAD_EXTENDED_POLICY,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (thread_policy_t)&policy,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             THREAD_EXTENDED_POLICY_COUNT);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != KERN_SUCCESS) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "thread_policy_set() failure: " << result;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to relatively high priority.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_precedence_policy_data_t precedence;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  precedence.importance = 63;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = thread_policy_set(mach_thread_id,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             THREAD_PRECEDENCE_POLICY,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (thread_policy_t)&precedence,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             THREAD_PRECEDENCE_POLICY_COUNT);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != KERN_SUCCESS) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "thread_policy_set() failure: " << result;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Most important, set real-time constraints.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Define the guaranteed and max fraction of time for the audio thread.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These "duty cycle" values can range from 0 to 1.  A value of 0.5
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // means the scheduler would give half the time to the thread.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These values have empirically been found to yield good behavior.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Good means that audio performance is high and other threads won't starve.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double kGuaranteedAudioDutyCycle = 0.75;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double kMaxAudioDutyCycle = 0.85;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Define constants determining how much time the audio thread can
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use in a given time quantum.  All times are in milliseconds.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // About 128 frames @44.1KHz
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double kTimeQuantum = 2.9;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Time guaranteed each quantum.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maximum time each quantum.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the conversion factor from milliseconds to absolute time
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which is what the time-constraints call needs.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mach_timebase_info_data_t tb_info;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mach_timebase_info(&tb_info);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double ms_to_abs_time =
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((double)tb_info.denom / (double)tb_info.numer) * 1000000;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_time_constraint_policy_data_t time_constraints;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_constraints.period = kTimeQuantum * ms_to_abs_time;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_constraints.computation = kAudioTimeNeeded * ms_to_abs_time;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_constraints.constraint = kMaxTimeAllowed * ms_to_abs_time;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_constraints.preemptible = 0;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = thread_policy_set(mach_thread_id,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             THREAD_TIME_CONSTRAINT_POLICY,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (thread_policy_t)&time_constraints,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             THREAD_TIME_CONSTRAINT_POLICY_COUNT);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != KERN_SUCCESS)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "thread_policy_set() failure: " << result;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ThreadPriority priority) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert from pthread_t to mach thread identifier.
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mach_port_t mach_thread_id = pthread_mach_thread_np(handle.handle_);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (priority) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kThreadPriority_Normal:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetPriorityNormal(mach_thread_id);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kThreadPriority_RealtimeAudio:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetPriorityRealtimeAudio(mach_thread_id);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED() << "Unknown priority.";
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_IOS)
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 0;
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The Mac OS X default for a pthread stack size is 512kB.
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // DEFAULT_STACK_SIZE for this purpose.
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // 512kB isn't quite generous enough for some deeply recursive threads that
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // otherwise request the default stack size by specifying 0. Here, adopt
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // glibc's behavior as on Linux, which is to use the current stack size
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // limit (ulimit -s) as the default stack size. See
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // avoid setting the limit below the Mac OS X default or the minimum usable
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // stack size, these values are also considered. If any of these values
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // stack_size is left at 0 to get the system default.
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Mac OS X normally only applies ulimit -s to the main thread stack. On
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // contemporary OS X and Linux systems alike, this value is generally 8MB
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // or in that neighborhood.
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t default_stack_size = 0;
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct rlimit stack_rlimit;
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      stack_rlimit.rlim_cur != RLIM_INFINITY) {
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default_stack_size =
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        std::max(std::max(default_stack_size,
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          static_cast<size_t>(PTHREAD_STACK_MIN)),
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 static_cast<size_t>(stack_rlimit.rlim_cur));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return default_stack_size;
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void InitOnThread() {
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TerminateOnThread() {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
225