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. 4 5 // WARNING: You should *NOT* be using this class directly. PlatformThread is 6 // the low-level platform-specific abstraction to the OS's threading interface. 7 // You should instead be using a message-loop driven Thread, see thread.h. 8 9 #ifndef BASE_THREADING_PLATFORM_THREAD_H_ 10 #define BASE_THREADING_PLATFORM_THREAD_H_ 11 12 #include <stddef.h> 13 14 #include "base/base_export.h" 15 #include "base/macros.h" 16 #include "base/time/time.h" 17 #include "build/build_config.h" 18 19 #if defined(OS_WIN) 20 #include "base/win/windows_types.h" 21 #elif defined(OS_FUCHSIA) 22 #include <zircon/types.h> 23 #elif defined(OS_MACOSX) 24 #include <mach/mach_types.h> 25 #elif defined(OS_POSIX) 26 #include <pthread.h> 27 #include <unistd.h> 28 #endif 29 30 namespace base { 31 32 // Used for logging. Always an integer value. 33 #if defined(OS_WIN) 34 typedef DWORD PlatformThreadId; 35 #elif defined(OS_FUCHSIA) 36 typedef zx_handle_t PlatformThreadId; 37 #elif defined(OS_MACOSX) 38 typedef mach_port_t PlatformThreadId; 39 #elif defined(OS_POSIX) 40 typedef pid_t PlatformThreadId; 41 #endif 42 43 // Used for thread checking and debugging. 44 // Meant to be as fast as possible. 45 // These are produced by PlatformThread::CurrentRef(), and used to later 46 // check if we are on the same thread or not by using ==. These are safe 47 // to copy between threads, but can't be copied to another process as they 48 // have no meaning there. Also, the internal identifier can be re-used 49 // after a thread dies, so a PlatformThreadRef cannot be reliably used 50 // to distinguish a new thread from an old, dead thread. 51 class PlatformThreadRef { 52 public: 53 #if defined(OS_WIN) 54 typedef DWORD RefType; 55 #else // OS_POSIX 56 typedef pthread_t RefType; 57 #endif PlatformThreadRef()58 constexpr PlatformThreadRef() : id_(0) {} 59 PlatformThreadRef(RefType id)60 explicit constexpr PlatformThreadRef(RefType id) : id_(id) {} 61 62 bool operator==(PlatformThreadRef other) const { 63 return id_ == other.id_; 64 } 65 66 bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; } 67 is_null()68 bool is_null() const { 69 return id_ == 0; 70 } 71 private: 72 RefType id_; 73 }; 74 75 // Used to operate on threads. 76 class PlatformThreadHandle { 77 public: 78 #if defined(OS_WIN) 79 typedef void* Handle; 80 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) 81 typedef pthread_t Handle; 82 #endif 83 PlatformThreadHandle()84 constexpr PlatformThreadHandle() : handle_(0) {} 85 PlatformThreadHandle(Handle handle)86 explicit constexpr PlatformThreadHandle(Handle handle) : handle_(handle) {} 87 is_equal(const PlatformThreadHandle & other)88 bool is_equal(const PlatformThreadHandle& other) const { 89 return handle_ == other.handle_; 90 } 91 is_null()92 bool is_null() const { 93 return !handle_; 94 } 95 platform_handle()96 Handle platform_handle() const { 97 return handle_; 98 } 99 100 private: 101 Handle handle_; 102 }; 103 104 const PlatformThreadId kInvalidThreadId(0); 105 106 // Valid values for priority of Thread::Options and SimpleThread::Options, and 107 // SetCurrentThreadPriority(), listed in increasing order of importance. 108 enum class ThreadPriority : int { 109 // Suitable for threads that shouldn't disrupt high priority work. 110 BACKGROUND, 111 // Default priority level. 112 NORMAL, 113 // Suitable for threads which generate data for the display (at ~60Hz). 114 DISPLAY, 115 // Suitable for low-latency, glitch-resistant audio. 116 REALTIME_AUDIO, 117 }; 118 119 // A namespace for low-level thread functions. 120 class BASE_EXPORT PlatformThread { 121 public: 122 // Implement this interface to run code on a background thread. Your 123 // ThreadMain method will be called on the newly created thread. 124 class BASE_EXPORT Delegate { 125 public: 126 virtual void ThreadMain() = 0; 127 128 protected: 129 virtual ~Delegate() = default; 130 }; 131 132 // Gets the current thread id, which may be useful for logging purposes. 133 static PlatformThreadId CurrentId(); 134 135 // Gets the current thread reference, which can be used to check if 136 // we're on the right thread quickly. 137 static PlatformThreadRef CurrentRef(); 138 139 // Get the handle representing the current thread. On Windows, this is a 140 // pseudo handle constant which will always represent the thread using it and 141 // hence should not be shared with other threads nor be used to differentiate 142 // the current thread from another. 143 static PlatformThreadHandle CurrentHandle(); 144 145 // Yield the current thread so another thread can be scheduled. 146 static void YieldCurrentThread(); 147 148 // Sleeps for the specified duration. 149 static void Sleep(base::TimeDelta duration); 150 151 // Sets the thread name visible to debuggers/tools. This will try to 152 // initialize the context for current thread unless it's a WorkerThread. 153 static void SetName(const std::string& name); 154 155 // Gets the thread name, if previously set by SetName. 156 static const char* GetName(); 157 158 // Creates a new thread. The |stack_size| parameter can be 0 to indicate 159 // that the default stack size should be used. Upon success, 160 // |*thread_handle| will be assigned a handle to the newly created thread, 161 // and |delegate|'s ThreadMain method will be executed on the newly created 162 // thread. 163 // NOTE: When you are done with the thread handle, you must call Join to 164 // release system resources associated with the thread. You must ensure that 165 // the Delegate object outlives the thread. Create(size_t stack_size,Delegate * delegate,PlatformThreadHandle * thread_handle)166 static bool Create(size_t stack_size, 167 Delegate* delegate, 168 PlatformThreadHandle* thread_handle) { 169 return CreateWithPriority(stack_size, delegate, thread_handle, 170 ThreadPriority::NORMAL); 171 } 172 173 // CreateWithPriority() does the same thing as Create() except the priority of 174 // the thread is set based on |priority|. 175 static bool CreateWithPriority(size_t stack_size, Delegate* delegate, 176 PlatformThreadHandle* thread_handle, 177 ThreadPriority priority); 178 179 // CreateNonJoinable() does the same thing as Create() except the thread 180 // cannot be Join()'d. Therefore, it also does not output a 181 // PlatformThreadHandle. 182 static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); 183 184 // CreateNonJoinableWithPriority() does the same thing as CreateNonJoinable() 185 // except the priority of the thread is set based on |priority|. 186 static bool CreateNonJoinableWithPriority(size_t stack_size, 187 Delegate* delegate, 188 ThreadPriority priority); 189 190 // Joins with a thread created via the Create function. This function blocks 191 // the caller until the designated thread exits. This will invalidate 192 // |thread_handle|. 193 static void Join(PlatformThreadHandle thread_handle); 194 195 // Detaches and releases the thread handle. The thread is no longer joinable 196 // and |thread_handle| is invalidated after this call. 197 static void Detach(PlatformThreadHandle thread_handle); 198 199 // Returns true if SetCurrentThreadPriority() can be used to increase the 200 // priority of the current thread. 201 static bool CanIncreaseCurrentThreadPriority(); 202 203 // Toggles the current thread's priority at runtime. 204 // 205 // A thread may not be able to raise its priority back up after lowering it if 206 // the process does not have a proper permission, e.g. CAP_SYS_NICE on Linux. 207 // A thread may not be able to lower its priority back down after raising it 208 // to REALTIME_AUDIO. 209 // 210 // This function must not be called from the main thread on Mac. This is to 211 // avoid performance regressions (https://crbug.com/601270). 212 // 213 // Since changing other threads' priority is not permitted in favor of 214 // security, this interface is restricted to change only the current thread 215 // priority (https://crbug.com/399473). 216 static void SetCurrentThreadPriority(ThreadPriority priority); 217 218 static ThreadPriority GetCurrentThreadPriority(); 219 220 #if defined(OS_LINUX) 221 // Toggles a specific thread's priority at runtime. This can be used to 222 // change the priority of a thread in a different process and will fail 223 // if the calling process does not have proper permissions. The 224 // SetCurrentThreadPriority() function above is preferred in favor of 225 // security but on platforms where sandboxed processes are not allowed to 226 // change priority this function exists to allow a non-sandboxed process 227 // to change the priority of sandboxed threads for improved performance. 228 // Warning: Don't use this for a main thread because that will change the 229 // whole thread group's (i.e. process) priority. 230 static void SetThreadPriority(PlatformThreadId thread_id, 231 ThreadPriority priority); 232 #endif 233 234 private: 235 DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); 236 }; 237 238 } // namespace base 239 240 #endif // BASE_THREADING_PLATFORM_THREAD_H_ 241