• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "process_filter.h"
17 #include <cinttypes>
18 #include <limits>
19 #include <string_view>
20 #include <utility>
21 
22 using CustomPair = std::pair<uint32_t, uint32_t>;
23 namespace SysTuning {
24 namespace TraceStreamer {
25 namespace {
26 const uint32_t INVALID_ID = std::numeric_limits<uint32_t>::max();
27 }
ProcessFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)28 ProcessFilter::ProcessFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
29     : FilterBase(dataCache, filter)
30 {
31     tidMappingSet_.insert(CustomPair(0, 0));
32     pidToInternalPidMap_.insert(CustomPair(0, 0));
33 }
34 
~ProcessFilter()35 ProcessFilter::~ProcessFilter() {}
36 
UpdateOrCreateThreadWithName(uint64_t timeStamp,uint32_t tid,std::string_view name)37 uint32_t ProcessFilter::UpdateOrCreateThreadWithName(uint64_t timeStamp, uint32_t tid, std::string_view name)
38 {
39     DataIndex nameIndex = traceDataCache_->GetDataIndex(name);
40     return UpdateOrCreateThreadWithNameIndex(timeStamp, tid, nameIndex);
41 }
42 
AddProcessMemory(uint32_t ipid)43 void ProcessFilter::AddProcessMemory(uint32_t ipid)
44 {
45     traceDataCache_->GetProcessData(ipid)->memSize_ = 1;
46 }
47 
AddThreadSliceNum(uint32_t itid)48 void ProcessFilter::AddThreadSliceNum(uint32_t itid)
49 {
50     traceDataCache_->GetThreadData(itid)->sliceSize_ = 1;
51 }
AddProcessSliceNum(uint32_t ipid)52 void ProcessFilter::AddProcessSliceNum(uint32_t ipid)
53 {
54     traceDataCache_->GetProcessData(ipid)->sliceSize_ = 1;
55 }
56 
AddCpuStateCount(uint32_t itid)57 void ProcessFilter::AddCpuStateCount(uint32_t itid)
58 {
59     auto thread = traceDataCache_->GetThreadData(itid);
60     if (thread) {
61         thread->cpuStatesCount_++;
62     }
63 }
UpdateOrCreateThread(uint64_t timeStamp,uint32_t tid)64 uint32_t ProcessFilter::UpdateOrCreateThread(uint64_t timeStamp, uint32_t tid)
65 {
66     return UpdateOrCreateThreadWithNameIndex(timeStamp, tid, 0);
67 }
UpdateOrCreateThreadWithPidAndName(uint32_t tid,uint32_t pid,std::string_view name)68 uint32_t ProcessFilter::UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name)
69 {
70     uint32_t internalTid = GetOrCreateThreadWithPid(tid, pid);
71     auto thread = traceDataCache_->GetThreadData(internalTid);
72     auto nameIndex = traceDataCache_->GetDataIndex(name);
73     thread->nameIndex_ = nameIndex;
74     // When the process ID is equal to the thread ID, the process name is also equal to the thread name
75     if (tid == pid) {
76         UpdateOrCreateProcessWithName(pid, name);
77     }
78     return internalTid;
79 }
80 
GetOrCreateThreadWithPid(uint32_t tid,uint32_t pid)81 uint32_t ProcessFilter::GetOrCreateThreadWithPid(uint32_t tid, uint32_t pid)
82 {
83     TraceStdtype::Thread *thread = nullptr;
84     uint32_t internalTid;
85     if (pid == 0) {
86         internalTid = GetInternalTid(tid);
87     } else {
88         internalTid = GetInternalTid(tid, pid);
89     }
90     if (internalTid != INVALID_ID) {
91         thread = traceDataCache_->GetThreadData(internalTid);
92     } else {
93         std::tie(internalTid, thread) = NewThread(tid);
94     }
95 
96     if (thread->internalPid_ == INVALID_UINT32 && pid != 0) {
97         std::tie(thread->internalPid_, std::ignore) = CreateProcessMaybe(pid, thread->startT_);
98     }
99 
100     return internalTid;
101 }
102 
UpdateOrCreateProcessWithName(uint32_t pid,std::string_view name)103 uint32_t ProcessFilter::UpdateOrCreateProcessWithName(uint32_t pid, std::string_view name)
104 {
105     uint32_t internalPid = 0;
106     TraceStdtype::Process *process = nullptr;
107     std::tie(internalPid, process) = CreateProcessMaybe(pid, 0);
108     if (process && name != "" && process->cmdLine_ != name) {
109         process->cmdLine_ = std::string(name);
110     }
111     // update main thread name
112     auto internalTid = GetInternalTid(pid, pid);
113     if (internalTid != INVALID_ID) {
114         auto thread = traceDataCache_->GetThreadData(internalTid);
115         thread->nameIndex_ = traceDataCache_->GetDataIndex(process->cmdLine_);
116     }
117     return internalPid;
118 }
119 
UpdateOrCreateThreadWithNameIndex(uint64_t timeStamp,uint32_t tid,DataIndex threadNameIndex)120 uint32_t ProcessFilter::UpdateOrCreateThreadWithNameIndex(uint64_t timeStamp, uint32_t tid, DataIndex threadNameIndex)
121 {
122     TraceStdtype::Thread *thread = nullptr;
123     auto &internalTids = GetInternalTids(tid);
124     if (internalTids.size()) {
125         if (!threadNameIndex) {
126             return internalTids.back();
127         }
128         for (auto i : internalTids) {
129             thread = traceDataCache_->GetThreadData(i);
130             if (thread && threadNameIndex != thread->nameIndex_) {
131                 thread->nameIndex_ = threadNameIndex;
132             }
133         }
134     } else {
135         InternalTid internalTid = INVALID_ITID;
136         std::tie(internalTid, thread) = NewThread(tid);
137         if (!thread) {
138             return INVALID_ID;
139         }
140         thread->nameIndex_ = threadNameIndex;
141         return internalTid;
142     }
143     return internalTids.back();
144 }
GetInternalTid(uint32_t tid,uint32_t pid) const145 uint32_t ProcessFilter::GetInternalTid(uint32_t tid, uint32_t pid) const
146 {
147     uint32_t internalTid = INVALID_ID;
148     auto tidsPair = tidMappingSet_.equal_range(tid);
149     for (auto it = tidsPair.first; it != tidsPair.second; it++) {
150         uint32_t iterItid = it->second;
151         auto iterThread = traceDataCache_->GetThreadData(iterItid);
152         if (iterThread->internalPid_ == INVALID_UINT32) {
153             internalTid = iterItid;
154             continue;
155         }
156 
157         const auto &iterProcess = traceDataCache_->GetConstProcessData(iterThread->internalPid_);
158         if (iterProcess.pid_ == pid) {
159             internalTid = iterItid;
160             break;
161         }
162     }
163 
164     return internalTid;
165 }
166 
GetInternalTid(uint32_t tid) const167 uint32_t ProcessFilter::GetInternalTid(uint32_t tid) const
168 {
169     auto itRange = tidMappingSet_.equal_range(tid);
170     if (itRange.first != itRange.second) {
171         auto internalTid = std::prev(itRange.second)->second;
172         return internalTid;
173     }
174     return INVALID_ID;
175 }
176 
GetInternalTids(uint32_t tid)177 std::vector<InternalTid> &ProcessFilter::GetInternalTids(uint32_t tid)
178 {
179     tmpTids_.clear();
180     auto itRange = tidMappingSet_.equal_range(tid);
181     auto it = itRange.first;
182     while (it != itRange.second) {
183         tmpTids_.push_back(it->second);
184         it++;
185     }
186     return tmpTids_;
187 }
188 
GetInternalPid(uint32_t pid) const189 InternalPid ProcessFilter::GetInternalPid(uint32_t pid) const
190 {
191     auto it = pidToInternalPidMap_.find(pid);
192     if (it != pidToInternalPidMap_.end()) {
193         return it->second;
194     }
195     return INVALID_ID;
196 }
197 
GetOrCreateInternalPid(uint64_t timeStamp,uint32_t pid)198 InternalPid ProcessFilter::GetOrCreateInternalPid(uint64_t timeStamp, uint32_t pid)
199 {
200     auto ipid = GetInternalPid(pid);
201     if (ipid != INVALID_ID) {
202         return ipid;
203     }
204 
205     uint32_t internalPid = 0;
206     TraceStdtype::Process *process = nullptr;
207     std::tie(internalPid, process) = CreateProcessMaybe(pid, timeStamp);
208     return internalPid;
209 }
NewThread(uint32_t tid)210 std::tuple<uint32_t, TraceStdtype::Thread *> ProcessFilter::NewThread(uint32_t tid)
211 {
212     uint32_t internalTid = traceDataCache_->NewInternalThread(tid);
213     tidMappingSet_.emplace(tid, internalTid);
214     auto thread = traceDataCache_->GetThreadData(internalTid);
215 
216     return std::make_tuple(internalTid, thread);
217 }
218 
NewProcess(uint32_t pid)219 std::tuple<uint32_t, TraceStdtype::Process *> ProcessFilter::NewProcess(uint32_t pid)
220 {
221     uint32_t internalPid = traceDataCache_->GetProcessInternalPid(pid);
222     pidToInternalPidMap_.emplace(pid, internalPid);
223     auto process = traceDataCache_->GetProcessData(internalPid);
224 
225     return std::make_tuple(internalPid, process);
226 }
227 
CreateProcessMaybe(uint32_t pid,uint64_t startT)228 std::tuple<uint32_t, TraceStdtype::Process *> ProcessFilter::CreateProcessMaybe(uint32_t pid, uint64_t startT)
229 {
230     uint32_t internalPid = INVALID_ID;
231     TraceStdtype::Process *process = nullptr;
232     auto it = pidToInternalPidMap_.find(pid);
233     if (it != pidToInternalPidMap_.end()) {
234         internalPid = it->second;
235         process = traceDataCache_->GetProcessData(internalPid);
236     } else {
237         std::tie(internalPid, process) = NewProcess(pid);
238         void(GetOrCreateThreadWithPid(pid, pid));
239     }
240 
241     if (process->startT_ == 0) {
242         process->startT_ = startT;
243     }
244 
245     return std::make_tuple(internalPid, process);
246 }
UpdateProcessNameByNameToTid(std::unordered_map<int32_t,std::string> & tidToName)247 void ProcessFilter::UpdateProcessNameByNameToTid(std::unordered_map<int32_t, std::string> &tidToName)
248 {
249     auto processList = traceDataCache_->GetConstProcessData();
250     auto size = processList.size();
251     for (auto row = 0; row < size; row++) {
252         if (!processList[row].cmdLine_.empty()) {
253             continue;
254         }
255         auto process = traceDataCache_->GetProcessData(row);
256         if (!process) {
257             continue;
258         }
259         auto it = tidToName.find(process->pid_);
260         if (it != tidToName.end()) {
261             auto res = UpdateOrCreateProcessWithName(process->pid_, it->second.c_str());
262             TS_LOGI("Update process name %s to tid %d", it->second.c_str(), process->pid_);
263         }
264     }
265 }
Clear()266 void ProcessFilter::Clear()
267 {
268     tidMappingSet_.clear();
269     pidToInternalPidMap_.clear();
270 }
271 } // namespace TraceStreamer
272 } // namespace SysTuning
273