• 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 "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