xref: /aosp_15_r20/external/perfetto/src/base/unix_task_runner.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/platform.h"
20*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/unix_task_runner.h"
21*6dbdd20aSAndroid Build Coastguard Worker 
22*6dbdd20aSAndroid Build Coastguard Worker #include <errno.h>
23*6dbdd20aSAndroid Build Coastguard Worker #include <stdlib.h>
24*6dbdd20aSAndroid Build Coastguard Worker 
25*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
26*6dbdd20aSAndroid Build Coastguard Worker #include <Windows.h>
27*6dbdd20aSAndroid Build Coastguard Worker #include <synchapi.h>
28*6dbdd20aSAndroid Build Coastguard Worker #else
29*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
30*6dbdd20aSAndroid Build Coastguard Worker #endif
31*6dbdd20aSAndroid Build Coastguard Worker 
32*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
33*6dbdd20aSAndroid Build Coastguard Worker #include <limits>
34*6dbdd20aSAndroid Build Coastguard Worker 
35*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/watchdog.h"
36*6dbdd20aSAndroid Build Coastguard Worker 
37*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
38*6dbdd20aSAndroid Build Coastguard Worker namespace base {
39*6dbdd20aSAndroid Build Coastguard Worker 
UnixTaskRunner()40*6dbdd20aSAndroid Build Coastguard Worker UnixTaskRunner::UnixTaskRunner() {
41*6dbdd20aSAndroid Build Coastguard Worker   AddFileDescriptorWatch(event_.fd(), [] {
42*6dbdd20aSAndroid Build Coastguard Worker     // Not reached -- see PostFileDescriptorWatches().
43*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DFATAL("Should be unreachable.");
44*6dbdd20aSAndroid Build Coastguard Worker   });
45*6dbdd20aSAndroid Build Coastguard Worker }
46*6dbdd20aSAndroid Build Coastguard Worker 
47*6dbdd20aSAndroid Build Coastguard Worker UnixTaskRunner::~UnixTaskRunner() = default;
48*6dbdd20aSAndroid Build Coastguard Worker 
WakeUp()49*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::WakeUp() {
50*6dbdd20aSAndroid Build Coastguard Worker   event_.Notify();
51*6dbdd20aSAndroid Build Coastguard Worker }
52*6dbdd20aSAndroid Build Coastguard Worker 
Run()53*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::Run() {
54*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK_THREAD(thread_checker_);
55*6dbdd20aSAndroid Build Coastguard Worker   created_thread_id_.store(GetThreadId(), std::memory_order_relaxed);
56*6dbdd20aSAndroid Build Coastguard Worker   {
57*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
58*6dbdd20aSAndroid Build Coastguard Worker     quit_ = false;
59*6dbdd20aSAndroid Build Coastguard Worker   }
60*6dbdd20aSAndroid Build Coastguard Worker   for (;;) {
61*6dbdd20aSAndroid Build Coastguard Worker     int poll_timeout_ms;
62*6dbdd20aSAndroid Build Coastguard Worker     {
63*6dbdd20aSAndroid Build Coastguard Worker       std::lock_guard<std::mutex> lock(lock_);
64*6dbdd20aSAndroid Build Coastguard Worker       if (quit_)
65*6dbdd20aSAndroid Build Coastguard Worker         return;
66*6dbdd20aSAndroid Build Coastguard Worker       poll_timeout_ms = GetDelayMsToNextTaskLocked();
67*6dbdd20aSAndroid Build Coastguard Worker       UpdateWatchTasksLocked();
68*6dbdd20aSAndroid Build Coastguard Worker     }
69*6dbdd20aSAndroid Build Coastguard Worker 
70*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
71*6dbdd20aSAndroid Build Coastguard Worker     DWORD timeout =
72*6dbdd20aSAndroid Build Coastguard Worker         poll_timeout_ms >= 0 ? static_cast<DWORD>(poll_timeout_ms) : INFINITE;
73*6dbdd20aSAndroid Build Coastguard Worker     DWORD ret =
74*6dbdd20aSAndroid Build Coastguard Worker         WaitForMultipleObjects(static_cast<DWORD>(poll_fds_.size()),
75*6dbdd20aSAndroid Build Coastguard Worker                                &poll_fds_[0], /*bWaitAll=*/false, timeout);
76*6dbdd20aSAndroid Build Coastguard Worker     // Unlike poll(2), WaitForMultipleObjects() returns only *one* handle in the
77*6dbdd20aSAndroid Build Coastguard Worker     // set, even when >1 is signalled. In order to avoid starvation,
78*6dbdd20aSAndroid Build Coastguard Worker     // PostFileDescriptorWatches() will WaitForSingleObject() each other handle
79*6dbdd20aSAndroid Build Coastguard Worker     // to ensure fairness. |ret| here is passed just to avoid an extra
80*6dbdd20aSAndroid Build Coastguard Worker     // WaitForSingleObject() for the one handle that WaitForMultipleObject()
81*6dbdd20aSAndroid Build Coastguard Worker     // returned.
82*6dbdd20aSAndroid Build Coastguard Worker     PostFileDescriptorWatches(ret);
83*6dbdd20aSAndroid Build Coastguard Worker #else
84*6dbdd20aSAndroid Build Coastguard Worker     platform::BeforeMaybeBlockingSyscall();
85*6dbdd20aSAndroid Build Coastguard Worker     int ret = PERFETTO_EINTR(poll(
86*6dbdd20aSAndroid Build Coastguard Worker         &poll_fds_[0], static_cast<nfds_t>(poll_fds_.size()), poll_timeout_ms));
87*6dbdd20aSAndroid Build Coastguard Worker     platform::AfterMaybeBlockingSyscall();
88*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(ret >= 0);
89*6dbdd20aSAndroid Build Coastguard Worker     PostFileDescriptorWatches(0 /*ignored*/);
90*6dbdd20aSAndroid Build Coastguard Worker #endif
91*6dbdd20aSAndroid Build Coastguard Worker 
92*6dbdd20aSAndroid Build Coastguard Worker     // To avoid starvation we always interleave all types of tasks -- immediate,
93*6dbdd20aSAndroid Build Coastguard Worker     // delayed and file descriptor watches.
94*6dbdd20aSAndroid Build Coastguard Worker     RunImmediateAndDelayedTask();
95*6dbdd20aSAndroid Build Coastguard Worker   }
96*6dbdd20aSAndroid Build Coastguard Worker }
97*6dbdd20aSAndroid Build Coastguard Worker 
Quit()98*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::Quit() {
99*6dbdd20aSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(lock_);
100*6dbdd20aSAndroid Build Coastguard Worker   quit_ = true;
101*6dbdd20aSAndroid Build Coastguard Worker   WakeUp();
102*6dbdd20aSAndroid Build Coastguard Worker }
103*6dbdd20aSAndroid Build Coastguard Worker 
QuitCalled()104*6dbdd20aSAndroid Build Coastguard Worker bool UnixTaskRunner::QuitCalled() {
105*6dbdd20aSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(lock_);
106*6dbdd20aSAndroid Build Coastguard Worker   return quit_;
107*6dbdd20aSAndroid Build Coastguard Worker }
108*6dbdd20aSAndroid Build Coastguard Worker 
IsIdleForTesting()109*6dbdd20aSAndroid Build Coastguard Worker bool UnixTaskRunner::IsIdleForTesting() {
110*6dbdd20aSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(lock_);
111*6dbdd20aSAndroid Build Coastguard Worker   return immediate_tasks_.empty();
112*6dbdd20aSAndroid Build Coastguard Worker }
113*6dbdd20aSAndroid Build Coastguard Worker 
AdvanceTimeForTesting(uint32_t ms)114*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::AdvanceTimeForTesting(uint32_t ms) {
115*6dbdd20aSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(lock_);
116*6dbdd20aSAndroid Build Coastguard Worker   advanced_time_for_testing_ += TimeMillis(ms);
117*6dbdd20aSAndroid Build Coastguard Worker }
118*6dbdd20aSAndroid Build Coastguard Worker 
UpdateWatchTasksLocked()119*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::UpdateWatchTasksLocked() {
120*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK_THREAD(thread_checker_);
121*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
122*6dbdd20aSAndroid Build Coastguard Worker   if (!watch_tasks_changed_)
123*6dbdd20aSAndroid Build Coastguard Worker     return;
124*6dbdd20aSAndroid Build Coastguard Worker   watch_tasks_changed_ = false;
125*6dbdd20aSAndroid Build Coastguard Worker #endif
126*6dbdd20aSAndroid Build Coastguard Worker   poll_fds_.clear();
127*6dbdd20aSAndroid Build Coastguard Worker   for (auto& it : watch_tasks_) {
128*6dbdd20aSAndroid Build Coastguard Worker     PlatformHandle handle = it.first;
129*6dbdd20aSAndroid Build Coastguard Worker     WatchTask& watch_task = it.second;
130*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
131*6dbdd20aSAndroid Build Coastguard Worker     if (!watch_task.pending)
132*6dbdd20aSAndroid Build Coastguard Worker       poll_fds_.push_back(handle);
133*6dbdd20aSAndroid Build Coastguard Worker #else
134*6dbdd20aSAndroid Build Coastguard Worker     watch_task.poll_fd_index = poll_fds_.size();
135*6dbdd20aSAndroid Build Coastguard Worker     poll_fds_.push_back({handle, POLLIN | POLLHUP, 0});
136*6dbdd20aSAndroid Build Coastguard Worker #endif
137*6dbdd20aSAndroid Build Coastguard Worker   }
138*6dbdd20aSAndroid Build Coastguard Worker }
139*6dbdd20aSAndroid Build Coastguard Worker 
RunImmediateAndDelayedTask()140*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::RunImmediateAndDelayedTask() {
141*6dbdd20aSAndroid Build Coastguard Worker   // If locking overhead becomes an issue, add a separate work queue.
142*6dbdd20aSAndroid Build Coastguard Worker   std::function<void()> immediate_task;
143*6dbdd20aSAndroid Build Coastguard Worker   std::function<void()> delayed_task;
144*6dbdd20aSAndroid Build Coastguard Worker   TimeMillis now = GetWallTimeMs();
145*6dbdd20aSAndroid Build Coastguard Worker   {
146*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
147*6dbdd20aSAndroid Build Coastguard Worker     if (!immediate_tasks_.empty()) {
148*6dbdd20aSAndroid Build Coastguard Worker       immediate_task = std::move(immediate_tasks_.front());
149*6dbdd20aSAndroid Build Coastguard Worker       immediate_tasks_.pop_front();
150*6dbdd20aSAndroid Build Coastguard Worker     }
151*6dbdd20aSAndroid Build Coastguard Worker     if (!delayed_tasks_.empty()) {
152*6dbdd20aSAndroid Build Coastguard Worker       auto it = delayed_tasks_.begin();
153*6dbdd20aSAndroid Build Coastguard Worker       if (now + advanced_time_for_testing_ >= it->first) {
154*6dbdd20aSAndroid Build Coastguard Worker         delayed_task = std::move(it->second);
155*6dbdd20aSAndroid Build Coastguard Worker         delayed_tasks_.erase(it);
156*6dbdd20aSAndroid Build Coastguard Worker       }
157*6dbdd20aSAndroid Build Coastguard Worker     }
158*6dbdd20aSAndroid Build Coastguard Worker   }
159*6dbdd20aSAndroid Build Coastguard Worker 
160*6dbdd20aSAndroid Build Coastguard Worker   errno = 0;
161*6dbdd20aSAndroid Build Coastguard Worker   if (immediate_task)
162*6dbdd20aSAndroid Build Coastguard Worker     RunTaskWithWatchdogGuard(immediate_task);
163*6dbdd20aSAndroid Build Coastguard Worker   errno = 0;
164*6dbdd20aSAndroid Build Coastguard Worker   if (delayed_task)
165*6dbdd20aSAndroid Build Coastguard Worker     RunTaskWithWatchdogGuard(delayed_task);
166*6dbdd20aSAndroid Build Coastguard Worker }
167*6dbdd20aSAndroid Build Coastguard Worker 
PostFileDescriptorWatches(uint64_t windows_wait_result)168*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::PostFileDescriptorWatches(uint64_t windows_wait_result) {
169*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK_THREAD(thread_checker_);
170*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < poll_fds_.size(); i++) {
171*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
172*6dbdd20aSAndroid Build Coastguard Worker     const PlatformHandle handle = poll_fds_[i];
173*6dbdd20aSAndroid Build Coastguard Worker     // |windows_wait_result| is the result of WaitForMultipleObjects() call. If
174*6dbdd20aSAndroid Build Coastguard Worker     // one of the objects was signalled, it will have a value between
175*6dbdd20aSAndroid Build Coastguard Worker     // [0, poll_fds_.size()].
176*6dbdd20aSAndroid Build Coastguard Worker     if (i != windows_wait_result &&
177*6dbdd20aSAndroid Build Coastguard Worker         WaitForSingleObject(handle, 0) != WAIT_OBJECT_0) {
178*6dbdd20aSAndroid Build Coastguard Worker       continue;
179*6dbdd20aSAndroid Build Coastguard Worker     }
180*6dbdd20aSAndroid Build Coastguard Worker #else
181*6dbdd20aSAndroid Build Coastguard Worker     base::ignore_result(windows_wait_result);
182*6dbdd20aSAndroid Build Coastguard Worker     const PlatformHandle handle = poll_fds_[i].fd;
183*6dbdd20aSAndroid Build Coastguard Worker     if (!(poll_fds_[i].revents & (POLLIN | POLLHUP)))
184*6dbdd20aSAndroid Build Coastguard Worker       continue;
185*6dbdd20aSAndroid Build Coastguard Worker     poll_fds_[i].revents = 0;
186*6dbdd20aSAndroid Build Coastguard Worker #endif
187*6dbdd20aSAndroid Build Coastguard Worker 
188*6dbdd20aSAndroid Build Coastguard Worker     // The wake-up event is handled inline to avoid an infinite recursion of
189*6dbdd20aSAndroid Build Coastguard Worker     // posted tasks.
190*6dbdd20aSAndroid Build Coastguard Worker     if (handle == event_.fd()) {
191*6dbdd20aSAndroid Build Coastguard Worker       event_.Clear();
192*6dbdd20aSAndroid Build Coastguard Worker       continue;
193*6dbdd20aSAndroid Build Coastguard Worker     }
194*6dbdd20aSAndroid Build Coastguard Worker 
195*6dbdd20aSAndroid Build Coastguard Worker     // Binding to |this| is safe since we are the only object executing the
196*6dbdd20aSAndroid Build Coastguard Worker     // task.
197*6dbdd20aSAndroid Build Coastguard Worker     PostTask(std::bind(&UnixTaskRunner::RunFileDescriptorWatch, this, handle));
198*6dbdd20aSAndroid Build Coastguard Worker 
199*6dbdd20aSAndroid Build Coastguard Worker     // Flag the task as pending.
200*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
201*6dbdd20aSAndroid Build Coastguard Worker     // On Windows this is done by marking the WatchTask entry as pending. This
202*6dbdd20aSAndroid Build Coastguard Worker     // is more expensive than Linux as requires rebuilding the |poll_fds_|
203*6dbdd20aSAndroid Build Coastguard Worker     // vector on each call. There doesn't seem to be a good alternative though.
204*6dbdd20aSAndroid Build Coastguard Worker     auto it = watch_tasks_.find(handle);
205*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(it != watch_tasks_.end());
206*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(!it->second.pending);
207*6dbdd20aSAndroid Build Coastguard Worker     it->second.pending = true;
208*6dbdd20aSAndroid Build Coastguard Worker #else
209*6dbdd20aSAndroid Build Coastguard Worker     // On UNIX systems instead, we just make the fd negative while its task is
210*6dbdd20aSAndroid Build Coastguard Worker     // pending. This makes poll(2) ignore the fd.
211*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(poll_fds_[i].fd >= 0);
212*6dbdd20aSAndroid Build Coastguard Worker     poll_fds_[i].fd = -poll_fds_[i].fd;
213*6dbdd20aSAndroid Build Coastguard Worker #endif
214*6dbdd20aSAndroid Build Coastguard Worker   }
215*6dbdd20aSAndroid Build Coastguard Worker }
216*6dbdd20aSAndroid Build Coastguard Worker 
RunFileDescriptorWatch(PlatformHandle fd)217*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::RunFileDescriptorWatch(PlatformHandle fd) {
218*6dbdd20aSAndroid Build Coastguard Worker   std::function<void()> task;
219*6dbdd20aSAndroid Build Coastguard Worker   {
220*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
221*6dbdd20aSAndroid Build Coastguard Worker     auto it = watch_tasks_.find(fd);
222*6dbdd20aSAndroid Build Coastguard Worker     if (it == watch_tasks_.end())
223*6dbdd20aSAndroid Build Coastguard Worker       return;
224*6dbdd20aSAndroid Build Coastguard Worker     WatchTask& watch_task = it->second;
225*6dbdd20aSAndroid Build Coastguard Worker 
226*6dbdd20aSAndroid Build Coastguard Worker     // Make poll(2) pay attention to the fd again. Since another thread may have
227*6dbdd20aSAndroid Build Coastguard Worker     // updated this watch we need to refresh the set first.
228*6dbdd20aSAndroid Build Coastguard Worker     UpdateWatchTasksLocked();
229*6dbdd20aSAndroid Build Coastguard Worker 
230*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
231*6dbdd20aSAndroid Build Coastguard Worker     // On Windows we manually track the presence of outstanding tasks for the
232*6dbdd20aSAndroid Build Coastguard Worker     // watch. The UpdateWatchTasksLocked() in the Run() loop will re-add the
233*6dbdd20aSAndroid Build Coastguard Worker     // task to the |poll_fds_| vector.
234*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(watch_task.pending);
235*6dbdd20aSAndroid Build Coastguard Worker     watch_task.pending = false;
236*6dbdd20aSAndroid Build Coastguard Worker #else
237*6dbdd20aSAndroid Build Coastguard Worker     size_t fd_index = watch_task.poll_fd_index;
238*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(fd_index < poll_fds_.size());
239*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(::abs(poll_fds_[fd_index].fd) == fd);
240*6dbdd20aSAndroid Build Coastguard Worker     poll_fds_[fd_index].fd = fd;
241*6dbdd20aSAndroid Build Coastguard Worker #endif
242*6dbdd20aSAndroid Build Coastguard Worker     task = watch_task.callback;
243*6dbdd20aSAndroid Build Coastguard Worker   }
244*6dbdd20aSAndroid Build Coastguard Worker   errno = 0;
245*6dbdd20aSAndroid Build Coastguard Worker   RunTaskWithWatchdogGuard(task);
246*6dbdd20aSAndroid Build Coastguard Worker }
247*6dbdd20aSAndroid Build Coastguard Worker 
GetDelayMsToNextTaskLocked() const248*6dbdd20aSAndroid Build Coastguard Worker int UnixTaskRunner::GetDelayMsToNextTaskLocked() const {
249*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK_THREAD(thread_checker_);
250*6dbdd20aSAndroid Build Coastguard Worker   if (!immediate_tasks_.empty())
251*6dbdd20aSAndroid Build Coastguard Worker     return 0;
252*6dbdd20aSAndroid Build Coastguard Worker   if (!delayed_tasks_.empty()) {
253*6dbdd20aSAndroid Build Coastguard Worker     TimeMillis diff = delayed_tasks_.begin()->first - GetWallTimeMs() -
254*6dbdd20aSAndroid Build Coastguard Worker                       advanced_time_for_testing_;
255*6dbdd20aSAndroid Build Coastguard Worker     return std::max(0, static_cast<int>(diff.count()));
256*6dbdd20aSAndroid Build Coastguard Worker   }
257*6dbdd20aSAndroid Build Coastguard Worker   return -1;
258*6dbdd20aSAndroid Build Coastguard Worker }
259*6dbdd20aSAndroid Build Coastguard Worker 
PostTask(std::function<void ()> task)260*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::PostTask(std::function<void()> task) {
261*6dbdd20aSAndroid Build Coastguard Worker   bool was_empty;
262*6dbdd20aSAndroid Build Coastguard Worker   {
263*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
264*6dbdd20aSAndroid Build Coastguard Worker     was_empty = immediate_tasks_.empty();
265*6dbdd20aSAndroid Build Coastguard Worker     immediate_tasks_.push_back(std::move(task));
266*6dbdd20aSAndroid Build Coastguard Worker   }
267*6dbdd20aSAndroid Build Coastguard Worker   if (was_empty)
268*6dbdd20aSAndroid Build Coastguard Worker     WakeUp();
269*6dbdd20aSAndroid Build Coastguard Worker }
270*6dbdd20aSAndroid Build Coastguard Worker 
PostDelayedTask(std::function<void ()> task,uint32_t delay_ms)271*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::PostDelayedTask(std::function<void()> task,
272*6dbdd20aSAndroid Build Coastguard Worker                                      uint32_t delay_ms) {
273*6dbdd20aSAndroid Build Coastguard Worker   TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms);
274*6dbdd20aSAndroid Build Coastguard Worker   {
275*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
276*6dbdd20aSAndroid Build Coastguard Worker     delayed_tasks_.insert(
277*6dbdd20aSAndroid Build Coastguard Worker         std::make_pair(runtime + advanced_time_for_testing_, std::move(task)));
278*6dbdd20aSAndroid Build Coastguard Worker   }
279*6dbdd20aSAndroid Build Coastguard Worker   WakeUp();
280*6dbdd20aSAndroid Build Coastguard Worker }
281*6dbdd20aSAndroid Build Coastguard Worker 
AddFileDescriptorWatch(PlatformHandle fd,std::function<void ()> task)282*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::AddFileDescriptorWatch(PlatformHandle fd,
283*6dbdd20aSAndroid Build Coastguard Worker                                             std::function<void()> task) {
284*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(PlatformHandleChecker::IsValid(fd));
285*6dbdd20aSAndroid Build Coastguard Worker   {
286*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
287*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(!watch_tasks_.count(fd));
288*6dbdd20aSAndroid Build Coastguard Worker     WatchTask& watch_task = watch_tasks_[fd];
289*6dbdd20aSAndroid Build Coastguard Worker     watch_task.callback = std::move(task);
290*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
291*6dbdd20aSAndroid Build Coastguard Worker     watch_task.pending = false;
292*6dbdd20aSAndroid Build Coastguard Worker #else
293*6dbdd20aSAndroid Build Coastguard Worker     watch_task.poll_fd_index = SIZE_MAX;
294*6dbdd20aSAndroid Build Coastguard Worker #endif
295*6dbdd20aSAndroid Build Coastguard Worker     watch_tasks_changed_ = true;
296*6dbdd20aSAndroid Build Coastguard Worker   }
297*6dbdd20aSAndroid Build Coastguard Worker   WakeUp();
298*6dbdd20aSAndroid Build Coastguard Worker }
299*6dbdd20aSAndroid Build Coastguard Worker 
RemoveFileDescriptorWatch(PlatformHandle fd)300*6dbdd20aSAndroid Build Coastguard Worker void UnixTaskRunner::RemoveFileDescriptorWatch(PlatformHandle fd) {
301*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(PlatformHandleChecker::IsValid(fd));
302*6dbdd20aSAndroid Build Coastguard Worker   {
303*6dbdd20aSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(lock_);
304*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(watch_tasks_.count(fd));
305*6dbdd20aSAndroid Build Coastguard Worker     watch_tasks_.erase(fd);
306*6dbdd20aSAndroid Build Coastguard Worker     watch_tasks_changed_ = true;
307*6dbdd20aSAndroid Build Coastguard Worker   }
308*6dbdd20aSAndroid Build Coastguard Worker   // No need to schedule a wake-up for this.
309*6dbdd20aSAndroid Build Coastguard Worker }
310*6dbdd20aSAndroid Build Coastguard Worker 
RunsTasksOnCurrentThread() const311*6dbdd20aSAndroid Build Coastguard Worker bool UnixTaskRunner::RunsTasksOnCurrentThread() const {
312*6dbdd20aSAndroid Build Coastguard Worker   return GetThreadId() == created_thread_id_.load(std::memory_order_relaxed);
313*6dbdd20aSAndroid Build Coastguard Worker }
314*6dbdd20aSAndroid Build Coastguard Worker 
315*6dbdd20aSAndroid Build Coastguard Worker }  // namespace base
316*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
317