1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_BINDER_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_BINDER_TRACKER_H_ 19 20 #include <stdint.h> 21 #include <optional> 22 #include <stack> 23 24 #include "perfetto/base/flat_set.h" 25 #include "perfetto/ext/base/flat_hash_map.h" 26 #include "src/trace_processor/importers/common/args_tracker.h" 27 #include "src/trace_processor/storage/trace_storage.h" 28 #include "src/trace_processor/types/destructible.h" 29 #include "src/trace_processor/types/trace_processor_context.h" 30 31 namespace perfetto { 32 namespace trace_processor { 33 34 class TraceProcessorContext; 35 36 class BinderTracker : public Destructible { 37 public: 38 // Commands sent from userspace to the kernel binder driver. 39 enum : uint32_t { 40 kBC_TRANSACTION = 0x40406300, 41 kBC_REPLY = 0x40406301, 42 kBC_TRANSACTION_SG = 0x40486311, 43 kBC_REPLY_SG = 0x40486312, 44 }; 45 46 // Return commands sent from the kernel binder driver to userspace. 47 enum : uint32_t { 48 kBR_TRANSACTION_SEC_CTX = 0x80487202, 49 kBR_TRANSACTION = 0x80407202, 50 kBR_REPLY = 0x80407203, 51 kBR_DEAD_REPLY = 0x7205, 52 kBR_TRANSACTION_COMPLETE = 0x7206, 53 kBR_FAILED_REPLY = 0x7211, 54 kBR_FROZEN_REPLY = 0x7212, 55 kBR_TRANSACTION_PENDING_FROZEN = 0x7214, 56 kBR_ONEWAY_SPAM_SUSPECT = 0x7213, 57 }; 58 59 using SetArgsCallback = std::function<void(ArgsTracker::BoundInserter*)>; 60 // Declared public for testing only. 61 explicit BinderTracker(TraceProcessorContext*); 62 BinderTracker(const BinderTracker&) = delete; 63 BinderTracker& operator=(const BinderTracker&) = delete; 64 ~BinderTracker() override; GetOrCreate(TraceProcessorContext * context)65 static BinderTracker* GetOrCreate(TraceProcessorContext* context) { 66 if (!context->binder_tracker) { 67 context->binder_tracker.reset(new BinderTracker(context)); 68 } 69 return static_cast<BinderTracker*>(context->binder_tracker.get()); 70 } 71 72 void Transaction(int64_t timestamp, 73 uint32_t tid, 74 int32_t transaction_id, 75 int32_t dest_node, 76 uint32_t dest_tgid, 77 uint32_t dest_tid, 78 bool is_reply, 79 uint32_t flags, 80 StringId code); 81 void Locked(int64_t timestamp, uint32_t pid); 82 void Lock(int64_t timestamp, uint32_t dest_pid); 83 void Unlock(int64_t timestamp, uint32_t pid); 84 void TransactionReceived(int64_t timestamp, 85 uint32_t tid, 86 int32_t transaction_id); 87 void CommandToKernel(int64_t timestamp, uint32_t tid, uint32_t cmd); 88 void ReturnFromKernel(int64_t timestamp, uint32_t tid, uint32_t cmd); 89 void TransactionAllocBuf(int64_t timestamp, 90 uint32_t pid, 91 uint64_t data_size, 92 uint64_t offsets_size); 93 94 // For testing utid_stacks_empty()95 bool utid_stacks_empty() const { return utid_stacks_.size() == 0; } 96 97 private: 98 TraceProcessorContext* const context_; 99 100 struct OutstandingTransaction { 101 bool is_reply = false; 102 bool is_oneway = false; 103 SetArgsCallback args_inserter; 104 std::optional<TrackId> send_track_id; 105 std::optional<SliceId> send_slice_id; 106 }; 107 // TODO(rsavitski): switch back to FlatHashMap once the latter's perf is fixed 108 // for insert+erase heavy workfloads. 109 std::unordered_map<int32_t, OutstandingTransaction> outstanding_transactions_; 110 111 struct TxnFrame { 112 // The state of this thread at this stack level. 113 enum State : uint32_t; 114 State state; 115 struct TxnInfo { 116 bool is_oneway; 117 bool is_reply; 118 }; 119 std::optional<TxnInfo> txn_info; 120 }; 121 // Each thread can have a stack of multiple transactions. 122 base::FlatHashMap<UniqueTid, std::stack<TxnFrame>> utid_stacks_; 123 124 // Returns the current state of this thread or nullptr, if the thread doesn't 125 // have a binder state. 126 TxnFrame* GetTidTopFrame(uint32_t tid); 127 // Creates a new frame in the stack for this thread. Note: this might 128 // invalidate previously returned TxnFrame*. 129 TxnFrame* PushTidFrame(uint32_t tid); 130 // Removes the current frame for this thread. It's an error to call this if 131 // the thread didn't have a frame. Note: this might invalidate previously 132 // returned TxnFrame*. 133 void PopTidFrame(uint32_t tid); 134 135 base::FlatHashMap<uint32_t, int64_t> attempt_lock_; 136 base::FlatHashMap<uint32_t, int64_t> lock_acquired_; 137 138 const StringId binder_category_id_; 139 const StringId lock_waiting_id_; 140 const StringId lock_held_id_; 141 const StringId transaction_slice_id_; 142 const StringId transaction_async_id_; 143 const StringId reply_id_; 144 const StringId async_rcv_id_; 145 const StringId transaction_id_; 146 const StringId dest_node_; 147 const StringId dest_process_; 148 const StringId dest_thread_; 149 const StringId dest_name_; 150 const StringId is_reply_; 151 const StringId flags_; 152 const StringId code_; 153 const StringId calling_tid_; 154 const StringId data_size_; 155 const StringId offsets_size_; 156 }; 157 158 } // namespace trace_processor 159 } // namespace perfetto 160 161 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_BINDER_TRACKER_H_ 162