1 /* 2 * Copyright (C) 2018 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_COMMON_PROCESS_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_PROCESS_TRACKER_H_ 19 20 #include <cstdint> 21 #include <optional> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <utility> 25 #include <vector> 26 27 #include "perfetto/ext/base/flat_hash_map.h" 28 #include "perfetto/ext/base/string_view.h" 29 #include "src/trace_processor/importers/common/args_tracker.h" 30 #include "src/trace_processor/storage/trace_storage.h" 31 #include "src/trace_processor/types/trace_processor_context.h" 32 33 namespace perfetto { 34 namespace trace_processor { 35 36 // Thread names can come from different sources, and we don't always want to 37 // overwrite the previously set name. This enum determines the priority of 38 // different sources. 39 enum class ThreadNamePriority { 40 kOther = 0, 41 kFtrace = 1, 42 kEtwTrace = 1, 43 kProcessTree = 2, 44 kTrackDescriptorThreadType = 3, 45 kTrackDescriptor = 4, 46 47 // Priority when trace processor hardcodes a name for a process (e.g. calling 48 // the idle thread "swapper" when parsing ftrace). 49 // Keep this last. 50 kTraceProcessorConstant = 5, 51 }; 52 53 class ProcessTracker { 54 public: 55 explicit ProcessTracker(TraceProcessorContext*); 56 ProcessTracker(const ProcessTracker&) = delete; 57 ProcessTracker& operator=(const ProcessTracker&) = delete; 58 virtual ~ProcessTracker(); 59 60 using UniqueThreadIterator = std::vector<UniqueTid>::const_iterator; 61 using UniqueThreadBounds = 62 std::pair<UniqueThreadIterator, UniqueThreadIterator>; 63 64 // TODO(b/110409911): Invalidation of process and threads is yet to be 65 // implemented. This will include passing timestamps into the below methods 66 // to ensure the correct upid/utid is found. 67 68 // Called when a task_newtask is observed. This force the tracker to start 69 // a new UTID for the thread, which is needed for TID-recycling resolution. 70 UniqueTid StartNewThread(std::optional<int64_t> timestamp, uint32_t tid); 71 72 // Returns whether a thread is considered alive by the process tracker. 73 bool IsThreadAlive(UniqueTid utid); 74 75 // Called when sched_process_exit is observed. This forces the tracker to 76 // end the thread lifetime for the utid associated with the given tid. 77 void EndThread(int64_t timestamp, uint32_t tid); 78 79 // Returns the thread utid or std::nullopt if it doesn't exist. 80 std::optional<UniqueTid> GetThreadOrNull(uint32_t tid); 81 82 // Returns the thread utid (or creates a new entry if not present) 83 UniqueTid GetOrCreateThread(uint32_t tid); 84 85 // Assigns the given name to the thread if the new name has a higher priority 86 // than the existing one. Returns the utid of the thread. 87 virtual UniqueTid UpdateThreadName(uint32_t tid, 88 StringId thread_name_id, 89 ThreadNamePriority priority); 90 91 // Assigns the given name to the thread if the new name has a higher priority 92 // than the existing one. The thread is identified by utid. 93 virtual void UpdateThreadNameByUtid(UniqueTid utid, 94 StringId thread_name_id, 95 ThreadNamePriority priority); 96 97 // Called when a thread is seen the process tree. Retrieves the matching utid 98 // for the tid and the matching upid for the tgid and stores both. 99 // Virtual for testing. 100 virtual UniqueTid UpdateThread(uint32_t tid, uint32_t pid); 101 102 // Associates trusted_pid with track UUID. 103 void UpdateTrustedPid(uint32_t trusted_pid, uint64_t uuid); 104 105 // Returns the trusted_pid associated with the track UUID, or std::nullopt if 106 // not found. 107 std::optional<uint32_t> GetTrustedPid(uint64_t uuid); 108 109 // Performs namespace-local to root-level resolution of thread or process id, 110 // given tid (can be root-level or namespace-local, but we don't know 111 // beforehand) and root-level pid/tgid that the thread belongs to. 112 // Returns the root-level thread id for tid on successful resolution; 113 // otherwise, returns std::nullopt on resolution failure, or the thread of 114 // tid isn't running in a pid namespace. 115 std::optional<uint32_t> ResolveNamespacedTid(uint32_t root_level_pid, 116 uint32_t tid); 117 118 // Called when a task_newtask without the CLONE_THREAD flag is observed. 119 // This force the tracker to start both a new UTID and a new UPID. 120 UniquePid StartNewProcess(std::optional<int64_t> timestamp, 121 std::optional<uint32_t> parent_tid, 122 uint32_t pid, 123 StringId main_thread_name, 124 ThreadNamePriority priority); 125 126 // Called when a process is seen in a process tree. Retrieves the UniquePid 127 // for that pid or assigns a new one. 128 // Virtual for testing. 129 virtual UniquePid SetProcessMetadata(uint32_t pid, 130 std::optional<uint32_t> ppid, 131 base::StringView name, 132 base::StringView cmdline); 133 134 // Sets the process user id. 135 void SetProcessUid(UniquePid upid, uint32_t uid); 136 137 // Assigns the given name to the process identified by |upid| if it does not 138 // have a name yet. 139 virtual void SetProcessNameIfUnset(UniquePid upid, StringId process_name_id); 140 141 // Sets the start timestamp to the process identified by |upid| if it doesn't 142 // have a timestamp yet. 143 void SetStartTsIfUnset(UniquePid upid, int64_t start_ts_nanoseconds); 144 145 // Called on a task rename event to set the thread name and possibly process 146 // name (if the tid provided is the main thread of the process). 147 void UpdateThreadNameAndMaybeProcessName(uint32_t tid, 148 StringId thread_name, 149 ThreadNamePriority priority); 150 151 // Called when a process is seen in a process tree. Retrieves the UniquePid 152 // for that pid or assigns a new one. 153 // Virtual for testing. 154 virtual UniquePid GetOrCreateProcess(uint32_t pid); 155 156 // Returns the upid for a given pid. UpidForPidForTesting(uint32_t pid)157 std::optional<UniquePid> UpidForPidForTesting(uint32_t pid) { 158 auto it = pids_.Find(pid); 159 return it ? std::make_optional(*it) : std::nullopt; 160 } 161 162 // Returns the bounds of a range that includes all UniqueTids that have the 163 // requested tid. UtidsForTidForTesting(uint32_t tid)164 UniqueThreadBounds UtidsForTidForTesting(uint32_t tid) { 165 const auto& deque = tids_[tid]; 166 return std::make_pair(deque.begin(), deque.end()); 167 } 168 169 // Marks the two threads as belonging to the same process, even if we don't 170 // know which one yet. If one of the two threads is later mapped to a process, 171 // the other will be mapped to the same process. The order of the two threads 172 // is irrelevant, Associate(A, B) has the same effect of Associate(B, A). 173 void AssociateThreads(UniqueTid, UniqueTid); 174 175 // Creates the mapping from tid 0 <-> utid 0 and pid 0 <-> upid 0. This is 176 // done for Linux-based system traces (proto or ftrace format) as for these 177 // traces, we always have the "swapper" (idle) process having tid/pid 0. 178 void SetPidZeroIsUpidZeroIdleProcess(); 179 180 // Returns a BoundInserter to add arguments to the arg set of a process. 181 // Arguments are flushed into trace storage only after the trace was loaded in 182 // its entirety. 183 ArgsTracker::BoundInserter AddArgsTo(UniquePid upid); 184 185 // Called when the trace was fully loaded. 186 void NotifyEndOfFile(); 187 188 // Tracks the namespace-local pids for a process running in a pid namespace. 189 void UpdateNamespacedProcess(uint32_t pid, std::vector<uint32_t> nspid); 190 191 // Tracks the namespace-local thread ids for a thread running in a pid 192 // namespace. 193 void UpdateNamespacedThread(uint32_t pid, 194 uint32_t tid, 195 std::vector<uint32_t> nstid); 196 197 // The UniqueTid of the swapper thread, is 0 for the default machine and is 198 // > 0 for remote machines. swapper_utid()199 UniqueTid swapper_utid() const { return swapper_utid_; } 200 201 private: 202 // Returns the utid of a thread having |tid| and |pid| as the parent process. 203 // pid == std::nullopt matches all processes. 204 // Returns std::nullopt if such a thread doesn't exist. 205 std::optional<uint32_t> GetThreadOrNull(uint32_t tid, 206 std::optional<uint32_t> pid); 207 208 // Called whenever we discover that the passed thread belongs to the passed 209 // process. The |pending_assocs_| vector is scanned to see if there are any 210 // other threads associated to the passed thread. 211 void ResolvePendingAssociations(UniqueTid, UniquePid); 212 213 // Writes the association that the passed thread belongs to the passed 214 // process. 215 void AssociateThreadToProcess(UniqueTid, UniquePid); 216 217 TraceProcessorContext* const context_; 218 219 ArgsTracker args_tracker_; 220 221 // Mapping for tid to the vector of possible UniqueTids. 222 // TODO(lalitm): this is a one-many mapping because this code was written 223 // before global sorting was a thing so multiple threads could be "active" 224 // simultaneously. This is no longer the case so this should be removed 225 // (though it seems like there are subtle things which break in Chrome if this 226 // changes). 227 base::FlatHashMap<uint32_t /* tid */, std::vector<UniqueTid>> tids_; 228 229 // Mapping of the most recently seen pid to the associated upid. 230 base::FlatHashMap<uint32_t /* pid (aka tgid) */, UniquePid> pids_; 231 232 // Pending thread associations. The meaning of a pair<ThreadA, ThreadB> in 233 // this vector is: we know that A and B belong to the same process, but we 234 // don't know yet which process. A and A are idempotent, as in, pair<A,B> is 235 // equivalent to pair<B,A>. 236 std::vector<std::pair<UniqueTid, UniqueTid>> pending_assocs_; 237 238 // Pending parent process associations. The meaning of pair<ThreadA, ProcessB> 239 // in this vector is: we know that A created process B but we don't know the 240 // process of A. That is, we don't know the parent *process* of B. 241 std::vector<std::pair<UniqueTid, UniquePid>> pending_parent_assocs_; 242 243 // A mapping from utid to the priority of a thread name source. 244 std::vector<ThreadNamePriority> thread_name_priorities_; 245 246 // A mapping from track UUIDs to trusted pids. 247 std::unordered_map<uint64_t, uint32_t> trusted_pids_; 248 249 struct NamespacedThread { 250 uint32_t pid; // Root-level pid. 251 uint32_t tid; // Root-level tid. 252 std::vector<uint32_t> nstid; // Namespace-local tids. 253 }; 254 // Keeps track of pid-namespaced threads, keyed by root-level thread ids. 255 std::unordered_map<uint32_t /* tid */, NamespacedThread> namespaced_threads_; 256 257 struct NamespacedProcess { 258 uint32_t pid; // Root-level pid. 259 std::vector<uint32_t> nspid; // Namespace-local pids. 260 std::unordered_set<uint32_t> threads; // Root-level thread IDs. 261 }; 262 // Keeps track pid-namespaced processes, keyed by root-level pids. 263 std::unordered_map<uint32_t /* pid (aka tgid) */, NamespacedProcess> 264 namespaced_processes_; 265 266 UniquePid swapper_upid_ = 0; 267 UniqueTid swapper_utid_ = 0; 268 }; 269 270 } // namespace trace_processor 271 } // namespace perfetto 272 273 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_PROCESS_TRACKER_H_ 274