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 "slice_filter.h"
17 #include <cstdint>
18 #include <limits>
19 #include <optional>
20
21 #include "args_filter.h"
22 #include "measure_filter.h"
23 #include "process_filter.h"
24 #include "stat_filter.h"
25 #include "string_help.h"
26 #include "string_to_numerical.h"
27 #include "ts_common.h"
28
29 namespace SysTuning {
30 namespace TraceStreamer {
31 using namespace SysTuning::base;
SliceFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)32 SliceFilter::SliceFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
33 : FilterBase(dataCache, filter), asyncEventMap_(INVALID_UINT64), gEventMap_(std::vector<uint64_t>(0))
34 {
35 }
36
37 SliceFilter::~SliceFilter() = default;
38
BeginSlice(const std::string & comm,uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,DataIndex cat,DataIndex nameIndex)39 size_t SliceFilter::BeginSlice(const std::string &comm,
40 uint64_t timeStamp,
41 uint32_t pid,
42 uint32_t threadGroupId,
43 DataIndex cat,
44 DataIndex nameIndex)
45 {
46 InternalTid internalTid = INVALID_ITID;
47 if (threadGroupId > 0) {
48 internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(pid, threadGroupId, comm);
49 pidTothreadGroupId_[pid] = threadGroupId;
50 } else {
51 internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(timeStamp, pid, comm);
52 }
53 // make a SliceData DataItem, {timeStamp, dur, internalTid, cat, nameIndex}
54 SliceData sliceData = {timeStamp, -1, internalTid, cat, nameIndex};
55 ArgsSet args;
56 return StartSlice(timeStamp, cat, nameIndex, args, sliceData);
57 }
58
IrqHandlerEntry(uint64_t timeStamp,uint32_t cpu,DataIndex catalog,DataIndex nameIndex)59 void SliceFilter::IrqHandlerEntry(uint64_t timeStamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex)
60 {
61 // clear ipi for current cpu and nameIndex
62 irqDataLinker_.erase(cpu);
63 SliceData sliceData = {timeStamp, 0, cpu, catalog, nameIndex};
64 auto slices = traceDataCache_->GetIrqData();
65 CallStackInternalRow callStackInternalRow = {sliceData.timeStamp, static_cast<uint64_t>(sliceData.duration),
66 sliceData.internalTid, sliceData.cat,
67 sliceData.name, 0};
68 size_t index = slices->AppendInternalSlice(callStackInternalRow, std::nullopt);
69 if (irqEventMap_.count(cpu)) {
70 // not match
71 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST);
72 irqEventMap_.at(cpu) = {timeStamp, index};
73 } else {
74 irqEventMap_[cpu] = {timeStamp, index};
75 }
76 return;
77 }
78
IrqHandlerExit(uint64_t timeStamp,uint32_t cpu,ArgsSet args)79 void SliceFilter::IrqHandlerExit(uint64_t timeStamp, uint32_t cpu, ArgsSet args)
80 {
81 if (!irqEventMap_.count(cpu)) {
82 // not match
83 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH);
84 return;
85 }
86 uint32_t argSetId = INVALID_UINT32;
87 auto slices = traceDataCache_->GetIrqData();
88 argSetId = streamFilters_->argsFilter_->NewArgs(args);
89 slices->SetIrqDurAndArg(irqEventMap_.at(cpu).row, timeStamp, argSetId);
90 auto internalEventRow = irqDataLinker_.find(cpu);
91 if (internalEventRow != irqDataLinker_.end()) {
92 slices->SetArgSetId(internalEventRow->second, slices->ArgSetIdsData()[irqEventMap_.at(cpu).row]);
93 slices->SetDurationEx(irqEventMap_.at(cpu).row, slices->DursData()[internalEventRow->second]);
94 } else {
95 slices->SetFlag(irqEventMap_.at(cpu).row, 1);
96 }
97 irqDataLinker_.erase(cpu);
98 irqEventMap_.erase(cpu);
99 return;
100 }
101
IpiHandlerEntry(uint64_t timeStamp,uint32_t cpu,DataIndex catalog,DataIndex nameIndex)102 void SliceFilter::IpiHandlerEntry(uint64_t timeStamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex)
103 {
104 irqDataLinker_.erase(cpu);
105 SliceData sliceData = {timeStamp, 0, cpu, catalog, nameIndex};
106 auto slices = traceDataCache_->GetIrqData();
107 CallStackInternalRow callStackInternalRow = {sliceData.timeStamp, static_cast<uint64_t>(sliceData.duration),
108 sliceData.internalTid, sliceData.cat,
109 sliceData.name, 0};
110 size_t index = slices->AppendInternalSlice(callStackInternalRow, std::nullopt);
111 if (ipiEventMap_.count(cpu)) {
112 // not match
113 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST);
114 ipiEventMap_.at(cpu) = {timeStamp, index};
115 } else {
116 ipiEventMap_[cpu] = {timeStamp, index};
117 }
118 return;
119 }
IpiHandlerExit(uint64_t timeStamp,uint32_t cpu)120 void SliceFilter::IpiHandlerExit(uint64_t timeStamp, uint32_t cpu)
121 {
122 if (!ipiEventMap_.count(cpu)) {
123 // not match
124 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST);
125 return;
126 }
127 auto slices = traceDataCache_->GetIrqData();
128 slices->SetDurationWithFlag(ipiEventMap_.at(cpu).row, timeStamp);
129 irqDataLinker_.emplace(cpu, ipiEventMap_.at(cpu).row);
130 ipiEventMap_.erase(cpu);
131 }
SoftIrqEntry(uint64_t timeStamp,uint32_t cpu,DataIndex catalog,DataIndex nameIndex)132 void SliceFilter::SoftIrqEntry(uint64_t timeStamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex)
133 {
134 SliceData sliceData = {timeStamp, 0, cpu, catalog, nameIndex};
135 auto slices = traceDataCache_->GetIrqData();
136 CallStackInternalRow callStackInternalRow = {sliceData.timeStamp, static_cast<uint64_t>(sliceData.duration),
137 sliceData.internalTid, sliceData.cat,
138 sliceData.name, 0};
139 size_t index = slices->AppendInternalSlice(callStackInternalRow, std::nullopt);
140 if (softIrqEventMap_.count(cpu)) {
141 // not match
142 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST);
143 softIrqEventMap_.at(cpu) = {timeStamp, index};
144 } else {
145 softIrqEventMap_[cpu] = {timeStamp, index};
146 }
147 return;
148 }
149
SoftIrqExit(uint64_t timeStamp,uint32_t cpu,ArgsSet args)150 void SliceFilter::SoftIrqExit(uint64_t timeStamp, uint32_t cpu, ArgsSet args)
151 {
152 if (!softIrqEventMap_.count(cpu)) {
153 // not match
154 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST);
155 return;
156 }
157 uint32_t argSetId = INVALID_UINT32;
158 auto slices = traceDataCache_->GetIrqData();
159 argSetId = streamFilters_->argsFilter_->NewArgs(args);
160 slices->SetIrqDurAndArg(softIrqEventMap_.at(cpu).row, timeStamp, argSetId);
161 softIrqEventMap_.erase(cpu);
162 return;
163 }
164
DmaFence(DmaFenceRow & dmaFenceRow)165 void SliceFilter::DmaFence(DmaFenceRow &dmaFenceRow)
166 {
167 if (dmaFenceEventMap_.find(dmaFenceRow.timeline) == dmaFenceEventMap_.end()) {
168 dmaFenceEventMap_.emplace(dmaFenceRow.timeline, dmaFenceRow.timeStamp);
169 } else {
170 dmaFenceRow.duration = dmaFenceRow.timeStamp - dmaFenceEventMap_.at(dmaFenceRow.timeline);
171 dmaFenceEventMap_.at(dmaFenceRow.timeline) = dmaFenceRow.timeStamp;
172 }
173 traceDataCache_->GetDmaFenceData()->AppendNew(dmaFenceRow);
174 }
175
RememberSliceData(InternalTid internalTid,std::unordered_map<InternalTid,StackOfSlices> & stackMap,SliceData & slice,uint32_t depth,uint64_t index)176 void SliceFilter::RememberSliceData(InternalTid internalTid,
177 std::unordered_map<InternalTid, StackOfSlices> &stackMap,
178 SliceData &slice,
179 uint32_t depth,
180 uint64_t index)
181 {
182 if (stackMap.find(internalTid) == stackMap.end()) {
183 auto &sliceStack = stackMap[internalTid].sliceStack; // this can be a empty call, but it does not matter
184 slice.depth = depth;
185 slice.index = index;
186 sliceStack.push_back(slice);
187 } else {
188 auto &sliceStack = stackMap.at(internalTid).sliceStack; // this can be a empty call, but it does not matter
189 slice.depth = depth;
190 slice.index = index;
191 sliceStack.push_back(slice);
192 }
193 }
AsyncBinder(uint64_t timeStamp,uint32_t pid,DataIndex cat,DataIndex nameIndex,ArgsSet & args)194 size_t SliceFilter::AsyncBinder(uint64_t timeStamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet &args)
195 {
196 InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
197 SliceData sliceData = {timeStamp, 0, internalTid, cat, nameIndex};
198 return StartSlice(timeStamp, cat, nameIndex, args, std::move(sliceData));
199 }
CurrentDepth(InternalTid internalTid)200 uint8_t SliceFilter::CurrentDepth(InternalTid internalTid)
201 {
202 if (depthHolder_.find(internalTid) == depthHolder_.end()) {
203 return 0;
204 }
205 auto &depthMap = depthHolder_.at(internalTid);
206 auto depthSize = depthMap.size();
207 for (int32_t i = depthSize - 1; i >= 0; i--) {
208 if (depthMap.at(i)) {
209 return i;
210 }
211 }
212 return 0;
213 }
UpdateDepth(bool increase,InternalTid internalTid,int32_t depth)214 uint8_t SliceFilter::UpdateDepth(bool increase, InternalTid internalTid, int32_t depth)
215 {
216 if (increase) {
217 if (depthHolder_.find(internalTid) == depthHolder_.end()) {
218 StackOnDepth tmp;
219 tmp.insert(std::make_pair(0, true));
220 depthHolder_.insert(std::make_pair(internalTid, tmp));
221 return 0;
222 }
223 auto &depthMap = depthHolder_.at(internalTid);
224 auto depthSize = depthMap.size();
225 auto lastIndex = 0;
226 for (int32_t i = depthSize - 1; i >= 0; i--) {
227 if (depthMap.at(i) && (i == depthSize - 1)) {
228 depthMap.insert(std::make_pair(depthSize, true));
229 return depthSize;
230 }
231 if (depthMap.at(i)) {
232 break;
233 }
234 lastIndex = i;
235 }
236
237 if (!depthMap.at(lastIndex)) {
238 depthMap.at(lastIndex) = true;
239 return lastIndex;
240 }
241 } else {
242 if (depthHolder_.find(internalTid) == depthHolder_.end()) {
243 TS_LOGE("internalTid not found");
244 return 0;
245 }
246 auto &depthMap = depthHolder_.at(internalTid);
247 if (depthMap.find(depth) == depthMap.end()) {
248 return 0;
249 }
250 depthMap.at(depth) = false;
251 }
252 return depth;
253 }
254
CloseUnMatchedSlice(int64_t ts,SlicesStack & stack,InternalTid itid)255 void SliceFilter::CloseUnMatchedSlice(int64_t ts, SlicesStack &stack, InternalTid itid)
256 {
257 auto slices = traceDataCache_->GetInternalSlicesData();
258 bool incomplete = false;
259 for (int32_t i = stack.size() - 1; i >= 0; i--) {
260 uint32_t sliceIdx = stack[i].index;
261 int64_t startTs = slices->TimeStampData()[sliceIdx];
262 int64_t dur = slices->DursData()[sliceIdx];
263 int64_t endTs = startTs + dur;
264 if (dur == -1) {
265 incomplete = true;
266 continue;
267 }
268 if (incomplete) {
269 if (ts <= endTs) {
270 continue;
271 }
272 for (int32_t j = stack.size() - 1; j > i; --j) {
273 uint32_t childIdx = stack[i].index;
274 slices->SetDur(childIdx, endTs - slices->TimeStampData()[childIdx]);
275 stack.pop_back();
276 }
277 stack.pop_back();
278 incomplete = false;
279 continue;
280 }
281 if (endTs <= ts) {
282 stack.pop_back();
283 }
284 }
285 }
286
MatchingIncompleteSliceIndex(const SlicesStack & stack,DataIndex category,DataIndex name)287 int32_t SliceFilter::MatchingIncompleteSliceIndex(const SlicesStack &stack, DataIndex category, DataIndex name)
288 {
289 auto slices = traceDataCache_->GetInternalSlicesData();
290 for (int32_t i = stack.size() - 1; i >= 0; i--) {
291 uint32_t sliceIdx = stack[i].index;
292 if (slices->DursData()[sliceIdx] != -1) {
293 continue;
294 }
295 const DataIndex &categoryLast = slices->CatsData()[sliceIdx];
296 if (category != INVALID_UINT64 && (categoryLast != INVALID_UINT64 && category != categoryLast)) {
297 continue;
298 }
299 const DataIndex &nameLast = slices->NamesData()[sliceIdx];
300 if (name != INVALID_UINT64 && nameLast != INVALID_UINT64 && name != nameLast) {
301 continue;
302 }
303 return static_cast<int32_t>(i);
304 }
305 return -1;
306 }
StartSlice(uint64_t timeStamp,DataIndex cat,DataIndex nameIndex,ArgsSet & args,SliceData sliceData)307 size_t SliceFilter::StartSlice(uint64_t timeStamp,
308 DataIndex cat,
309 DataIndex nameIndex,
310 ArgsSet &args,
311 SliceData sliceData)
312 {
313 InternalTid internalTid = sliceData.internalTid;
314 auto &sliceStack = binderStackMap_[internalTid];
315 auto &stack = sliceStack.sliceStack;
316 if (sliceStack.isAsyncEvent) {
317 sliceStack.asyncEventCount++;
318 sliceStack.asyncEventLastBeginTs = timeStamp;
319 if (!stack.empty()) {
320 return SIZE_MAX;
321 }
322 }
323 // keep slice of thread
324 CloseUnMatchedSlice(timeStamp, stack, internalTid);
325 uint32_t depth = stack.size();
326 auto slices = traceDataCache_->GetInternalSlicesData();
327 uint32_t parentId = depth == 0 ? INVALID_UINT32 : slices->IdsData()[stack.back().index];
328 CallStackInternalRow callStackInternalRow = {sliceData.timeStamp, static_cast<uint64_t>(sliceData.duration),
329 sliceData.internalTid, sliceData.cat,
330 sliceData.name, 0,
331 INVALID_UINT32};
332 size_t index = slices->AppendInternalSlice(callStackInternalRow, parentId);
333 if (depth >= std::numeric_limits<uint8_t>::max()) {
334 return SIZE_MAX;
335 }
336 slices->SetDepth(index, depth);
337
338 uint32_t argSetId = INVALID_UINT32;
339 if (args.valuesMap_.size()) {
340 if (args.inserted_) {
341 argSetId = args.argSetId_;
342 } else {
343 argSetId = streamFilters_->argsFilter_->NewArgs(args);
344 sliceRowToArgsSetId_[index] = argSetId;
345 args.argSetId_ = argSetId;
346 args.inserted_ = true;
347 }
348 // set ArgSetId here
349 slices->SetArgSetId(index, argSetId);
350 }
351 sliceData.argSetId = argSetId;
352 RememberSliceData(internalTid, binderStackMap_, sliceData, depth, index);
353 return index;
354 }
BeginBinder(uint64_t timeStamp,uint32_t pid,DataIndex cat,DataIndex nameIndex,ArgsSet args)355 size_t SliceFilter::BeginBinder(uint64_t timeStamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args)
356 {
357 InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
358 SliceData sliceData = {timeStamp, -1, internalTid, cat, nameIndex};
359 return StartSlice(timeStamp, cat, nameIndex, args, std::move(sliceData));
360 }
361
CompleteSlice(uint64_t timeStamp,uint32_t internalTid,DataIndex category,DataIndex name,ArgsSet args)362 size_t SliceFilter::CompleteSlice(uint64_t timeStamp,
363 uint32_t internalTid,
364 DataIndex category,
365 DataIndex name,
366 ArgsSet args)
367 {
368 TS_CHECK_TRUE_RET(binderStackMap_.find(internalTid) != binderStackMap_.end(), SIZE_MAX);
369 auto &stackInfo = binderStackMap_[internalTid];
370 SlicesStack &stack = stackInfo.sliceStack;
371 CloseUnMatchedSlice(timeStamp, stack, internalTid);
372 if (stack.empty()) {
373 callEventDisMatchCount_++;
374 return SIZE_MAX;
375 }
376 auto stackIdx = MatchingIncompleteSliceIndex(stack, category, name);
377 TS_CHECK_TRUE(stackIdx >= 0, SIZE_MAX, "MatchingIncompleteSliceIndex failed");
378 auto lastRow = stack[stackIdx].index;
379 auto slices = traceDataCache_->GetInternalSlicesData();
380 slices->SetDuration(lastRow, timeStamp);
381
382 HandleAsyncEventAndOther(args, slices, lastRow, stackInfo);
383 if (stackIdx == stack.size() - 1) {
384 stack.pop_back();
385 }
386 streamFilters_->processFilter_->AddThreadSliceNum(internalTid);
387 return lastRow;
388 }
HandleAsyncEventAndOther(ArgsSet args,CallStack * slices,uint64_t lastRow,StackOfSlices & stackInfo)389 void SliceFilter::HandleAsyncEventAndOther(ArgsSet args, CallStack *slices, uint64_t lastRow, StackOfSlices &stackInfo)
390 {
391 auto argSize = sliceRowToArgsSetId_.count(lastRow);
392 size_t argSetId = 0;
393 if (args.valuesMap_.size()) {
394 if (!argSize) {
395 argSetId = streamFilters_->argsFilter_->NewArgs(args);
396 sliceRowToArgsSetId_[lastRow] = argSetId;
397 slices->SetArgSetId(lastRow, argSetId);
398 } else {
399 argSetId = sliceRowToArgsSetId_.at(lastRow);
400 }
401 streamFilters_->argsFilter_->AppendArgs(args, argSetId);
402 }
403 if (stackInfo.isAsyncEvent) {
404 ArgsSet args;
405 args.AppendArg(asyncBeginCountId_, BASE_DATA_TYPE_INT, stackInfo.asyncEventCount);
406 args.AppendArg(asyncBeginTsId_, BASE_DATA_TYPE_INT, stackInfo.asyncEventLastBeginTs);
407 if (!argSetId) {
408 argSetId = streamFilters_->argsFilter_->NewArgs(args);
409 sliceRowToArgsSetId_[lastRow] = argSetId;
410 slices->SetArgSetId(lastRow, argSetId);
411 } else {
412 streamFilters_->argsFilter_->AppendArgs(args, argSetId);
413 }
414 }
415 }
EndBinder(uint64_t timeStamp,uint32_t pid,DataIndex category,DataIndex name,ArgsSet args)416 size_t SliceFilter::EndBinder(uint64_t timeStamp, uint32_t pid, DataIndex category, DataIndex name, ArgsSet args)
417 {
418 auto internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
419 return CompleteSlice(timeStamp, internalTid, category, name, args);
420 }
AddArgs(uint32_t tid,DataIndex key1,DataIndex key2,ArgsSet & args)421 std::tuple<uint64_t, uint32_t> SliceFilter::AddArgs(uint32_t tid, DataIndex key1, DataIndex key2, ArgsSet &args)
422 {
423 InternalTid internalTid = streamFilters_->processFilter_->GetInternalTid(tid);
424 if (binderStackMap_.find(internalTid) == binderStackMap_.end()) {
425 return std::make_tuple(INVALID_UINT32, INVALID_UINT32);
426 }
427 auto &stack = binderStackMap_[internalTid];
428 auto idx = MatchingIncompleteSliceIndex(stack.sliceStack, key1, key2);
429 if (idx < 0) {
430 return std::make_tuple(INVALID_UINT32, INVALID_UINT32);
431 }
432 uint32_t argSetId = stack.sliceStack[idx].argSetId;
433 if (argSetId == INVALID_UINT32) {
434 argSetId = streamFilters_->argsFilter_->NewArgs(args);
435 sliceRowToArgsSetId_[stack.sliceStack[idx].index] = argSetId;
436 stack.sliceStack[idx].argSetId = argSetId;
437 } else {
438 streamFilters_->argsFilter_->AppendArgs(args, argSetId);
439 }
440 return std::make_tuple(stack.sliceStack[idx].index, argSetId);
441 }
StartAsyncSlice(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)442 uint64_t SliceFilter::StartAsyncSlice(uint64_t timeStamp,
443 uint32_t pid,
444 uint32_t threadGroupId,
445 int64_t cookie,
446 DataIndex nameIndex)
447 {
448 InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
449 uint32_t parentId = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
450 auto lastFilterId = asyncEventMap_.Find(internalTid, cookie, nameIndex);
451 auto slices = traceDataCache_->GetInternalSlicesData();
452 auto cat = INVALID_UINT64;
453 if (lastFilterId != INVALID_UINT64) {
454 asyncEventDisMatchCount_++;
455 return INVALID_UINT64;
456 }
457 asyncEventSize_++;
458 std::smatch matchLine;
459 if (std::regex_match(traceDataCache_->GetDataFromDict(nameIndex), matchLine, categoryReg_)) {
460 std::string category = matchLine[categoryMatchedIdx_].str();
461 cat = traceDataCache_->GetDataIndex(Strip(category));
462 }
463 // a pid, cookie and function name determain a callstack
464 asyncEventMap_.Insert(internalTid, cookie, nameIndex, asyncEventSize_);
465 // the IDE need a depth to paint call slice in different position of the canvas, the depth of async call
466 // do not mean the parent-to-child relationship, it is different from no-async call
467 uint8_t depth = 0;
468 uint32_t childCallid = parentId;
469 CallStackInternalRow callStackInternalRow = {
470 timeStamp, static_cast<uint64_t>(-1), internalTid, cat, nameIndex, depth, childCallid};
471 size_t index = slices->AppendInternalAsyncSlice(callStackInternalRow, cookie, parentId);
472 asyncEventFilterMap_.insert(std::make_pair(asyncEventSize_, AsyncEvent{timeStamp, index}));
473 return index;
474 }
475
FinishAsyncSlice(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)476 uint64_t SliceFilter::FinishAsyncSlice(uint64_t timeStamp,
477 uint32_t pid,
478 uint32_t threadGroupId,
479 int64_t cookie,
480 DataIndex nameIndex)
481 {
482 Unused(pid);
483 InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
484 auto lastFilterId = asyncEventMap_.Find(internalTid, cookie, nameIndex);
485 auto slices = traceDataCache_->GetInternalSlicesData();
486 if (lastFilterId == INVALID_UINT64) { // if failed
487 asyncEventDisMatchCount_++;
488 return INVALID_UINT64;
489 }
490 if (asyncEventFilterMap_.find(lastFilterId) == asyncEventFilterMap_.end()) {
491 TS_LOGE("logic error");
492 asyncEventDisMatchCount_++;
493 return INVALID_UINT64;
494 }
495 // update timeStamp
496 asyncEventFilterMap_.at(lastFilterId).timeStamp = timeStamp;
497 auto lastRow = asyncEventFilterMap_.at(lastFilterId).row;
498 slices->SetDuration(asyncEventFilterMap_.at(lastFilterId).row, timeStamp);
499 asyncEventFilterMap_.erase(lastFilterId);
500 asyncEventMap_.Erase(internalTid, cookie, nameIndex);
501 streamFilters_->processFilter_->AddThreadSliceNum(internalTid);
502 return lastRow;
503 }
504
StartGEvent(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)505 void SliceFilter::StartGEvent(uint64_t timeStamp,
506 uint32_t pid,
507 uint32_t threadGroupId,
508 int64_t cookie,
509 DataIndex nameIndex)
510 {
511 InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
512 auto gEventRes = gEventMap_.Find(internalTid, cookie, nameIndex);
513 auto slices = traceDataCache_->GetInternalSlicesData();
514 gEventSize_++;
515 if (!gEventRes.empty()) {
516 gEventRes.push_back(gEventSize_);
517 gEventMap_.Insert(internalTid, cookie, nameIndex, gEventRes);
518 } else {
519 gEventMap_.Insert(internalTid, cookie, nameIndex, {gEventSize_});
520 }
521 uint8_t depth = 0;
522 std::string nameStr = traceDataCache_->GetDataFromDict(nameIndex);
523 size_t pos = nameStr.find('|');
524 auto cat = traceDataCache_->GetDataIndex(nameStr.substr(0, pos));
525 nameIndex = traceDataCache_->GetDataIndex(nameStr.substr(pos + 1));
526 CallStackInternalRow callStackInternalRow = {timeStamp, static_cast<uint64_t>(-1), internalTid, cat, nameIndex,
527 depth};
528 size_t index = slices->AppendInternalAsyncSlice(callStackInternalRow, cookie, std::nullopt);
529 gEventFilterMap_.insert(std::make_pair(gEventSize_, AsyncEvent{timeStamp, index}));
530 }
531
FinishHEvent(uint64_t timeStamp,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)532 uint64_t SliceFilter::FinishHEvent(uint64_t timeStamp, uint32_t threadGroupId, int64_t cookie, DataIndex nameIndex)
533 {
534 InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
535 auto gEventRes = gEventMap_.Find(internalTid, cookie, nameIndex);
536 auto slices = traceDataCache_->GetInternalSlicesData();
537 if (gEventRes.empty()) { // if failed
538 asyncEventDisMatchCount_++;
539 return INVALID_UINT64;
540 }
541 auto finalGEventIndex = gEventRes.back();
542 if (gEventFilterMap_.find(finalGEventIndex) == gEventFilterMap_.end()) {
543 asyncEventDisMatchCount_++;
544 return INVALID_UINT64;
545 }
546 // update timeStamp
547 gEventFilterMap_.at(finalGEventIndex).timeStamp = timeStamp;
548 auto lastRow = gEventFilterMap_.at(finalGEventIndex).row;
549 slices->SetDuration(lastRow, timeStamp);
550 gEventFilterMap_.erase(finalGEventIndex);
551 if (gEventRes.size() == 1) {
552 gEventMap_.Erase(internalTid, cookie, nameIndex);
553 } else {
554 gEventRes.pop_back();
555 gEventMap_.Insert(internalTid, cookie, nameIndex, gEventRes);
556 }
557 streamFilters_->processFilter_->AddThreadSliceNum(internalTid);
558 return lastRow;
559 }
560
EndSlice(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,DataIndex category,DataIndex name)561 size_t SliceFilter::EndSlice(uint64_t timeStamp,
562 uint32_t pid,
563 uint32_t threadGroupId,
564 DataIndex category,
565 DataIndex name)
566 {
567 uint32_t internalTid = INVALID_UINT32;
568 if (threadGroupId > 0) {
569 internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, threadGroupId);
570 } else {
571 internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
572 }
573 return CompleteSlice(timeStamp, internalTid, category, name);
574 }
575
UpdateIrqReadySize()576 bool SliceFilter::UpdateIrqReadySize()
577 {
578 CallStack *irqDatas = traceDataCache_->GetIrqData();
579 irqDatas->UpdateReadySize(irqDatas->Size());
580 uint64_t minIrqRowToBeUpdated = INVALID_UINT64;
581 for (const auto &[_, irqRecord] : irqEventMap_) {
582 if (minIrqRowToBeUpdated > irqRecord.row) {
583 minIrqRowToBeUpdated = irqRecord.row;
584 }
585 }
586 for (const auto &[_, softIrqRecord] : softIrqEventMap_) {
587 if (minIrqRowToBeUpdated > softIrqRecord.row) {
588 minIrqRowToBeUpdated = softIrqRecord.row;
589 }
590 }
591 for (const auto &[_, ipiRecord] : ipiEventMap_) {
592 if (minIrqRowToBeUpdated > ipiRecord.row) {
593 minIrqRowToBeUpdated = ipiRecord.row;
594 }
595 }
596 // the ready size isn't all
597 TS_CHECK_TRUE_RET(minIrqRowToBeUpdated != INVALID_UINT64, true);
598 irqDatas->UpdateReadySize(minIrqRowToBeUpdated);
599 TS_LOGI("minIrqRowToBeUpdated=%" PRIu64 ", size=%zu, ready.size=%zu\n", minIrqRowToBeUpdated, irqDatas->Size(),
600 irqDatas->readySize_);
601 for (auto &[_, irqRecord] : irqEventMap_) {
602 irqRecord.row -= irqDatas->readySize_;
603 }
604 for (auto &[_, ipiRecord] : ipiEventMap_) {
605 ipiRecord.row -= irqDatas->readySize_;
606 }
607 for (auto &[_, softIrqRecord] : softIrqEventMap_) {
608 softIrqRecord.row -= irqDatas->readySize_;
609 }
610 return true;
611 }
612
Clear()613 void SliceFilter::Clear()
614 {
615 asyncEventMap_.Clear();
616 asyncNoEndingEventMap_.clear();
617 irqEventMap_.clear();
618 softIrqEventMap_.clear();
619 asyncEventFilterMap_.clear();
620 sliceStackMap_.clear();
621 depthHolder_.clear();
622 sliceRowToArgsSetId_.clear();
623 argsSet_.clear();
624 gEventMap_.Clear();
625 gEventFilterMap_.clear();
626 }
627 } // namespace TraceStreamer
628 } // namespace SysTuning
629