xref: /aosp_15_r20/external/cronet/base/tracing/perfetto_task_runner.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/tracing/perfetto_task_runner.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/auto_reset.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/task/common/checked_lock_impl.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/task/common/scoped_defer_task_posting.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool/thread_pool_instance.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/tracing/tracing_tls.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker namespace tracing {
26*6777b538SAndroid Build Coastguard Worker 
PerfettoTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner)27*6777b538SAndroid Build Coastguard Worker PerfettoTaskRunner::PerfettoTaskRunner(
28*6777b538SAndroid Build Coastguard Worker     scoped_refptr<base::SequencedTaskRunner> task_runner)
29*6777b538SAndroid Build Coastguard Worker     : task_runner_(std::move(task_runner)) {}
30*6777b538SAndroid Build Coastguard Worker 
~PerfettoTaskRunner()31*6777b538SAndroid Build Coastguard Worker PerfettoTaskRunner::~PerfettoTaskRunner() {
32*6777b538SAndroid Build Coastguard Worker   DCHECK(GetOrCreateTaskRunner()->RunsTasksInCurrentSequence());
33*6777b538SAndroid Build Coastguard Worker #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
34*6777b538SAndroid Build Coastguard Worker   fd_controllers_.clear();
35*6777b538SAndroid Build Coastguard Worker #endif  // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker 
PostTask(std::function<void ()> task)38*6777b538SAndroid Build Coastguard Worker void PerfettoTaskRunner::PostTask(std::function<void()> task) {
39*6777b538SAndroid Build Coastguard Worker   PostDelayedTask(task, /* delay_ms */ 0);
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker 
PostDelayedTask(std::function<void ()> task,uint32_t delay_ms)42*6777b538SAndroid Build Coastguard Worker void PerfettoTaskRunner::PostDelayedTask(std::function<void()> task,
43*6777b538SAndroid Build Coastguard Worker                                          uint32_t delay_ms) {
44*6777b538SAndroid Build Coastguard Worker   base::ScopedDeferTaskPosting::PostOrDefer(
45*6777b538SAndroid Build Coastguard Worker       GetOrCreateTaskRunner(), FROM_HERE,
46*6777b538SAndroid Build Coastguard Worker       base::BindOnce(
47*6777b538SAndroid Build Coastguard Worker           [](std::function<void()> task) {
48*6777b538SAndroid Build Coastguard Worker             // We block any trace events that happens while any
49*6777b538SAndroid Build Coastguard Worker             // Perfetto task is running, or we'll get deadlocks in
50*6777b538SAndroid Build Coastguard Worker             // situations where the StartupTraceWriterRegistry tries
51*6777b538SAndroid Build Coastguard Worker             // to bind a writer which in turn causes a PostTask where
52*6777b538SAndroid Build Coastguard Worker             // a trace event can be emitted, which then deadlocks as
53*6777b538SAndroid Build Coastguard Worker             // it needs a new chunk from the same StartupTraceWriter
54*6777b538SAndroid Build Coastguard Worker             // which we're trying to bind and are keeping the lock
55*6777b538SAndroid Build Coastguard Worker             // to.
56*6777b538SAndroid Build Coastguard Worker             // TODO(oysteine): Try to see if we can be more selective
57*6777b538SAndroid Build Coastguard Worker             // about this.
58*6777b538SAndroid Build Coastguard Worker             const AutoReset<bool> resetter(GetThreadIsInTraceEvent(), true,
59*6777b538SAndroid Build Coastguard Worker                                            false);
60*6777b538SAndroid Build Coastguard Worker             task();
61*6777b538SAndroid Build Coastguard Worker           },
62*6777b538SAndroid Build Coastguard Worker           task),
63*6777b538SAndroid Build Coastguard Worker       base::Milliseconds(delay_ms));
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
RunsTasksOnCurrentThread() const66*6777b538SAndroid Build Coastguard Worker bool PerfettoTaskRunner::RunsTasksOnCurrentThread() const {
67*6777b538SAndroid Build Coastguard Worker   DCHECK(task_runner_);
68*6777b538SAndroid Build Coastguard Worker   return task_runner_->RunsTasksInCurrentSequence();
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker // PlatformHandle is an int on POSIX, a HANDLE on Windows.
AddFileDescriptorWatch(perfetto::base::PlatformHandle fd,std::function<void ()> callback)72*6777b538SAndroid Build Coastguard Worker void PerfettoTaskRunner::AddFileDescriptorWatch(
73*6777b538SAndroid Build Coastguard Worker     perfetto::base::PlatformHandle fd,
74*6777b538SAndroid Build Coastguard Worker     std::function<void()> callback) {
75*6777b538SAndroid Build Coastguard Worker #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
76*6777b538SAndroid Build Coastguard Worker   DCHECK(GetOrCreateTaskRunner()->RunsTasksInCurrentSequence());
77*6777b538SAndroid Build Coastguard Worker   DCHECK(!base::Contains(fd_controllers_, fd));
78*6777b538SAndroid Build Coastguard Worker   // Set up the |fd| in the map to signal intent to add a watch. We need to
79*6777b538SAndroid Build Coastguard Worker   // PostTask the WatchReadable creation because if we do it in this task we'll
80*6777b538SAndroid Build Coastguard Worker   // race with perfetto setting up the connection on this task and the IO thread
81*6777b538SAndroid Build Coastguard Worker   // setting up epoll on the |fd|. Using a CancelableOnceClosure ensures that
82*6777b538SAndroid Build Coastguard Worker   // the |fd| won't be added for watch if RemoveFileDescriptorWatch is called.
83*6777b538SAndroid Build Coastguard Worker   fd_controllers_[fd].callback.Reset(
84*6777b538SAndroid Build Coastguard Worker       base::BindOnce(
85*6777b538SAndroid Build Coastguard Worker           [](PerfettoTaskRunner* perfetto_runner, int fd,
86*6777b538SAndroid Build Coastguard Worker              std::function<void()> callback) {
87*6777b538SAndroid Build Coastguard Worker             DCHECK(perfetto_runner->GetOrCreateTaskRunner()
88*6777b538SAndroid Build Coastguard Worker                        ->RunsTasksInCurrentSequence());
89*6777b538SAndroid Build Coastguard Worker             // When this callback runs, we must not have removed |fd|'s watch.
90*6777b538SAndroid Build Coastguard Worker             CHECK(base::Contains(perfetto_runner->fd_controllers_, fd));
91*6777b538SAndroid Build Coastguard Worker             auto& controller_and_cb = perfetto_runner->fd_controllers_[fd];
92*6777b538SAndroid Build Coastguard Worker             // We should never overwrite an existing watch.
93*6777b538SAndroid Build Coastguard Worker             CHECK(!controller_and_cb.controller);
94*6777b538SAndroid Build Coastguard Worker             controller_and_cb.controller =
95*6777b538SAndroid Build Coastguard Worker                 base::FileDescriptorWatcher::WatchReadable(
96*6777b538SAndroid Build Coastguard Worker                     fd, base::BindRepeating(
97*6777b538SAndroid Build Coastguard Worker                             [](std::function<void()> callback) { callback(); },
98*6777b538SAndroid Build Coastguard Worker                             std::move(callback)));
99*6777b538SAndroid Build Coastguard Worker           },
100*6777b538SAndroid Build Coastguard Worker           base::Unretained(this), fd, std::move(callback)));
101*6777b538SAndroid Build Coastguard Worker   task_runner_->PostTask(FROM_HERE, fd_controllers_[fd].callback.callback());
102*6777b538SAndroid Build Coastguard Worker #else   // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
103*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
104*6777b538SAndroid Build Coastguard Worker #endif  // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
105*6777b538SAndroid Build Coastguard Worker }
106*6777b538SAndroid Build Coastguard Worker 
RemoveFileDescriptorWatch(perfetto::base::PlatformHandle fd)107*6777b538SAndroid Build Coastguard Worker void PerfettoTaskRunner::RemoveFileDescriptorWatch(
108*6777b538SAndroid Build Coastguard Worker     perfetto::base::PlatformHandle fd) {
109*6777b538SAndroid Build Coastguard Worker #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
110*6777b538SAndroid Build Coastguard Worker   DCHECK(GetOrCreateTaskRunner()->RunsTasksInCurrentSequence());
111*6777b538SAndroid Build Coastguard Worker   DCHECK(base::Contains(fd_controllers_, fd));
112*6777b538SAndroid Build Coastguard Worker   // This also cancels the base::FileDescriptorWatcher::WatchReadable() task if
113*6777b538SAndroid Build Coastguard Worker   // it's pending.
114*6777b538SAndroid Build Coastguard Worker   fd_controllers_.erase(fd);
115*6777b538SAndroid Build Coastguard Worker #else   // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
116*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
117*6777b538SAndroid Build Coastguard Worker #endif  // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker 
ResetTaskRunnerForTesting(scoped_refptr<base::SequencedTaskRunner> task_runner)120*6777b538SAndroid Build Coastguard Worker void PerfettoTaskRunner::ResetTaskRunnerForTesting(
121*6777b538SAndroid Build Coastguard Worker     scoped_refptr<base::SequencedTaskRunner> task_runner) {
122*6777b538SAndroid Build Coastguard Worker   task_runner_ = std::move(task_runner);
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
SetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner)125*6777b538SAndroid Build Coastguard Worker void PerfettoTaskRunner::SetTaskRunner(
126*6777b538SAndroid Build Coastguard Worker     scoped_refptr<base::SequencedTaskRunner> task_runner) {
127*6777b538SAndroid Build Coastguard Worker   DCHECK(!task_runner_);
128*6777b538SAndroid Build Coastguard Worker   task_runner_ = std::move(task_runner);
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner>
GetOrCreateTaskRunner()132*6777b538SAndroid Build Coastguard Worker PerfettoTaskRunner::GetOrCreateTaskRunner() {
133*6777b538SAndroid Build Coastguard Worker   // TODO(eseckler): This is not really thread-safe. We should probably add a
134*6777b538SAndroid Build Coastguard Worker   // lock around this. At the moment we can get away without one because this
135*6777b538SAndroid Build Coastguard Worker   // method is called for the first time on the process's main thread before the
136*6777b538SAndroid Build Coastguard Worker   // tracing service connects.
137*6777b538SAndroid Build Coastguard Worker   if (!task_runner_) {
138*6777b538SAndroid Build Coastguard Worker     DCHECK(base::ThreadPoolInstance::Get());
139*6777b538SAndroid Build Coastguard Worker     task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
140*6777b538SAndroid Build Coastguard Worker         {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
141*6777b538SAndroid Build Coastguard Worker   }
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker   return task_runner_;
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
147*6777b538SAndroid Build Coastguard Worker PerfettoTaskRunner::FDControllerAndCallback::FDControllerAndCallback() =
148*6777b538SAndroid Build Coastguard Worker     default;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker PerfettoTaskRunner::FDControllerAndCallback::~FDControllerAndCallback() =
151*6777b538SAndroid Build Coastguard Worker     default;
152*6777b538SAndroid Build Coastguard Worker #endif  // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker }  // namespace tracing
155*6777b538SAndroid Build Coastguard Worker }  // namespace base
156