sequence_manager_impl.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // Copyright 2018 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. #ifndef BASE_TASK_SEQUENCE_MANAGER_SEQUENCE_MANAGER_IMPL_H_
  5. #define BASE_TASK_SEQUENCE_MANAGER_SEQUENCE_MANAGER_IMPL_H_
  6. #include <deque>
  7. #include <list>
  8. #include <map>
  9. #include <memory>
  10. #include <random>
  11. #include <set>
  12. #include <string>
  13. #include <unordered_map>
  14. #include <utility>
  15. #include "base/atomic_sequence_num.h"
  16. #include "base/cancelable_callback.h"
  17. #include "base/containers/circular_deque.h"
  18. #include "base/debug/crash_logging.h"
  19. #include "base/memory/scoped_refptr.h"
  20. #include "base/memory/weak_ptr.h"
  21. #include "base/message_loop/message_pump_type.h"
  22. #include "base/pending_task.h"
  23. #include "base/run_loop.h"
  24. #include "base/sequenced_task_runner.h"
  25. #include "base/single_thread_task_runner.h"
  26. #include "base/synchronization/lock.h"
  27. #include "base/task/common/task_annotator.h"
  28. #include "base/task/current_thread.h"
  29. #include "base/task/sequence_manager/associated_thread_id.h"
  30. #include "base/task/sequence_manager/enqueue_order.h"
  31. #include "base/task/sequence_manager/enqueue_order_generator.h"
  32. #include "base/task/sequence_manager/sequence_manager.h"
  33. #include "base/task/sequence_manager/task_queue_impl.h"
  34. #include "base/task/sequence_manager/task_queue_selector.h"
  35. #include "base/task/sequence_manager/thread_controller.h"
  36. #include "base/threading/thread_checker.h"
  37. #include "base/time/default_tick_clock.h"
  38. #include "base/values.h"
  39. #include "build/build_config.h"
  40. namespace base {
  41. namespace trace_event {
  42. class ConvertableToTraceFormat;
  43. } // namespace trace_event
  44. namespace sequence_manager {
  45. class SequenceManagerForTest;
  46. class TaskQueue;
  47. class TaskTimeObserver;
  48. class TimeDomain;
  49. namespace internal {
  50. class RealTimeDomain;
  51. class TaskQueueImpl;
  52. class ThreadControllerImpl;
  53. // The task queue manager provides N task queues and a selector interface for
  54. // choosing which task queue to service next. Each task queue consists of two
  55. // sub queues:
  56. //
  57. // 1. Incoming task queue. Tasks that are posted get immediately appended here.
  58. // When a task is appended into an empty incoming queue, the task manager
  59. // work function (DoWork()) is scheduled to run on the main task runner.
  60. //
  61. // 2. Work queue. If a work queue is empty when DoWork() is entered, tasks from
  62. // the incoming task queue (if any) are moved here. The work queues are
  63. // registered with the selector as input to the scheduling decision.
  64. //
  65. class BASE_EXPORT SequenceManagerImpl
  66. : public SequenceManager,
  67. public internal::SequencedTaskSource,
  68. public internal::TaskQueueSelector::Observer,
  69. public RunLoop::NestingObserver {
  70. public:
  71. using Observer = SequenceManager::Observer;
  72. SequenceManagerImpl(const SequenceManagerImpl&) = delete;
  73. SequenceManagerImpl& operator=(const SequenceManagerImpl&) = delete;
  74. ~SequenceManagerImpl() override;
  75. // Assume direct control over current thread and create a SequenceManager.
  76. // This function should be called only once per thread.
  77. // This function assumes that a task execution environment is already
  78. // initialized for the current thread.
  79. static std::unique_ptr<SequenceManagerImpl> CreateOnCurrentThread(
  80. SequenceManager::Settings settings = SequenceManager::Settings());
  81. // Create an unbound SequenceManager (typically for a future thread). The
  82. // SequenceManager can be initialized on the current thread and then needs to
  83. // be bound and initialized on the target thread by calling one of the Bind*()
  84. // methods.
  85. static std::unique_ptr<SequenceManagerImpl> CreateUnbound(
  86. SequenceManager::Settings settings);
  87. // SequenceManager implementation:
  88. void BindToCurrentThread() override;
  89. scoped_refptr<SequencedTaskRunner> GetTaskRunnerForCurrentTask() override;
  90. void BindToMessagePump(std::unique_ptr<MessagePump> message_pump) override;
  91. void SetObserver(Observer* observer) override;
  92. void AddTaskTimeObserver(TaskTimeObserver* task_time_observer) override;
  93. void RemoveTaskTimeObserver(TaskTimeObserver* task_time_observer) override;
  94. void RegisterTimeDomain(TimeDomain* time_domain) override;
  95. void UnregisterTimeDomain(TimeDomain* time_domain) override;
  96. TimeDomain* GetRealTimeDomain() const override;
  97. const TickClock* GetTickClock() const override;
  98. TimeTicks NowTicks() const override;
  99. void SetDefaultTaskRunner(
  100. scoped_refptr<SingleThreadTaskRunner> task_runner) override;
  101. void ReclaimMemory() override;
  102. bool GetAndClearSystemIsQuiescentBit() override;
  103. void SetWorkBatchSize(int work_batch_size) override;
  104. void SetTimerSlack(TimerSlack timer_slack) override;
  105. void EnableCrashKeys(const char* async_stack_crash_key) override;
  106. const MetricRecordingSettings& GetMetricRecordingSettings() const override;
  107. size_t GetPendingTaskCountForTesting() const override;
  108. scoped_refptr<TaskQueue> CreateTaskQueue(
  109. const TaskQueue::Spec& spec) override;
  110. std::string DescribeAllPendingTasks() const override;
  111. std::unique_ptr<NativeWorkHandle> OnNativeWorkPending(
  112. TaskQueue::QueuePriority priority) override;
  113. void AddTaskObserver(TaskObserver* task_observer) override;
  114. void RemoveTaskObserver(TaskObserver* task_observer) override;
  115. // SequencedTaskSource implementation:
  116. Task* SelectNextTask(
  117. SelectTaskOption option = SelectTaskOption::kDefault) override;
  118. void DidRunTask() override;
  119. TimeDelta DelayTillNextTask(
  120. LazyNow* lazy_now,
  121. SelectTaskOption option = SelectTaskOption::kDefault) const override;
  122. bool HasPendingHighResolutionTasks() override;
  123. bool OnSystemIdle() override;
  124. void AddDestructionObserver(
  125. CurrentThread::DestructionObserver* destruction_observer);
  126. void RemoveDestructionObserver(
  127. CurrentThread::DestructionObserver* destruction_observer);
  128. // TODO(alexclarke): Remove this as part of https://crbug.com/825327.
  129. void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
  130. // TODO(alexclarke): Remove this as part of https://crbug.com/825327.
  131. scoped_refptr<SingleThreadTaskRunner> GetTaskRunner();
  132. bool IsBoundToCurrentThread() const;
  133. MessagePump* GetMessagePump() const;
  134. bool IsType(MessagePumpType type) const;
  135. void SetAddQueueTimeToTasks(bool enable);
  136. void SetTaskExecutionAllowed(bool allowed);
  137. bool IsTaskExecutionAllowed() const;
  138. #if defined(OS_IOS)
  139. void AttachToMessagePump();
  140. #endif
  141. bool IsIdleForTesting() override;
  142. void BindToCurrentThread(std::unique_ptr<MessagePump> pump);
  143. void DeletePendingTasks();
  144. bool HasTasks();
  145. MessagePumpType GetType() const;
  146. // Requests that a task to process work is scheduled.
  147. void ScheduleWork();
  148. // Requests that a delayed task to process work is posted on the main task
  149. // runner. These delayed tasks are de-duplicated. Must be called on the thread
  150. // this class was created on.
  151. // Schedules next wake-up at the given time, cancels any previous requests.
  152. // Use TimeTicks::Max() to cancel a wake-up.
  153. // Must be called from a TimeDomain only.
  154. void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time);
  155. // Returns the currently executing TaskQueue if any. Must be called on the
  156. // thread this class was created on.
  157. internal::TaskQueueImpl* currently_executing_task_queue() const;
  158. // Unregisters a TaskQueue previously created by |NewTaskQueue()|.
  159. // No tasks will run on this queue after this call.
  160. void UnregisterTaskQueueImpl(
  161. std::unique_ptr<internal::TaskQueueImpl> task_queue);
  162. // Schedule a call to UnregisterTaskQueueImpl as soon as it's safe to do so.
  163. void ShutdownTaskQueueGracefully(
  164. std::unique_ptr<internal::TaskQueueImpl> task_queue);
  165. const scoped_refptr<AssociatedThreadId>& associated_thread() const {
  166. return associated_thread_;
  167. }
  168. const Settings& settings() const { return settings_; }
  169. WeakPtr<SequenceManagerImpl> GetWeakPtr();
  170. // How frequently to perform housekeeping tasks (sweeping canceled tasks etc).
  171. static constexpr TimeDelta kReclaimMemoryInterval =
  172. TimeDelta::FromSeconds(30);
  173. protected:
  174. static std::unique_ptr<ThreadControllerImpl>
  175. CreateThreadControllerImplForCurrentThread(const TickClock* clock);
  176. // Create a task queue manager where |controller| controls the thread
  177. // on which the tasks are eventually run.
  178. SequenceManagerImpl(std::unique_ptr<internal::ThreadController> controller,
  179. SequenceManager::Settings settings = Settings());
  180. friend class internal::TaskQueueImpl;
  181. friend class ::base::sequence_manager::SequenceManagerForTest;
  182. private:
  183. class NativeWorkHandleImpl;
  184. // Returns the SequenceManager running the
  185. // current thread. It must only be used on the thread it was obtained.
  186. // Only to be used by CurrentThread for the moment
  187. static SequenceManagerImpl* GetCurrent();
  188. friend class ::base::CurrentThread;
  189. enum class ProcessTaskResult {
  190. kDeferred,
  191. kExecuted,
  192. kSequenceManagerDeleted,
  193. };
  194. // SequenceManager maintains a queue of non-nestable tasks since they're
  195. // uncommon and allocating an extra deque per TaskQueue will waste the memory.
  196. using NonNestableTaskDeque =
  197. circular_deque<internal::TaskQueueImpl::DeferredNonNestableTask>;
  198. // We have to track rentrancy because we support nested runloops but the
  199. // selector interface is unaware of those. This struct keeps track off all
  200. // task related state needed to make pairs of SelectNextTask() / DidRunTask()
  201. // work.
  202. struct ExecutingTask {
  203. ExecutingTask(Task&& task,
  204. internal::TaskQueueImpl* task_queue,
  205. TaskQueue::TaskTiming task_timing)
  206. : pending_task(std::move(task)),
  207. task_queue(task_queue),
  208. task_queue_name(task_queue->GetName()),
  209. task_timing(task_timing),
  210. priority(task_queue->GetQueuePriority()),
  211. task_type(pending_task.task_type) {}
  212. Task pending_task;
  213. internal::TaskQueueImpl* task_queue = nullptr;
  214. // Save task_queue_name as the task queue can be deleted within the task.
  215. const char* task_queue_name;
  216. TaskQueue::TaskTiming task_timing;
  217. // Save priority as it might change after running a task.
  218. TaskQueue::QueuePriority priority;
  219. // Save task metadata to use in after running a task as |pending_task|
  220. // won't be available then.
  221. int task_type;
  222. };
  223. struct MainThreadOnly {
  224. explicit MainThreadOnly(
  225. const scoped_refptr<AssociatedThreadId>& associated_thread,
  226. const SequenceManager::Settings& settings);
  227. ~MainThreadOnly();
  228. int nesting_depth = 0;
  229. NonNestableTaskDeque non_nestable_task_queue;
  230. // TODO(altimin): Switch to instruction pointer crash key when it's
  231. // available.
  232. debug::CrashKeyString* file_name_crash_key = nullptr;
  233. debug::CrashKeyString* function_name_crash_key = nullptr;
  234. debug::CrashKeyString* async_stack_crash_key = nullptr;
  235. std::array<char, static_cast<size_t>(debug::CrashKeySize::Size64)>
  236. async_stack_buffer = {};
  237. std::mt19937_64 random_generator;
  238. std::uniform_real_distribution<double> uniform_distribution;
  239. internal::TaskQueueSelector selector;
  240. ObserverList<TaskObserver>::Unchecked task_observers;
  241. ObserverList<TaskTimeObserver>::Unchecked task_time_observers;
  242. std::set<TimeDomain*> time_domains;
  243. std::unique_ptr<internal::RealTimeDomain> real_time_domain;
  244. // If true MaybeReclaimMemory will attempt to reclaim memory.
  245. bool memory_reclaim_scheduled = false;
  246. // Used to ensure we don't perform expensive housekeeping too frequently.
  247. TimeTicks next_time_to_reclaim_memory;
  248. // List of task queues managed by this SequenceManager.
  249. // - active_queues contains queues that are still running tasks.
  250. // Most often they are owned by relevant TaskQueues, but
  251. // queues_to_gracefully_shutdown_ are included here too.
  252. // - queues_to_gracefully_shutdown contains queues which should be deleted
  253. // when they become empty.
  254. // - queues_to_delete contains soon-to-be-deleted queues, because some
  255. // internal scheduling code does not expect queues to be pulled
  256. // from underneath.
  257. std::set<internal::TaskQueueImpl*> active_queues;
  258. std::map<internal::TaskQueueImpl*, std::unique_ptr<internal::TaskQueueImpl>>
  259. queues_to_gracefully_shutdown;
  260. std::map<internal::TaskQueueImpl*, std::unique_ptr<internal::TaskQueueImpl>>
  261. queues_to_delete;
  262. bool task_was_run_on_quiescence_monitored_queue = false;
  263. bool nesting_observer_registered_ = false;
  264. // Due to nested runloops more than one task can be executing concurrently.
  265. // Note that this uses std::deque for pointer stability, since pointers to
  266. // objects in this container are stored in TLS.
  267. std::deque<ExecutingTask> task_execution_stack;
  268. Observer* observer = nullptr; // NOT OWNED
  269. ObserverList<CurrentThread::DestructionObserver>::Unchecked
  270. destruction_observers;
  271. // By default native work is not prioritized at all.
  272. std::multiset<TaskQueue::QueuePriority> pending_native_work{
  273. TaskQueue::kBestEffortPriority};
  274. };
  275. void CompleteInitializationOnBoundThread();
  276. // TaskQueueSelector::Observer:
  277. void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) override;
  278. // RunLoop::NestingObserver:
  279. void OnBeginNestedRunLoop() override;
  280. void OnExitNestedRunLoop() override;
  281. // Called by the task queue to inform this SequenceManager of a task that's
  282. // about to be queued. This SequenceManager may use this opportunity to add
  283. // metadata to |pending_task| before it is moved into the queue.
  284. void WillQueueTask(Task* pending_task, const char* task_queue_name);
  285. // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and
  286. // reloads any empty work queues.
  287. void MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now);
  288. void NotifyWillProcessTask(ExecutingTask* task, LazyNow* time_before_task);
  289. void NotifyDidProcessTask(ExecutingTask* task, LazyNow* time_after_task);
  290. EnqueueOrder GetNextSequenceNumber();
  291. bool GetAddQueueTimeToTasks();
  292. std::unique_ptr<trace_event::ConvertableToTraceFormat>
  293. AsValueWithSelectorResultForTracing(internal::WorkQueue* selected_work_queue,
  294. bool force_verbose) const;
  295. Value AsValueWithSelectorResult(internal::WorkQueue* selected_work_queue,
  296. bool force_verbose) const;
  297. // Used in construction of TaskQueueImpl to obtain an AtomicFlag which it can
  298. // use to request reload by ReloadEmptyWorkQueues. The lifetime of
  299. // TaskQueueImpl is managed by this class and the handle will be released by
  300. // TaskQueueImpl::UnregisterTaskQueue which is always called before the
  301. // queue's destruction.
  302. AtomicFlagSet::AtomicFlag GetFlagToRequestReloadForEmptyQueue(
  303. TaskQueueImpl* task_queue);
  304. // Calls |TakeImmediateIncomingQueueTasks| on all queues with their reload
  305. // flag set in |empty_queues_to_reload_|.
  306. void ReloadEmptyWorkQueues() const;
  307. std::unique_ptr<internal::TaskQueueImpl> CreateTaskQueueImpl(
  308. const TaskQueue::Spec& spec) override;
  309. // Periodically reclaims memory by sweeping away canceled tasks and shrinking
  310. // buffers.
  311. void MaybeReclaimMemory();
  312. // Deletes queues marked for deletion and empty queues marked for shutdown.
  313. void CleanUpQueues();
  314. void RemoveAllCanceledTasksFromFrontOfWorkQueues();
  315. TaskQueue::TaskTiming::TimeRecordingPolicy ShouldRecordTaskTiming(
  316. const internal::TaskQueueImpl* task_queue);
  317. bool ShouldRecordCPUTimeForTask();
  318. void RecordCrashKeys(const PendingTask&);
  319. // Helper to terminate all scoped trace events to allow starting new ones
  320. // in SelectNextTask().
  321. Task* SelectNextTaskImpl(SelectTaskOption option);
  322. // Check if a task of priority |priority| should run given the pending set of
  323. // native work.
  324. bool ShouldRunTaskOfPriority(TaskQueue::QueuePriority priority) const;
  325. // Ignores any immediate work.
  326. TimeDelta GetDelayTillNextDelayedTask(LazyNow* lazy_now,
  327. SelectTaskOption option) const;
  328. #if DCHECK_IS_ON()
  329. void LogTaskDebugInfo(const internal::WorkQueue* work_queue) const;
  330. #endif
  331. // Determines if wall time or thread time should be recorded for the next
  332. // task.
  333. TaskQueue::TaskTiming InitializeTaskTiming(
  334. internal::TaskQueueImpl* task_queue);
  335. scoped_refptr<AssociatedThreadId> associated_thread_;
  336. EnqueueOrderGenerator enqueue_order_generator_;
  337. const std::unique_ptr<internal::ThreadController> controller_;
  338. const Settings settings_;
  339. const MetricRecordingSettings metric_recording_settings_;
  340. // Whether to add the queue time to tasks.
  341. base::subtle::Atomic32 add_queue_time_to_tasks_;
  342. AtomicFlagSet empty_queues_to_reload_;
  343. // A check to bail out early during memory corruption.
  344. // https://crbug.com/757940
  345. bool Validate();
  346. volatile int32_t memory_corruption_sentinel_;
  347. MainThreadOnly main_thread_only_;
  348. MainThreadOnly& main_thread_only() {
  349. DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
  350. return main_thread_only_;
  351. }
  352. const MainThreadOnly& main_thread_only() const {
  353. DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
  354. return main_thread_only_;
  355. }
  356. WeakPtrFactory<SequenceManagerImpl> weak_factory_{this};
  357. };
  358. } // namespace internal
  359. } // namespace sequence_manager
  360. } // namespace base
  361. #endif // BASE_TASK_SEQUENCE_MANAGER_SEQUENCE_MANAGER_IMPL_H_