1*6dbdd20aSAndroid Build Coastguard Worker /* 2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2020 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 #ifndef SRC_PROFILING_PERF_UNWINDING_H_ 18*6dbdd20aSAndroid Build Coastguard Worker #define SRC_PROFILING_PERF_UNWINDING_H_ 19*6dbdd20aSAndroid Build Coastguard Worker 20*6dbdd20aSAndroid Build Coastguard Worker #include <stdint.h> 21*6dbdd20aSAndroid Build Coastguard Worker #include <condition_variable> 22*6dbdd20aSAndroid Build Coastguard Worker #include <map> 23*6dbdd20aSAndroid Build Coastguard Worker #include <optional> 24*6dbdd20aSAndroid Build Coastguard Worker #include <thread> 25*6dbdd20aSAndroid Build Coastguard Worker 26*6dbdd20aSAndroid Build Coastguard Worker #include <linux/perf_event.h> 27*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Error.h> 28*6dbdd20aSAndroid Build Coastguard Worker 29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/flat_set.h" 30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h" 31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/thread_checker.h" 32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/unix_task_runner.h" 33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/basic_types.h" 34*6dbdd20aSAndroid Build Coastguard Worker #include "src/kallsyms/kernel_symbol_map.h" 35*6dbdd20aSAndroid Build Coastguard Worker #include "src/kallsyms/lazy_kernel_symbolizer.h" 36*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/unwind_support.h" 37*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/common_types.h" 38*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/unwind_queue.h" 39*6dbdd20aSAndroid Build Coastguard Worker 40*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto { 41*6dbdd20aSAndroid Build Coastguard Worker namespace profiling { 42*6dbdd20aSAndroid Build Coastguard Worker 43*6dbdd20aSAndroid Build Coastguard Worker constexpr static uint32_t kUnwindQueueCapacity = 1024; 44*6dbdd20aSAndroid Build Coastguard Worker 45*6dbdd20aSAndroid Build Coastguard Worker // Unwinds and symbolises callstacks. For userspace this uses the sampled stack 46*6dbdd20aSAndroid Build Coastguard Worker // and register state (see |ParsedSample|). For kernelspace, the kernel itself 47*6dbdd20aSAndroid Build Coastguard Worker // unwinds the stack (recording a list of instruction pointers), so only 48*6dbdd20aSAndroid Build Coastguard Worker // symbolisation using /proc/kallsyms is necessary. Has a single unwinding ring 49*6dbdd20aSAndroid Build Coastguard Worker // queue, shared across all data sources. 50*6dbdd20aSAndroid Build Coastguard Worker // 51*6dbdd20aSAndroid Build Coastguard Worker // Userspace samples cannot be unwound without having /proc/<pid>/{maps,mem} 52*6dbdd20aSAndroid Build Coastguard Worker // file descriptors for that process. This lookup can be asynchronous (e.g. on 53*6dbdd20aSAndroid Build Coastguard Worker // Android), so the unwinder might have to wait before it can process (or 54*6dbdd20aSAndroid Build Coastguard Worker // discard) some of the enqueued samples. To avoid blocking the entire queue, 55*6dbdd20aSAndroid Build Coastguard Worker // the unwinder is allowed to process the entries out of order. 56*6dbdd20aSAndroid Build Coastguard Worker // 57*6dbdd20aSAndroid Build Coastguard Worker // Besides the queue, all interactions between the unwinder and the rest of the 58*6dbdd20aSAndroid Build Coastguard Worker // producer logic are through posted tasks. 59*6dbdd20aSAndroid Build Coastguard Worker // 60*6dbdd20aSAndroid Build Coastguard Worker // As unwinding times are long-tailed (example measurements: median <1ms, 61*6dbdd20aSAndroid Build Coastguard Worker // worst-case ~1000ms), the unwinder runs on a dedicated thread to avoid 62*6dbdd20aSAndroid Build Coastguard Worker // starving the rest of the producer's work (including IPC and consumption of 63*6dbdd20aSAndroid Build Coastguard Worker // records from the kernel ring buffers). 64*6dbdd20aSAndroid Build Coastguard Worker // 65*6dbdd20aSAndroid Build Coastguard Worker // This class should not be instantiated directly, use the |UnwinderHandle| 66*6dbdd20aSAndroid Build Coastguard Worker // below instead. 67*6dbdd20aSAndroid Build Coastguard Worker // 68*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): while the inputs to the unwinder are batched as a result of 69*6dbdd20aSAndroid Build Coastguard Worker // the reader posting a wakeup only after consuming a batch of kernel samples, 70*6dbdd20aSAndroid Build Coastguard Worker // the Unwinder might be staggering wakeups for the producer thread by posting a 71*6dbdd20aSAndroid Build Coastguard Worker // task every time a sample has been unwound. Evaluate how bad these wakeups are 72*6dbdd20aSAndroid Build Coastguard Worker // in practice, and consider also implementing a batching strategy for the 73*6dbdd20aSAndroid Build Coastguard Worker // unwinder->serialization handoff (which isn't very latency-sensitive). 74*6dbdd20aSAndroid Build Coastguard Worker class Unwinder { 75*6dbdd20aSAndroid Build Coastguard Worker public: 76*6dbdd20aSAndroid Build Coastguard Worker friend class UnwinderHandle; 77*6dbdd20aSAndroid Build Coastguard Worker 78*6dbdd20aSAndroid Build Coastguard Worker enum class UnwindMode { kUnwindStack, kFramePointer }; 79*6dbdd20aSAndroid Build Coastguard Worker 80*6dbdd20aSAndroid Build Coastguard Worker // Callbacks from the unwinder to the primary producer thread. 81*6dbdd20aSAndroid Build Coastguard Worker class Delegate { 82*6dbdd20aSAndroid Build Coastguard Worker public: 83*6dbdd20aSAndroid Build Coastguard Worker virtual void PostEmitSample(DataSourceInstanceID ds_id, 84*6dbdd20aSAndroid Build Coastguard Worker CompletedSample sample) = 0; 85*6dbdd20aSAndroid Build Coastguard Worker virtual void PostEmitUnwinderSkippedSample(DataSourceInstanceID ds_id, 86*6dbdd20aSAndroid Build Coastguard Worker ParsedSample sample) = 0; 87*6dbdd20aSAndroid Build Coastguard Worker virtual void PostFinishDataSourceStop(DataSourceInstanceID ds_id) = 0; 88*6dbdd20aSAndroid Build Coastguard Worker 89*6dbdd20aSAndroid Build Coastguard Worker virtual ~Delegate(); 90*6dbdd20aSAndroid Build Coastguard Worker }; 91*6dbdd20aSAndroid Build Coastguard Worker ~Unwinder()92*6dbdd20aSAndroid Build Coastguard Worker ~Unwinder() { PERFETTO_DCHECK_THREAD(thread_checker_); } 93*6dbdd20aSAndroid Build Coastguard Worker 94*6dbdd20aSAndroid Build Coastguard Worker void PostStartDataSource(DataSourceInstanceID ds_id, 95*6dbdd20aSAndroid Build Coastguard Worker bool kernel_frames, 96*6dbdd20aSAndroid Build Coastguard Worker UnwindMode unwind_mode); 97*6dbdd20aSAndroid Build Coastguard Worker void PostAdoptProcDescriptors(DataSourceInstanceID ds_id, 98*6dbdd20aSAndroid Build Coastguard Worker pid_t pid, 99*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile maps_fd, 100*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile mem_fd); 101*6dbdd20aSAndroid Build Coastguard Worker void PostRecordTimedOutProcDescriptors(DataSourceInstanceID ds_id, pid_t pid); 102*6dbdd20aSAndroid Build Coastguard Worker void PostRecordNoUserspaceProcess(DataSourceInstanceID ds_id, pid_t pid); 103*6dbdd20aSAndroid Build Coastguard Worker void PostProcessQueue(); 104*6dbdd20aSAndroid Build Coastguard Worker void PostInitiateDataSourceStop(DataSourceInstanceID ds_id); 105*6dbdd20aSAndroid Build Coastguard Worker void PostPurgeDataSource(DataSourceInstanceID ds_id); 106*6dbdd20aSAndroid Build Coastguard Worker 107*6dbdd20aSAndroid Build Coastguard Worker void PostClearCachedStatePeriodic(DataSourceInstanceID ds_id, 108*6dbdd20aSAndroid Build Coastguard Worker uint32_t period_ms); 109*6dbdd20aSAndroid Build Coastguard Worker unwind_queue()110*6dbdd20aSAndroid Build Coastguard Worker UnwindQueue<UnwindEntry, kUnwindQueueCapacity>& unwind_queue() { 111*6dbdd20aSAndroid Build Coastguard Worker return unwind_queue_; 112*6dbdd20aSAndroid Build Coastguard Worker } 113*6dbdd20aSAndroid Build Coastguard Worker GetEnqueuedFootprint()114*6dbdd20aSAndroid Build Coastguard Worker uint64_t GetEnqueuedFootprint() { 115*6dbdd20aSAndroid Build Coastguard Worker uint64_t freed = 116*6dbdd20aSAndroid Build Coastguard Worker footprint_tracker_.stack_bytes_freed.load(std::memory_order_acquire); 117*6dbdd20aSAndroid Build Coastguard Worker uint64_t allocated = footprint_tracker_.stack_bytes_allocated.load( 118*6dbdd20aSAndroid Build Coastguard Worker std::memory_order_relaxed); 119*6dbdd20aSAndroid Build Coastguard Worker 120*6dbdd20aSAndroid Build Coastguard Worker // overflow not a concern in practice 121*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(allocated >= freed); 122*6dbdd20aSAndroid Build Coastguard Worker return allocated - freed; 123*6dbdd20aSAndroid Build Coastguard Worker } 124*6dbdd20aSAndroid Build Coastguard Worker IncrementEnqueuedFootprint(uint64_t increment)125*6dbdd20aSAndroid Build Coastguard Worker void IncrementEnqueuedFootprint(uint64_t increment) { 126*6dbdd20aSAndroid Build Coastguard Worker footprint_tracker_.stack_bytes_allocated.fetch_add( 127*6dbdd20aSAndroid Build Coastguard Worker increment, std::memory_order_relaxed); 128*6dbdd20aSAndroid Build Coastguard Worker } 129*6dbdd20aSAndroid Build Coastguard Worker 130*6dbdd20aSAndroid Build Coastguard Worker private: 131*6dbdd20aSAndroid Build Coastguard Worker struct ProcessState { 132*6dbdd20aSAndroid Build Coastguard Worker // kInitial: unwinder waiting for more info on the process (proc-fds, their 133*6dbdd20aSAndroid Build Coastguard Worker // lookup expiration, or that there is no need for them). 134*6dbdd20aSAndroid Build Coastguard Worker // kFdsResolved: proc-fds available, can unwind samples. 135*6dbdd20aSAndroid Build Coastguard Worker // kFdsTimedOut: proc-fd lookup timed out, will discard samples. Can still 136*6dbdd20aSAndroid Build Coastguard Worker // transition to kFdsResolved if the fds are received later. 137*6dbdd20aSAndroid Build Coastguard Worker // kNoUserspace: only handling kernel callchains (the sample might 138*6dbdd20aSAndroid Build Coastguard Worker // still be for a userspace process), can process samples. 139*6dbdd20aSAndroid Build Coastguard Worker enum class Status { kInitial, kFdsResolved, kFdsTimedOut, kNoUserspace }; 140*6dbdd20aSAndroid Build Coastguard Worker 141*6dbdd20aSAndroid Build Coastguard Worker Status status = Status::kInitial; 142*6dbdd20aSAndroid Build Coastguard Worker // Present iff status == kFdsResolved. 143*6dbdd20aSAndroid Build Coastguard Worker std::optional<UnwindingMetadata> unwind_state; 144*6dbdd20aSAndroid Build Coastguard Worker // Used to distinguish first-time unwinding attempts for a process, for 145*6dbdd20aSAndroid Build Coastguard Worker // logging purposes. 146*6dbdd20aSAndroid Build Coastguard Worker bool attempted_unwinding = false; 147*6dbdd20aSAndroid Build Coastguard Worker }; 148*6dbdd20aSAndroid Build Coastguard Worker 149*6dbdd20aSAndroid Build Coastguard Worker struct DataSourceState { 150*6dbdd20aSAndroid Build Coastguard Worker enum class Status { kActive, kShuttingDown }; DataSourceStateDataSourceState151*6dbdd20aSAndroid Build Coastguard Worker explicit DataSourceState(UnwindMode _unwind_mode) 152*6dbdd20aSAndroid Build Coastguard Worker : unwind_mode(_unwind_mode) {} 153*6dbdd20aSAndroid Build Coastguard Worker 154*6dbdd20aSAndroid Build Coastguard Worker Status status = Status::kActive; 155*6dbdd20aSAndroid Build Coastguard Worker const UnwindMode unwind_mode; 156*6dbdd20aSAndroid Build Coastguard Worker std::map<pid_t, ProcessState> process_states; 157*6dbdd20aSAndroid Build Coastguard Worker }; 158*6dbdd20aSAndroid Build Coastguard Worker 159*6dbdd20aSAndroid Build Coastguard Worker // Accounting for how much heap memory is attached to the enqueued samples at 160*6dbdd20aSAndroid Build Coastguard Worker // a given time. Read by the main thread, mutated by both threads. 161*6dbdd20aSAndroid Build Coastguard Worker // We track just the heap allocated for the sampled stacks, as it dominates 162*6dbdd20aSAndroid Build Coastguard Worker // the per-sample heap use. 163*6dbdd20aSAndroid Build Coastguard Worker struct QueueFootprintTracker { 164*6dbdd20aSAndroid Build Coastguard Worker std::atomic<uint64_t> stack_bytes_allocated; 165*6dbdd20aSAndroid Build Coastguard Worker std::atomic<uint64_t> stack_bytes_freed; 166*6dbdd20aSAndroid Build Coastguard Worker }; 167*6dbdd20aSAndroid Build Coastguard Worker 168*6dbdd20aSAndroid Build Coastguard Worker // Must be instantiated via the |UnwinderHandle|. 169*6dbdd20aSAndroid Build Coastguard Worker Unwinder(Delegate* delegate, base::UnixTaskRunner* task_runner); 170*6dbdd20aSAndroid Build Coastguard Worker 171*6dbdd20aSAndroid Build Coastguard Worker // Marks the data source as valid and active at the unwinding stage. 172*6dbdd20aSAndroid Build Coastguard Worker // Initializes kernel address symbolization if needed. 173*6dbdd20aSAndroid Build Coastguard Worker void StartDataSource(DataSourceInstanceID ds_id, 174*6dbdd20aSAndroid Build Coastguard Worker bool kernel_frames, 175*6dbdd20aSAndroid Build Coastguard Worker UnwindMode unwind_mode); 176*6dbdd20aSAndroid Build Coastguard Worker 177*6dbdd20aSAndroid Build Coastguard Worker void AdoptProcDescriptors(DataSourceInstanceID ds_id, 178*6dbdd20aSAndroid Build Coastguard Worker pid_t pid, 179*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile maps_fd, 180*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile mem_fd); 181*6dbdd20aSAndroid Build Coastguard Worker void UpdateProcessStateStatus(DataSourceInstanceID ds_id, 182*6dbdd20aSAndroid Build Coastguard Worker pid_t pid, 183*6dbdd20aSAndroid Build Coastguard Worker ProcessState::Status new_status); 184*6dbdd20aSAndroid Build Coastguard Worker 185*6dbdd20aSAndroid Build Coastguard Worker // Primary task. Processes the enqueued samples using 186*6dbdd20aSAndroid Build Coastguard Worker // |ConsumeAndUnwindReadySamples|, and re-evaluates data source state. 187*6dbdd20aSAndroid Build Coastguard Worker void ProcessQueue(); 188*6dbdd20aSAndroid Build Coastguard Worker 189*6dbdd20aSAndroid Build Coastguard Worker // Processes the enqueued samples for which all unwinding inputs are ready. 190*6dbdd20aSAndroid Build Coastguard Worker // Returns the set of data source instances which still have samples pending 191*6dbdd20aSAndroid Build Coastguard Worker // (i.e. waiting on the proc-fds). 192*6dbdd20aSAndroid Build Coastguard Worker base::FlatSet<DataSourceInstanceID> ConsumeAndUnwindReadySamples(); 193*6dbdd20aSAndroid Build Coastguard Worker 194*6dbdd20aSAndroid Build Coastguard Worker CompletedSample UnwindSample(const ParsedSample& sample, 195*6dbdd20aSAndroid Build Coastguard Worker UnwindingMetadata* opt_user_state, 196*6dbdd20aSAndroid Build Coastguard Worker bool pid_unwound_before, 197*6dbdd20aSAndroid Build Coastguard Worker UnwindMode unwind_mode); 198*6dbdd20aSAndroid Build Coastguard Worker 199*6dbdd20aSAndroid Build Coastguard Worker // Returns a list of symbolized kernel frames in the sample (if any). 200*6dbdd20aSAndroid Build Coastguard Worker std::vector<unwindstack::FrameData> SymbolizeKernelCallchain( 201*6dbdd20aSAndroid Build Coastguard Worker const ParsedSample& sample); 202*6dbdd20aSAndroid Build Coastguard Worker 203*6dbdd20aSAndroid Build Coastguard Worker // Marks the data source as shutting down at the unwinding stage. It is known 204*6dbdd20aSAndroid Build Coastguard Worker // that no new samples for this source will be pushed into the queue, but we 205*6dbdd20aSAndroid Build Coastguard Worker // need to delay the unwinder state teardown until all previously-enqueued 206*6dbdd20aSAndroid Build Coastguard Worker // samples for this source are processed. 207*6dbdd20aSAndroid Build Coastguard Worker void InitiateDataSourceStop(DataSourceInstanceID ds_id); 208*6dbdd20aSAndroid Build Coastguard Worker 209*6dbdd20aSAndroid Build Coastguard Worker // Tears down unwinding state for the data source without any outstanding 210*6dbdd20aSAndroid Build Coastguard Worker // samples, and informs the service that it can continue the shutdown 211*6dbdd20aSAndroid Build Coastguard Worker // sequence. 212*6dbdd20aSAndroid Build Coastguard Worker void FinishDataSourceStop(DataSourceInstanceID ds_id); 213*6dbdd20aSAndroid Build Coastguard Worker 214*6dbdd20aSAndroid Build Coastguard Worker // Immediately destroys the data source state, used for abrupt stops. 215*6dbdd20aSAndroid Build Coastguard Worker void PurgeDataSource(DataSourceInstanceID ds_id); 216*6dbdd20aSAndroid Build Coastguard Worker DecrementEnqueuedFootprint(uint64_t decrement)217*6dbdd20aSAndroid Build Coastguard Worker void DecrementEnqueuedFootprint(uint64_t decrement) { 218*6dbdd20aSAndroid Build Coastguard Worker footprint_tracker_.stack_bytes_freed.fetch_add(decrement, 219*6dbdd20aSAndroid Build Coastguard Worker std::memory_order_relaxed); 220*6dbdd20aSAndroid Build Coastguard Worker } 221*6dbdd20aSAndroid Build Coastguard Worker 222*6dbdd20aSAndroid Build Coastguard Worker // Clears the parsed maps for all previously-sampled processes, and resets the 223*6dbdd20aSAndroid Build Coastguard Worker // libunwindstack cache. This has the effect of deallocating the cached Elf 224*6dbdd20aSAndroid Build Coastguard Worker // objects within libunwindstack, which take up non-trivial amounts of memory. 225*6dbdd20aSAndroid Build Coastguard Worker // 226*6dbdd20aSAndroid Build Coastguard Worker // There are two reasons for having this operation: 227*6dbdd20aSAndroid Build Coastguard Worker // * over a longer trace, it's desireable to drop heavy state for processes 228*6dbdd20aSAndroid Build Coastguard Worker // that haven't been sampled recently. 229*6dbdd20aSAndroid Build Coastguard Worker // * since libunwindstack's cache is not bounded, it'll tend towards having 230*6dbdd20aSAndroid Build Coastguard Worker // state for all processes that are targeted by the profiling config. 231*6dbdd20aSAndroid Build Coastguard Worker // Clearing the cache periodically helps keep its footprint closer to the 232*6dbdd20aSAndroid Build Coastguard Worker // actual working set (NB: which might still be arbitrarily big, depending 233*6dbdd20aSAndroid Build Coastguard Worker // on the profiling config). 234*6dbdd20aSAndroid Build Coastguard Worker // 235*6dbdd20aSAndroid Build Coastguard Worker // After this function completes, the next unwind for each process will 236*6dbdd20aSAndroid Build Coastguard Worker // therefore incur a guaranteed maps reparse. 237*6dbdd20aSAndroid Build Coastguard Worker // 238*6dbdd20aSAndroid Build Coastguard Worker // Unwinding for concurrent data sources will *not* be directly affected at 239*6dbdd20aSAndroid Build Coastguard Worker // the time of writing, as the non-cleared parsed maps will keep the cached 240*6dbdd20aSAndroid Build Coastguard Worker // Elf objects alive through shared_ptrs. 241*6dbdd20aSAndroid Build Coastguard Worker // 242*6dbdd20aSAndroid Build Coastguard Worker // Note that this operation is heavy in terms of cpu%, and should therefore 243*6dbdd20aSAndroid Build Coastguard Worker // be called only for profiling configs that require it. 244*6dbdd20aSAndroid Build Coastguard Worker // 245*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): dropping the full parsed maps is somewhat excessive, could 246*6dbdd20aSAndroid Build Coastguard Worker // instead clear just the |MapInfo.elf| shared_ptr, but that's considered too 247*6dbdd20aSAndroid Build Coastguard Worker // brittle as it's an implementation detail of libunwindstack. 248*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): improve libunwindstack cache's architecture (it is still 249*6dbdd20aSAndroid Build Coastguard Worker // worth having at the moment to speed up unwinds across map reparses). 250*6dbdd20aSAndroid Build Coastguard Worker void ClearCachedStatePeriodic(DataSourceInstanceID ds_id, uint32_t period_ms); 251*6dbdd20aSAndroid Build Coastguard Worker 252*6dbdd20aSAndroid Build Coastguard Worker void ResetAndEnableUnwindstackCache(); 253*6dbdd20aSAndroid Build Coastguard Worker 254*6dbdd20aSAndroid Build Coastguard Worker base::UnixTaskRunner* const task_runner_; 255*6dbdd20aSAndroid Build Coastguard Worker Delegate* const delegate_; 256*6dbdd20aSAndroid Build Coastguard Worker UnwindQueue<UnwindEntry, kUnwindQueueCapacity> unwind_queue_; 257*6dbdd20aSAndroid Build Coastguard Worker QueueFootprintTracker footprint_tracker_; 258*6dbdd20aSAndroid Build Coastguard Worker std::map<DataSourceInstanceID, DataSourceState> data_sources_; 259*6dbdd20aSAndroid Build Coastguard Worker LazyKernelSymbolizer kernel_symbolizer_; 260*6dbdd20aSAndroid Build Coastguard Worker 261*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_THREAD_CHECKER(thread_checker_) 262*6dbdd20aSAndroid Build Coastguard Worker }; 263*6dbdd20aSAndroid Build Coastguard Worker 264*6dbdd20aSAndroid Build Coastguard Worker // Owning resource handle for an |Unwinder| with a dedicated task thread. 265*6dbdd20aSAndroid Build Coastguard Worker // Ensures that the |Unwinder| is constructed and destructed on the task thread. 266*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): update base::ThreadTaskRunner to allow for this pattern of 267*6dbdd20aSAndroid Build Coastguard Worker // owned state, and consolidate. 268*6dbdd20aSAndroid Build Coastguard Worker class UnwinderHandle { 269*6dbdd20aSAndroid Build Coastguard Worker public: UnwinderHandle(Unwinder::Delegate * delegate)270*6dbdd20aSAndroid Build Coastguard Worker explicit UnwinderHandle(Unwinder::Delegate* delegate) { 271*6dbdd20aSAndroid Build Coastguard Worker std::mutex init_lock; 272*6dbdd20aSAndroid Build Coastguard Worker std::condition_variable init_cv; 273*6dbdd20aSAndroid Build Coastguard Worker 274*6dbdd20aSAndroid Build Coastguard Worker std::function<void(base::UnixTaskRunner*, Unwinder*)> initializer = 275*6dbdd20aSAndroid Build Coastguard Worker [this, &init_lock, &init_cv](base::UnixTaskRunner* task_runner, 276*6dbdd20aSAndroid Build Coastguard Worker Unwinder* unwinder) { 277*6dbdd20aSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(init_lock); 278*6dbdd20aSAndroid Build Coastguard Worker task_runner_ = task_runner; 279*6dbdd20aSAndroid Build Coastguard Worker unwinder_ = unwinder; 280*6dbdd20aSAndroid Build Coastguard Worker // Notify while still holding the lock, as init_cv ceases to exist as 281*6dbdd20aSAndroid Build Coastguard Worker // soon as the main thread observes a non-null task_runner_, and it 282*6dbdd20aSAndroid Build Coastguard Worker // can wake up spuriously (i.e. before the notify if we had unlocked 283*6dbdd20aSAndroid Build Coastguard Worker // before notifying). 284*6dbdd20aSAndroid Build Coastguard Worker init_cv.notify_one(); 285*6dbdd20aSAndroid Build Coastguard Worker }; 286*6dbdd20aSAndroid Build Coastguard Worker 287*6dbdd20aSAndroid Build Coastguard Worker thread_ = std::thread(&UnwinderHandle::RunTaskThread, this, 288*6dbdd20aSAndroid Build Coastguard Worker std::move(initializer), delegate); 289*6dbdd20aSAndroid Build Coastguard Worker 290*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(init_lock); 291*6dbdd20aSAndroid Build Coastguard Worker init_cv.wait(lock, [this] { return !!task_runner_ && !!unwinder_; }); 292*6dbdd20aSAndroid Build Coastguard Worker } 293*6dbdd20aSAndroid Build Coastguard Worker ~UnwinderHandle()294*6dbdd20aSAndroid Build Coastguard Worker ~UnwinderHandle() { 295*6dbdd20aSAndroid Build Coastguard Worker if (task_runner_) { 296*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(!task_runner_->QuitCalled()); 297*6dbdd20aSAndroid Build Coastguard Worker task_runner_->Quit(); 298*6dbdd20aSAndroid Build Coastguard Worker 299*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(thread_.joinable()); 300*6dbdd20aSAndroid Build Coastguard Worker } 301*6dbdd20aSAndroid Build Coastguard Worker if (thread_.joinable()) 302*6dbdd20aSAndroid Build Coastguard Worker thread_.join(); 303*6dbdd20aSAndroid Build Coastguard Worker } 304*6dbdd20aSAndroid Build Coastguard Worker 305*6dbdd20aSAndroid Build Coastguard Worker Unwinder* operator->() { return unwinder_; } 306*6dbdd20aSAndroid Build Coastguard Worker 307*6dbdd20aSAndroid Build Coastguard Worker private: RunTaskThread(std::function<void (base::UnixTaskRunner *,Unwinder *)> initializer,Unwinder::Delegate * delegate)308*6dbdd20aSAndroid Build Coastguard Worker void RunTaskThread( 309*6dbdd20aSAndroid Build Coastguard Worker std::function<void(base::UnixTaskRunner*, Unwinder*)> initializer, 310*6dbdd20aSAndroid Build Coastguard Worker Unwinder::Delegate* delegate) { 311*6dbdd20aSAndroid Build Coastguard Worker base::UnixTaskRunner task_runner; 312*6dbdd20aSAndroid Build Coastguard Worker Unwinder unwinder(delegate, &task_runner); 313*6dbdd20aSAndroid Build Coastguard Worker task_runner.PostTask( 314*6dbdd20aSAndroid Build Coastguard Worker std::bind(std::move(initializer), &task_runner, &unwinder)); 315*6dbdd20aSAndroid Build Coastguard Worker task_runner.Run(); 316*6dbdd20aSAndroid Build Coastguard Worker } 317*6dbdd20aSAndroid Build Coastguard Worker 318*6dbdd20aSAndroid Build Coastguard Worker std::thread thread_; 319*6dbdd20aSAndroid Build Coastguard Worker base::UnixTaskRunner* task_runner_ = nullptr; 320*6dbdd20aSAndroid Build Coastguard Worker Unwinder* unwinder_ = nullptr; 321*6dbdd20aSAndroid Build Coastguard Worker }; 322*6dbdd20aSAndroid Build Coastguard Worker 323*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling 324*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto 325*6dbdd20aSAndroid Build Coastguard Worker 326*6dbdd20aSAndroid Build Coastguard Worker #endif // SRC_PROFILING_PERF_UNWINDING_H_ 327