1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_THREAD_POOL_WORKER_THREAD_H_ 6 #define BASE_TASK_THREAD_POOL_WORKER_THREAD_H_ 7 8 #include "base/base_export.h" 9 #include "base/compiler_specific.h" 10 #include "base/memory/raw_ptr.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/synchronization/atomic_flag.h" 13 #include "base/synchronization/waitable_event.h" 14 #include "base/task/common/checked_lock.h" 15 #include "base/task/thread_pool/task_source.h" 16 #include "base/task/thread_pool/task_tracker.h" 17 #include "base/task/thread_pool/tracked_ref.h" 18 #include "base/thread_annotations.h" 19 #include "base/threading/platform_thread.h" 20 #include "base/time/time.h" 21 #include "build/build_config.h" 22 23 namespace base { 24 25 class WorkerThreadObserver; 26 27 namespace internal { 28 29 class TaskTracker; 30 31 // A worker that manages a single thread to run Tasks from TaskSources returned 32 // by a delegate. 33 // 34 // A WorkerThread starts out sleeping. It is woken up by a call to WakeUp(). 35 // After a wake-up, a WorkerThread runs Tasks from TaskSources returned by 36 // the GetWork() method of its delegate as long as it doesn't return nullptr. It 37 // also periodically checks with its TaskTracker whether shutdown has completed 38 // and exits when it has. 39 // 40 // This class is thread-safe. 41 class BASE_EXPORT WorkerThread : public RefCountedThreadSafe<WorkerThread>, 42 public PlatformThread::Delegate { 43 public: 44 // Labels this WorkerThread's association. This doesn't affect any logic 45 // but will add a stack frame labeling this thread for ease of stack trace 46 // identification 47 enum class ThreadLabel { 48 POOLED, 49 SHARED, 50 DEDICATED, 51 #if BUILDFLAG(IS_WIN) 52 SHARED_COM, 53 DEDICATED_COM, 54 #endif // BUILDFLAG(IS_WIN) 55 }; 56 57 // Delegate interface for WorkerThread. All methods are called from the 58 // thread managed by the WorkerThread instance. 59 class BASE_EXPORT Delegate { 60 public: 61 virtual ~Delegate() = default; 62 63 // Returns the ThreadLabel the Delegate wants its WorkerThreads' stacks 64 // to be labeled with. 65 virtual ThreadLabel GetThreadLabel() const; 66 67 // Called by |worker|'s thread when it enters its main function. 68 virtual void OnMainEntry(WorkerThread* worker) = 0; 69 70 // Called by |worker|'s thread to get a TaskSource from which to run a Task. 71 virtual RegisteredTaskSource GetWork(WorkerThread* worker) = 0; 72 73 // Called by the worker thread to swap the task source that has just run for 74 // another one, if available. |task_source| must not be null. The worker can 75 // then run the task returned as if it was acquired via GetWork(). 76 virtual RegisteredTaskSource SwapProcessedTask( 77 RegisteredTaskSource task_source, 78 WorkerThread* worker) = 0; 79 80 // Called to determine how long to sleep before the next call to GetWork(). 81 // GetWork() may be called before this timeout expires if the worker's 82 // WakeUp() method is called. 83 virtual TimeDelta GetSleepTimeout() = 0; 84 85 // Called by the WorkerThread's thread to wait for work. 86 virtual void WaitForWork(); 87 88 // Called by |worker|'s thread right before the main function exits. The 89 // Delegate is free to release any associated resources in this call. It is 90 // guaranteed that WorkerThread won't access the Delegate or the 91 // TaskTracker after calling OnMainExit() on the Delegate. OnMainExit(WorkerThread * worker)92 virtual void OnMainExit(WorkerThread* worker) {} 93 94 // Called by a WorkerThread when it is woken up without any work being 95 // available for it to run. RecordUnnecessaryWakeup()96 virtual void RecordUnnecessaryWakeup() {} 97 98 static constexpr TimeDelta kPurgeThreadCacheIdleDelay = Seconds(1); 99 100 // Do not wake up to purge within the first minute of process lifetime. In 101 // short lived processes this will avoid waking up to try and save memory 102 // for a heap that will be going away soon. For longer lived processes this 103 // should allow for better performance at process startup since even if a 104 // worker goes to sleep for kPurgeThreadCacheIdleDelay it's very likely it 105 // will be needed soon after because of heavy startup workloads. 106 static constexpr TimeDelta kFirstSleepDurationBeforePurge = Minutes(1); 107 108 protected: 109 friend WorkerThread; 110 static bool IsDelayFirstWorkerSleepEnabled(); 111 112 // Called in WaitForWork() to hide the worker's synchronization 113 // mechanism. Returns |true| if signaled, and |false| if the call timed out. 114 virtual bool TimedWait(TimeDelta timeout); 115 116 #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ 117 PA_CONFIG(THREAD_CACHE_SUPPORTED) 118 // Returns the desired sleep time before the worker has to wake up to purge 119 // the cache thread or reclaim itself. 120 virtual TimeDelta GetSleepDurationBeforePurge(TimeTicks now); 121 set_first_sleep_time_for_testing(TimeTicks first_sleep_time)122 void set_first_sleep_time_for_testing(TimeTicks first_sleep_time) { 123 first_sleep_time_for_testing_ = first_sleep_time; 124 } 125 126 // Simulated time at which the worker first attempts to go to sleep. 127 TimeTicks first_sleep_time_for_testing_; 128 129 #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && 130 // PA_CONFIG(THREAD_CACHE_SUPPORTED) 131 132 // Event to wake up the thread managed by the WorkerThread whose delegate 133 // this is. 134 WaitableEvent wake_up_event_{WaitableEvent::ResetPolicy::AUTOMATIC, 135 WaitableEvent::InitialState::NOT_SIGNALED}; 136 }; 137 138 // Creates a WorkerThread that runs Tasks from TaskSources returned by 139 // |delegate()|. No actual thread will be created for this WorkerThread before 140 // Start() is called. |thread_type_hint| is the preferred thread type; the 141 // actual thread type depends on shutdown state and platform 142 // capabilities. |task_tracker| is used to handle shutdown behavior of 143 // Tasks. |sequence_num| is an index that helps identifying this 144 // WorkerThread. |predecessor_lock| is a lock that is allowed to be held when 145 // calling methods on this WorkerThread. Either JoinForTesting() or Cleanup() 146 // must be called before releasing the last external reference. 147 WorkerThread(ThreadType thread_type_hint, 148 std::unique_ptr<Delegate> delegate, 149 TrackedRef<TaskTracker> task_tracker, 150 size_t sequence_num, 151 const CheckedLock* predecessor_lock = nullptr, 152 void* flow_terminator = nullptr); 153 154 WorkerThread(const WorkerThread&) = delete; 155 WorkerThread& operator=(const WorkerThread&) = delete; 156 157 // Creates a thread to back the WorkerThread. The thread will be in a wait 158 // state pending a WakeUp() call. No thread will be created if Cleanup() was 159 // called. `io_thread_task_runner` is used to setup FileDescriptorWatcher on 160 // worker threads. `io_thread_task_runner` must refer to a Thread with 161 // MessgaePumpType::IO. If specified, |worker_thread_observer| will be 162 // notified when the worker enters and exits its main function. It must not be 163 // destroyed before JoinForTesting() has returned (must never be destroyed in 164 // production). Returns true on success. 165 bool Start(scoped_refptr<SingleThreadTaskRunner> io_thread_task_runner_, 166 WorkerThreadObserver* worker_thread_observer = nullptr); 167 168 // Wakes up this WorkerThread if it wasn't already awake. After 169 // this is called, this WorkerThread will run Tasks from 170 // TaskSources returned by the GetWork() method of its delegate until it 171 // returns nullptr. No-op if Start() wasn't called. DCHECKs if called after 172 // Start() has failed or after Cleanup() has been called. 173 void WakeUp(); 174 175 // Joins this WorkerThread. If a Task is already running, it will be 176 // allowed to complete its execution. This can only be called once. 177 // 178 // Note: A thread that detaches before JoinForTesting() is called may still be 179 // running after JoinForTesting() returns. However, it can't run tasks after 180 // JoinForTesting() returns. 181 void JoinForTesting(); 182 183 // Returns true if the worker is alive. 184 bool ThreadAliveForTesting() const; 185 186 // Makes a request to cleanup the worker. This may be called from any thread. 187 // The caller is expected to release its reference to this object after 188 // calling Cleanup(). Further method calls after Cleanup() returns are 189 // undefined. 190 // 191 // Expected Usage: 192 // scoped_refptr<WorkerThread> worker_ = /* Existing Worker */ 193 // worker_->Cleanup(); 194 // worker_ = nullptr; 195 void Cleanup(); 196 197 Delegate* delegate(); 198 199 // Possibly updates the thread type to the appropriate type based on the 200 // thread type hint, current shutdown state, and platform capabilities. 201 // Must be called on the thread managed by |this|. 202 void MaybeUpdateThreadType(); 203 204 // Informs this WorkerThread about periods during which it is not being 205 // used. Thread-safe. 206 void BeginUnusedPeriod(); 207 void EndUnusedPeriod(); 208 // Returns the last time this WorkerThread was used. Returns a null time if 209 // this WorkerThread is currently in-use. Thread-safe. 210 TimeTicks GetLastUsedTime() const; 211 sequence_num()212 size_t sequence_num() const { return sequence_num_; } 213 214 protected: 215 friend class RefCountedThreadSafe<WorkerThread>; 216 class Thread; 217 218 ~WorkerThread() override; 219 220 // Must be called by implementations on destruction. 221 void Destroy(); 222 223 bool ShouldExit() const; 224 225 // Returns the thread type to use based on the thread type hint, current 226 // shutdown state, and platform capabilities. 227 ThreadType GetDesiredThreadType() const; 228 229 // Changes the thread type to |desired_thread_type|. Must be called on the 230 // thread managed by |this|. 231 void UpdateThreadType(ThreadType desired_thread_type); 232 233 // PlatformThread::Delegate: 234 void ThreadMain() override; 235 236 // Dummy frames to act as "RunLabeledWorker()" (see RunMain() below). Their 237 // impl is aliased to prevent compiler/linker from optimizing them out. 238 void RunPooledWorker(); 239 void RunBackgroundPooledWorker(); 240 void RunSharedWorker(); 241 void RunBackgroundSharedWorker(); 242 void RunDedicatedWorker(); 243 void RunBackgroundDedicatedWorker(); 244 #if BUILDFLAG(IS_WIN) 245 void RunSharedCOMWorker(); 246 void RunBackgroundSharedCOMWorker(); 247 void RunDedicatedCOMWorker(); 248 void RunBackgroundDedicatedCOMWorker(); 249 #endif // BUILDFLAG(IS_WIN) 250 251 // The real main, invoked through : 252 // ThreadMain() -> RunLabeledWorker() -> RunWorker(). 253 // "RunLabeledWorker()" is a dummy frame based on ThreadLabel+ThreadType 254 // and used to easily identify threads in stack traces. 255 NOT_TAIL_CALLED void RunWorker(); 256 257 // Self-reference to prevent destruction of |this| while the thread is alive. 258 // Set in Start() before creating the thread. Reset in ThreadMain() before the 259 // thread exits. No lock required because the first access occurs before the 260 // thread is created and the second access occurs on the thread. 261 scoped_refptr<WorkerThread> self_; 262 263 mutable CheckedLock thread_lock_; 264 265 // Handle for the thread managed by |this|. 266 PlatformThreadHandle thread_handle_ GUARDED_BY(thread_lock_); 267 268 // The last time this worker was used by its owner (e.g. to process work or 269 // stand as a required idle thread). 270 TimeTicks last_used_time_ GUARDED_BY(thread_lock_); 271 272 // Whether the thread should exit. Set by Cleanup(). 273 AtomicFlag should_exit_; 274 275 const TrackedRef<TaskTracker> task_tracker_; 276 277 // Optional observer notified when a worker enters and exits its main 278 // function. Set in Start() and never modified afterwards. 279 raw_ptr<WorkerThreadObserver> worker_thread_observer_ = nullptr; 280 281 // Desired thread type. 282 const ThreadType thread_type_hint_; 283 284 // Actual thread type. Can be different than |thread_type_hint_| 285 // depending on system capabilities and shutdown state. No lock required 286 // because all post-construction accesses occur on the thread. 287 ThreadType current_thread_type_; 288 289 const size_t sequence_num_; 290 291 // Used to terminate WorkerThread::WakeUp trace event flows. 292 const intptr_t flow_terminator_; 293 294 // Service thread task runner. 295 scoped_refptr<SingleThreadTaskRunner> io_thread_task_runner_; 296 297 const std::unique_ptr<Delegate> delegate_; 298 299 // Set once JoinForTesting() has been called. 300 AtomicFlag join_called_for_testing_; 301 }; 302 303 } // namespace internal 304 } // namespace base 305 306 #endif // BASE_TASK_THREAD_POOL_WORKER_THREAD_H_ 307