platform_thread.h 10 KB

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