Fake PO2TS GetRequestContext should return NULL.
[chromium-blink-merge.git] / base / threading / platform_thread_mac.mm
blobd81a286cb2cba25dec3be9be80d16eb6ac54b7e7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/threading/platform_thread.h"
7 #import <Foundation/Foundation.h>
8 #include <algorithm>
9 #include <dlfcn.h>
10 #include <mach/mach.h>
11 #include <mach/mach_time.h>
12 #include <mach/thread_policy.h>
13 #include <sys/resource.h>
15 #include "base/lazy_instance.h"
16 #include "base/logging.h"
17 #include "base/threading/thread_id_name_manager.h"
18 #include "base/tracked_objects.h"
20 namespace base {
22 // If Cocoa is to be used on more than one thread, it must know that the
23 // application is multithreaded.  Since it's possible to enter Cocoa code
24 // from threads created by pthread_thread_create, Cocoa won't necessarily
25 // be aware that the application is multithreaded.  Spawning an NSThread is
26 // enough to get Cocoa to set up for multithreaded operation, so this is done
27 // if necessary before pthread_thread_create spawns any threads.
29 // http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html
30 void InitThreading() {
31   static BOOL multithreaded = [NSThread isMultiThreaded];
32   if (!multithreaded) {
33     // +[NSObject class] is idempotent.
34     [NSThread detachNewThreadSelector:@selector(class)
35                              toTarget:[NSObject class]
36                            withObject:nil];
37     multithreaded = YES;
39     DCHECK([NSThread isMultiThreaded]);
40   }
43 // static
44 void PlatformThread::SetName(const char* name) {
45   ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name);
46   tracked_objects::ThreadData::InitializeThreadContext(name);
48   // pthread_setname_np is only available in 10.6 or later, so test
49   // for it at runtime.
50   int (*dynamic_pthread_setname_np)(const char*);
51   *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
52       dlsym(RTLD_DEFAULT, "pthread_setname_np");
53   if (!dynamic_pthread_setname_np)
54     return;
56   // Mac OS X does not expose the length limit of the name, so
57   // hardcode it.
58   const int kMaxNameLength = 63;
59   std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
60   // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
61   // See http://crbug.com/47058
62   dynamic_pthread_setname_np(shortened_name.c_str());
65 namespace {
67 void SetPriorityNormal(mach_port_t mach_thread_id) {
68   // Make thread standard policy.
69   // Please note that this call could fail in rare cases depending
70   // on runtime conditions.
71   thread_standard_policy policy;
72   kern_return_t result = thread_policy_set(mach_thread_id,
73                                            THREAD_STANDARD_POLICY,
74                                            (thread_policy_t)&policy,
75                                            THREAD_STANDARD_POLICY_COUNT);
77   if (result != KERN_SUCCESS)
78     DVLOG(1) << "thread_policy_set() failure: " << result;
81 // Enables time-contraint policy and priority suitable for low-latency,
82 // glitch-resistant audio.
83 void SetPriorityRealtimeAudio(mach_port_t mach_thread_id) {
84   kern_return_t result;
86   // Increase thread priority to real-time.
88   // Please note that the thread_policy_set() calls may fail in
89   // rare cases if the kernel decides the system is under heavy load
90   // and is unable to handle boosting the thread priority.
91   // In these cases we just return early and go on with life.
93   // Make thread fixed priority.
94   thread_extended_policy_data_t policy;
95   policy.timeshare = 0;  // Set to 1 for a non-fixed thread.
96   result = thread_policy_set(mach_thread_id,
97                              THREAD_EXTENDED_POLICY,
98                              (thread_policy_t)&policy,
99                              THREAD_EXTENDED_POLICY_COUNT);
100   if (result != KERN_SUCCESS) {
101     DVLOG(1) << "thread_policy_set() failure: " << result;
102     return;
103   }
105   // Set to relatively high priority.
106   thread_precedence_policy_data_t precedence;
107   precedence.importance = 63;
108   result = thread_policy_set(mach_thread_id,
109                              THREAD_PRECEDENCE_POLICY,
110                              (thread_policy_t)&precedence,
111                              THREAD_PRECEDENCE_POLICY_COUNT);
112   if (result != KERN_SUCCESS) {
113     DVLOG(1) << "thread_policy_set() failure: " << result;
114     return;
115   }
117   // Most important, set real-time constraints.
119   // Define the guaranteed and max fraction of time for the audio thread.
120   // These "duty cycle" values can range from 0 to 1.  A value of 0.5
121   // means the scheduler would give half the time to the thread.
122   // These values have empirically been found to yield good behavior.
123   // Good means that audio performance is high and other threads won't starve.
124   const double kGuaranteedAudioDutyCycle = 0.75;
125   const double kMaxAudioDutyCycle = 0.85;
127   // Define constants determining how much time the audio thread can
128   // use in a given time quantum.  All times are in milliseconds.
130   // About 128 frames @44.1KHz
131   const double kTimeQuantum = 2.9;
133   // Time guaranteed each quantum.
134   const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum;
136   // Maximum time each quantum.
137   const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum;
139   // Get the conversion factor from milliseconds to absolute time
140   // which is what the time-constraints call needs.
141   mach_timebase_info_data_t tb_info;
142   mach_timebase_info(&tb_info);
143   double ms_to_abs_time =
144       ((double)tb_info.denom / (double)tb_info.numer) * 1000000;
146   thread_time_constraint_policy_data_t time_constraints;
147   time_constraints.period = kTimeQuantum * ms_to_abs_time;
148   time_constraints.computation = kAudioTimeNeeded * ms_to_abs_time;
149   time_constraints.constraint = kMaxTimeAllowed * ms_to_abs_time;
150   time_constraints.preemptible = 0;
152   result = thread_policy_set(mach_thread_id,
153                              THREAD_TIME_CONSTRAINT_POLICY,
154                              (thread_policy_t)&time_constraints,
155                              THREAD_TIME_CONSTRAINT_POLICY_COUNT);
156   if (result != KERN_SUCCESS)
157     DVLOG(1) << "thread_policy_set() failure: " << result;
159   return;
162 }  // anonymous namespace
164 // static
165 void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
166                                        ThreadPriority priority) {
167   // Convert from pthread_t to mach thread identifier.
168   mach_port_t mach_thread_id = pthread_mach_thread_np(handle.handle_);
170   switch (priority) {
171     case kThreadPriority_Normal:
172       SetPriorityNormal(mach_thread_id);
173       break;
174     case kThreadPriority_RealtimeAudio:
175       SetPriorityRealtimeAudio(mach_thread_id);
176       break;
177     default:
178       NOTREACHED() << "Unknown priority.";
179       break;
180   }
183 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
184 #if defined(OS_IOS)
185   return 0;
186 #else
187   // The Mac OS X default for a pthread stack size is 512kB.
188   // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
189   // DEFAULT_STACK_SIZE for this purpose.
190   //
191   // 512kB isn't quite generous enough for some deeply recursive threads that
192   // otherwise request the default stack size by specifying 0. Here, adopt
193   // glibc's behavior as on Linux, which is to use the current stack size
194   // limit (ulimit -s) as the default stack size. See
195   // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
196   // avoid setting the limit below the Mac OS X default or the minimum usable
197   // stack size, these values are also considered. If any of these values
198   // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
199   // stack_size is left at 0 to get the system default.
200   //
201   // Mac OS X normally only applies ulimit -s to the main thread stack. On
202   // contemporary OS X and Linux systems alike, this value is generally 8MB
203   // or in that neighborhood.
204   size_t default_stack_size = 0;
205   struct rlimit stack_rlimit;
206   if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
207       getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
208       stack_rlimit.rlim_cur != RLIM_INFINITY) {
209     default_stack_size =
210         std::max(std::max(default_stack_size,
211                           static_cast<size_t>(PTHREAD_STACK_MIN)),
212                  static_cast<size_t>(stack_rlimit.rlim_cur));
213   }
214   return default_stack_size;
215 #endif
218 void InitOnThread() {
221 void TerminateOnThread() {
224 }  // namespace base