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