1*6dbdd20aSAndroid Build Coastguard Worker /* 2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2018 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_MEMORY_UNWINDING_H_ 18*6dbdd20aSAndroid Build Coastguard Worker #define SRC_PROFILING_MEMORY_UNWINDING_H_ 19*6dbdd20aSAndroid Build Coastguard Worker 20*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Regs.h> 21*6dbdd20aSAndroid Build Coastguard Worker 22*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h" 23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/scoped_file.h" 24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/thread_task_runner.h" 25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/basic_types.h" 26*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/unwind_support.h" 27*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/bookkeeping.h" 28*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/unwound_messages.h" 29*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/wire_protocol.h" 30*6dbdd20aSAndroid Build Coastguard Worker 31*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto { 32*6dbdd20aSAndroid Build Coastguard Worker namespace profiling { 33*6dbdd20aSAndroid Build Coastguard Worker 34*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::Regs> CreateRegsFromRawData( 35*6dbdd20aSAndroid Build Coastguard Worker unwindstack::ArchEnum arch, 36*6dbdd20aSAndroid Build Coastguard Worker void* raw_data); 37*6dbdd20aSAndroid Build Coastguard Worker 38*6dbdd20aSAndroid Build Coastguard Worker bool DoUnwind(WireMessage*, UnwindingMetadata* metadata, AllocRecord* out); 39*6dbdd20aSAndroid Build Coastguard Worker 40*6dbdd20aSAndroid Build Coastguard Worker // AllocRecords are expensive to construct and destruct. We have seen up to 41*6dbdd20aSAndroid Build Coastguard Worker // 10 % of total CPU of heapprofd being used to destruct them. That is why 42*6dbdd20aSAndroid Build Coastguard Worker // we re-use them to cut CPU usage significantly. 43*6dbdd20aSAndroid Build Coastguard Worker class AllocRecordArena { 44*6dbdd20aSAndroid Build Coastguard Worker public: AllocRecordArena()45*6dbdd20aSAndroid Build Coastguard Worker AllocRecordArena() : alloc_records_mutex_(new std::mutex()) {} 46*6dbdd20aSAndroid Build Coastguard Worker 47*6dbdd20aSAndroid Build Coastguard Worker void ReturnAllocRecord(std::unique_ptr<AllocRecord>); 48*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<AllocRecord> BorrowAllocRecord(); 49*6dbdd20aSAndroid Build Coastguard Worker 50*6dbdd20aSAndroid Build Coastguard Worker void Enable(); 51*6dbdd20aSAndroid Build Coastguard Worker void Disable(); 52*6dbdd20aSAndroid Build Coastguard Worker 53*6dbdd20aSAndroid Build Coastguard Worker private: 54*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<std::mutex> alloc_records_mutex_; 55*6dbdd20aSAndroid Build Coastguard Worker std::vector<std::unique_ptr<AllocRecord>> alloc_records_; 56*6dbdd20aSAndroid Build Coastguard Worker bool enabled_ = true; 57*6dbdd20aSAndroid Build Coastguard Worker }; 58*6dbdd20aSAndroid Build Coastguard Worker 59*6dbdd20aSAndroid Build Coastguard Worker class UnwindingWorker : public base::UnixSocket::EventListener { 60*6dbdd20aSAndroid Build Coastguard Worker public: 61*6dbdd20aSAndroid Build Coastguard Worker class Delegate { 62*6dbdd20aSAndroid Build Coastguard Worker public: 63*6dbdd20aSAndroid Build Coastguard Worker virtual void PostAllocRecord(UnwindingWorker*, 64*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<AllocRecord>) = 0; 65*6dbdd20aSAndroid Build Coastguard Worker virtual void PostFreeRecord(UnwindingWorker*, std::vector<FreeRecord>) = 0; 66*6dbdd20aSAndroid Build Coastguard Worker virtual void PostHeapNameRecord(UnwindingWorker*, HeapNameRecord rec) = 0; 67*6dbdd20aSAndroid Build Coastguard Worker virtual void PostSocketDisconnected(UnwindingWorker*, 68*6dbdd20aSAndroid Build Coastguard Worker DataSourceInstanceID, 69*6dbdd20aSAndroid Build Coastguard Worker pid_t pid, 70*6dbdd20aSAndroid Build Coastguard Worker SharedRingBuffer::Stats stats) = 0; 71*6dbdd20aSAndroid Build Coastguard Worker virtual void PostDrainDone(UnwindingWorker*, DataSourceInstanceID) = 0; 72*6dbdd20aSAndroid Build Coastguard Worker virtual ~Delegate(); 73*6dbdd20aSAndroid Build Coastguard Worker }; 74*6dbdd20aSAndroid Build Coastguard Worker 75*6dbdd20aSAndroid Build Coastguard Worker struct HandoffData { 76*6dbdd20aSAndroid Build Coastguard Worker DataSourceInstanceID data_source_instance_id; 77*6dbdd20aSAndroid Build Coastguard Worker base::UnixSocketRaw sock; 78*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile maps_fd; 79*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile mem_fd; 80*6dbdd20aSAndroid Build Coastguard Worker SharedRingBuffer shmem; 81*6dbdd20aSAndroid Build Coastguard Worker ClientConfiguration client_config; 82*6dbdd20aSAndroid Build Coastguard Worker bool stream_allocations; 83*6dbdd20aSAndroid Build Coastguard Worker }; 84*6dbdd20aSAndroid Build Coastguard Worker UnwindingWorker(Delegate * delegate,base::ThreadTaskRunner thread_task_runner)85*6dbdd20aSAndroid Build Coastguard Worker UnwindingWorker(Delegate* delegate, base::ThreadTaskRunner thread_task_runner) 86*6dbdd20aSAndroid Build Coastguard Worker : delegate_(delegate), 87*6dbdd20aSAndroid Build Coastguard Worker thread_task_runner_(std::move(thread_task_runner)) {} 88*6dbdd20aSAndroid Build Coastguard Worker 89*6dbdd20aSAndroid Build Coastguard Worker ~UnwindingWorker() override; 90*6dbdd20aSAndroid Build Coastguard Worker UnwindingWorker(UnwindingWorker&&) = default; 91*6dbdd20aSAndroid Build Coastguard Worker 92*6dbdd20aSAndroid Build Coastguard Worker // Public API safe to call from other threads. 93*6dbdd20aSAndroid Build Coastguard Worker void PostDisconnectSocket(pid_t pid); 94*6dbdd20aSAndroid Build Coastguard Worker void PostPurgeProcess(pid_t pid); 95*6dbdd20aSAndroid Build Coastguard Worker void PostHandoffSocket(HandoffData); 96*6dbdd20aSAndroid Build Coastguard Worker void PostDrainFree(DataSourceInstanceID, pid_t pid); ReturnAllocRecord(std::unique_ptr<AllocRecord> record)97*6dbdd20aSAndroid Build Coastguard Worker void ReturnAllocRecord(std::unique_ptr<AllocRecord> record) { 98*6dbdd20aSAndroid Build Coastguard Worker alloc_record_arena_.ReturnAllocRecord(std::move(record)); 99*6dbdd20aSAndroid Build Coastguard Worker } 100*6dbdd20aSAndroid Build Coastguard Worker 101*6dbdd20aSAndroid Build Coastguard Worker // Implementation of UnixSocket::EventListener. 102*6dbdd20aSAndroid Build Coastguard Worker // Do not call explicitly. 103*6dbdd20aSAndroid Build Coastguard Worker void OnDisconnect(base::UnixSocket* self) override; OnNewIncomingConnection(base::UnixSocket *,std::unique_ptr<base::UnixSocket>)104*6dbdd20aSAndroid Build Coastguard Worker void OnNewIncomingConnection(base::UnixSocket*, 105*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<base::UnixSocket>) override { 106*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DFATAL_OR_ELOG("This should not happen."); 107*6dbdd20aSAndroid Build Coastguard Worker } 108*6dbdd20aSAndroid Build Coastguard Worker void OnDataAvailable(base::UnixSocket* self) override; 109*6dbdd20aSAndroid Build Coastguard Worker 110*6dbdd20aSAndroid Build Coastguard Worker public: 111*6dbdd20aSAndroid Build Coastguard Worker // public for testing/fuzzer 112*6dbdd20aSAndroid Build Coastguard Worker struct ClientData { 113*6dbdd20aSAndroid Build Coastguard Worker DataSourceInstanceID data_source_instance_id; 114*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<base::UnixSocket> sock; 115*6dbdd20aSAndroid Build Coastguard Worker UnwindingMetadata metadata; 116*6dbdd20aSAndroid Build Coastguard Worker SharedRingBuffer shmem; 117*6dbdd20aSAndroid Build Coastguard Worker ClientConfiguration client_config; 118*6dbdd20aSAndroid Build Coastguard Worker bool stream_allocations = false; 119*6dbdd20aSAndroid Build Coastguard Worker size_t drain_bytes = 0; 120*6dbdd20aSAndroid Build Coastguard Worker std::vector<FreeRecord> free_records; 121*6dbdd20aSAndroid Build Coastguard Worker }; 122*6dbdd20aSAndroid Build Coastguard Worker 123*6dbdd20aSAndroid Build Coastguard Worker // public for testing/fuzzing 124*6dbdd20aSAndroid Build Coastguard Worker static void HandleBuffer(UnwindingWorker* self, 125*6dbdd20aSAndroid Build Coastguard Worker AllocRecordArena* alloc_record_arena, 126*6dbdd20aSAndroid Build Coastguard Worker const SharedRingBuffer::Buffer& buf, 127*6dbdd20aSAndroid Build Coastguard Worker ClientData* client_data, 128*6dbdd20aSAndroid Build Coastguard Worker pid_t peer_pid, 129*6dbdd20aSAndroid Build Coastguard Worker Delegate* delegate); 130*6dbdd20aSAndroid Build Coastguard Worker 131*6dbdd20aSAndroid Build Coastguard Worker private: 132*6dbdd20aSAndroid Build Coastguard Worker void HandleHandoffSocket(HandoffData data); 133*6dbdd20aSAndroid Build Coastguard Worker void HandleDisconnectSocket(pid_t pid); 134*6dbdd20aSAndroid Build Coastguard Worker void HandleDrainFree(DataSourceInstanceID, pid_t); 135*6dbdd20aSAndroid Build Coastguard Worker void RemoveClientData( 136*6dbdd20aSAndroid Build Coastguard Worker std::map<pid_t, ClientData>::iterator client_data_iterator); 137*6dbdd20aSAndroid Build Coastguard Worker void FinishDisconnect( 138*6dbdd20aSAndroid Build Coastguard Worker std::map<pid_t, ClientData>::iterator client_data_iterator); 139*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<AllocRecord> BorrowAllocRecord(); 140*6dbdd20aSAndroid Build Coastguard Worker 141*6dbdd20aSAndroid Build Coastguard Worker struct ReadAndUnwindBatchResult { 142*6dbdd20aSAndroid Build Coastguard Worker enum class Status { 143*6dbdd20aSAndroid Build Coastguard Worker kHasMore, 144*6dbdd20aSAndroid Build Coastguard Worker kReadSome, 145*6dbdd20aSAndroid Build Coastguard Worker kReadNone, 146*6dbdd20aSAndroid Build Coastguard Worker }; 147*6dbdd20aSAndroid Build Coastguard Worker size_t bytes_read = 0; 148*6dbdd20aSAndroid Build Coastguard Worker Status status; 149*6dbdd20aSAndroid Build Coastguard Worker }; 150*6dbdd20aSAndroid Build Coastguard Worker ReadAndUnwindBatchResult ReadAndUnwindBatch(ClientData* client_data); 151*6dbdd20aSAndroid Build Coastguard Worker void BatchUnwindJob(pid_t); 152*6dbdd20aSAndroid Build Coastguard Worker void DrainJob(pid_t); 153*6dbdd20aSAndroid Build Coastguard Worker 154*6dbdd20aSAndroid Build Coastguard Worker AllocRecordArena alloc_record_arena_; 155*6dbdd20aSAndroid Build Coastguard Worker std::map<pid_t, ClientData> client_data_; 156*6dbdd20aSAndroid Build Coastguard Worker Delegate* delegate_; 157*6dbdd20aSAndroid Build Coastguard Worker 158*6dbdd20aSAndroid Build Coastguard Worker // Task runner with a dedicated thread. Keep last. By destroying this task 159*6dbdd20aSAndroid Build Coastguard Worker // runner first, we ensure that the UnwindingWorker is not active while the 160*6dbdd20aSAndroid Build Coastguard Worker // rest of its state is being destroyed. Additionally this ensures that the 161*6dbdd20aSAndroid Build Coastguard Worker // destructing thread sees a consistent view of the memory due to the 162*6dbdd20aSAndroid Build Coastguard Worker // ThreadTaskRunner's destructor joining a thread. 163*6dbdd20aSAndroid Build Coastguard Worker base::ThreadTaskRunner thread_task_runner_; 164*6dbdd20aSAndroid Build Coastguard Worker }; 165*6dbdd20aSAndroid Build Coastguard Worker 166*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling 167*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto 168*6dbdd20aSAndroid Build Coastguard Worker 169*6dbdd20aSAndroid Build Coastguard Worker #endif // SRC_PROFILING_MEMORY_UNWINDING_H_ 170