• 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     size_t index = slices->AppendInternalSlice(callStackInternalRow, parentId);
332     if (depth >= std::numeric_limits<uint8_t>::max()) {
333         return SIZE_MAX;
334     }
335     slices->SetDepth(index, depth);
336 
337     uint32_t argSetId = INVALID_UINT32;
338     if (args.valuesMap_.size()) {
339         if (args.inserted_) {
340             argSetId = args.argSetId_;
341         } else {
342             argSetId = streamFilters_->argsFilter_->NewArgs(args);
343             sliceRowToArgsSetId_[index] = argSetId;
344             args.argSetId_ = argSetId;
345             args.inserted_ = true;
346         }
347         // set ArgSetId here
348         slices->SetArgSetId(index, argSetId);
349     }
350     sliceData.argSetId = argSetId;
351     RememberSliceData(internalTid, binderStackMap_, sliceData, depth, index);
352     return index;
353 }
BeginBinder(uint64_t timeStamp,uint32_t pid,DataIndex cat,DataIndex nameIndex,ArgsSet args)354 size_t SliceFilter::BeginBinder(uint64_t timeStamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args)
355 {
356     InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
357     SliceData sliceData = {timeStamp, -1, internalTid, cat, nameIndex};
358     return StartSlice(timeStamp, cat, nameIndex, args, std::move(sliceData));
359 }
360 
CompleteSlice(uint64_t timeStamp,uint32_t internalTid,DataIndex category,DataIndex name,ArgsSet args)361 size_t SliceFilter::CompleteSlice(uint64_t timeStamp,
362                                   uint32_t internalTid,
363                                   DataIndex category,
364                                   DataIndex name,
365                                   ArgsSet args)
366 {
367     TS_CHECK_TRUE_RET(binderStackMap_.find(internalTid) != binderStackMap_.end(), SIZE_MAX);
368     auto &stackInfo = binderStackMap_[internalTid];
369     SlicesStack &stack = stackInfo.sliceStack;
370     CloseUnMatchedSlice(timeStamp, stack, internalTid);
371     if (stack.empty()) {
372         callEventDisMatchCount_++;
373         return SIZE_MAX;
374     }
375     auto stackIdx = MatchingIncompleteSliceIndex(stack, category, name);
376     TS_CHECK_TRUE(stackIdx >= 0, SIZE_MAX, "MatchingIncompleteSliceIndex failed");
377     auto lastRow = stack[stackIdx].index;
378     auto slices = traceDataCache_->GetInternalSlicesData();
379     slices->SetDuration(lastRow, timeStamp);
380 
381     HandleAsyncEventAndOther(args, slices, lastRow, stackInfo);
382     if (stackIdx == stack.size() - 1) {
383         stack.pop_back();
384     }
385     streamFilters_->processFilter_->AddThreadSliceNum(internalTid);
386     return lastRow;
387 }
HandleAsyncEventAndOther(ArgsSet args,CallStack * slices,uint64_t lastRow,StackOfSlices & stackInfo)388 void SliceFilter::HandleAsyncEventAndOther(ArgsSet args, CallStack *slices, uint64_t lastRow, StackOfSlices &stackInfo)
389 {
390     auto argSize = sliceRowToArgsSetId_.count(lastRow);
391     size_t argSetId = 0;
392     if (args.valuesMap_.size()) {
393         if (!argSize) {
394             argSetId = streamFilters_->argsFilter_->NewArgs(args);
395             sliceRowToArgsSetId_[lastRow] = argSetId;
396             slices->SetArgSetId(lastRow, argSetId);
397         } else {
398             argSetId = sliceRowToArgsSetId_.at(lastRow);
399         }
400         streamFilters_->argsFilter_->AppendArgs(args, argSetId);
401     }
402     if (stackInfo.isAsyncEvent) {
403         ArgsSet args;
404         args.AppendArg(asyncBeginCountId_, BASE_DATA_TYPE_INT, stackInfo.asyncEventCount);
405         args.AppendArg(asyncBeginTsId_, BASE_DATA_TYPE_INT, stackInfo.asyncEventLastBeginTs);
406         if (!argSetId) {
407             argSetId = streamFilters_->argsFilter_->NewArgs(args);
408             sliceRowToArgsSetId_[lastRow] = argSetId;
409             slices->SetArgSetId(lastRow, argSetId);
410         } else {
411             streamFilters_->argsFilter_->AppendArgs(args, argSetId);
412         }
413     }
414 }
EndBinder(uint64_t timeStamp,uint32_t pid,DataIndex category,DataIndex name,ArgsSet args)415 size_t SliceFilter::EndBinder(uint64_t timeStamp, uint32_t pid, DataIndex category, DataIndex name, ArgsSet args)
416 {
417     auto internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
418     return CompleteSlice(timeStamp, internalTid, category, name, args);
419 }
AddArgs(uint32_t tid,DataIndex key1,DataIndex key2,ArgsSet & args)420 std::tuple<uint64_t, uint32_t> SliceFilter::AddArgs(uint32_t tid, DataIndex key1, DataIndex key2, ArgsSet &args)
421 {
422     InternalTid internalTid = streamFilters_->processFilter_->GetInternalTid(tid);
423     if (binderStackMap_.find(internalTid) == binderStackMap_.end()) {
424         return std::make_tuple(INVALID_UINT32, INVALID_UINT32);
425     }
426     auto &stack = binderStackMap_[internalTid];
427     auto idx = MatchingIncompleteSliceIndex(stack.sliceStack, key1, key2);
428     if (idx < 0) {
429         return std::make_tuple(INVALID_UINT32, INVALID_UINT32);
430     }
431     uint32_t argSetId = stack.sliceStack[idx].argSetId;
432     if (argSetId == INVALID_UINT32) {
433         argSetId = streamFilters_->argsFilter_->NewArgs(args);
434         sliceRowToArgsSetId_[stack.sliceStack[idx].index] = argSetId;
435         stack.sliceStack[idx].argSetId = argSetId;
436     } else {
437         streamFilters_->argsFilter_->AppendArgs(args, argSetId);
438     }
439     return std::make_tuple(stack.sliceStack[idx].index, argSetId);
440 }
StartAsyncSlice(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)441 uint64_t SliceFilter::StartAsyncSlice(uint64_t timeStamp,
442                                       uint32_t pid,
443                                       uint32_t threadGroupId,
444                                       int64_t cookie,
445                                       DataIndex nameIndex)
446 {
447     InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
448     uint32_t parentId = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
449     auto lastFilterId = asyncEventMap_.Find(internalTid, cookie, nameIndex);
450     auto slices = traceDataCache_->GetInternalSlicesData();
451     auto cat = INVALID_UINT64;
452     if (lastFilterId != INVALID_UINT64) {
453         asyncEventDisMatchCount_++;
454         return INVALID_UINT64;
455     }
456     asyncEventSize_++;
457     std::smatch matchLine;
458     if (std::regex_match(traceDataCache_->GetDataFromDict(nameIndex), matchLine, categoryReg_)) {
459         std::string category = matchLine[categoryMatchedIdx_].str();
460         cat = traceDataCache_->GetDataIndex(Strip(category));
461     }
462     // a pid, cookie and function name determain a callstack
463     asyncEventMap_.Insert(internalTid, cookie, nameIndex, asyncEventSize_);
464     // the IDE need a depth to paint call slice in different position of the canvas, the depth of async call
465     // do not mean the parent-to-child relationship, it is different from no-async call
466     uint8_t depth = 0;
467     CallStackInternalRow callStackInternalRow = {timeStamp, static_cast<uint64_t>(-1), internalTid, cat, nameIndex,
468                                                  depth};
469     size_t index = slices->AppendInternalAsyncSlice(callStackInternalRow, cookie, parentId);
470     asyncEventFilterMap_.insert(std::make_pair(asyncEventSize_, AsyncEvent{timeStamp, index}));
471     return index;
472 }
473 
FinishAsyncSlice(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)474 uint64_t SliceFilter::FinishAsyncSlice(uint64_t timeStamp,
475                                        uint32_t pid,
476                                        uint32_t threadGroupId,
477                                        int64_t cookie,
478                                        DataIndex nameIndex)
479 {
480     Unused(pid);
481     InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
482     auto lastFilterId = asyncEventMap_.Find(internalTid, cookie, nameIndex);
483     auto slices = traceDataCache_->GetInternalSlicesData();
484     if (lastFilterId == INVALID_UINT64) { // if failed
485         asyncEventDisMatchCount_++;
486         return INVALID_UINT64;
487     }
488     if (asyncEventFilterMap_.find(lastFilterId) == asyncEventFilterMap_.end()) {
489         TS_LOGE("logic error");
490         asyncEventDisMatchCount_++;
491         return INVALID_UINT64;
492     }
493     // update timeStamp
494     asyncEventFilterMap_.at(lastFilterId).timeStamp = timeStamp;
495     auto lastRow = asyncEventFilterMap_.at(lastFilterId).row;
496     slices->SetDuration(asyncEventFilterMap_.at(lastFilterId).row, timeStamp);
497     asyncEventFilterMap_.erase(lastFilterId);
498     asyncEventMap_.Erase(internalTid, cookie, nameIndex);
499     streamFilters_->processFilter_->AddThreadSliceNum(internalTid);
500     return lastRow;
501 }
502 
StartGEvent(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)503 void SliceFilter::StartGEvent(uint64_t timeStamp,
504                               uint32_t pid,
505                               uint32_t threadGroupId,
506                               int64_t cookie,
507                               DataIndex nameIndex)
508 {
509     InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
510     auto gEventRes = gEventMap_.Find(internalTid, cookie, nameIndex);
511     auto slices = traceDataCache_->GetInternalSlicesData();
512     gEventSize_++;
513     if (!gEventRes.empty()) {
514         gEventRes.push_back(gEventSize_);
515         gEventMap_.Insert(internalTid, cookie, nameIndex, gEventRes);
516     } else {
517         gEventMap_.Insert(internalTid, cookie, nameIndex, {gEventSize_});
518     }
519     uint8_t depth = 0;
520     std::string nameStr = traceDataCache_->GetDataFromDict(nameIndex);
521     size_t pos = nameStr.find('|');
522     auto cat = traceDataCache_->GetDataIndex(nameStr.substr(0, pos));
523     nameIndex = traceDataCache_->GetDataIndex(nameStr.substr(pos + 1));
524     CallStackInternalRow callStackInternalRow = {timeStamp, static_cast<uint64_t>(-1), internalTid, cat, nameIndex,
525                                                  depth};
526     size_t index = slices->AppendInternalAsyncSlice(callStackInternalRow, cookie, std::nullopt);
527     gEventFilterMap_.insert(std::make_pair(gEventSize_, AsyncEvent{timeStamp, index}));
528 }
529 
FinishHEvent(uint64_t timeStamp,uint32_t threadGroupId,int64_t cookie,DataIndex nameIndex)530 uint64_t SliceFilter::FinishHEvent(uint64_t timeStamp, uint32_t threadGroupId, int64_t cookie, DataIndex nameIndex)
531 {
532     InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, threadGroupId);
533     auto gEventRes = gEventMap_.Find(internalTid, cookie, nameIndex);
534     auto slices = traceDataCache_->GetInternalSlicesData();
535     if (gEventRes.empty()) { // if failed
536         asyncEventDisMatchCount_++;
537         return INVALID_UINT64;
538     }
539     auto finalGEventIndex = gEventRes.back();
540     if (gEventFilterMap_.find(finalGEventIndex) == gEventFilterMap_.end()) {
541         asyncEventDisMatchCount_++;
542         return INVALID_UINT64;
543     }
544     // update timeStamp
545     gEventFilterMap_.at(finalGEventIndex).timeStamp = timeStamp;
546     auto lastRow = gEventFilterMap_.at(finalGEventIndex).row;
547     slices->SetDuration(lastRow, timeStamp);
548     gEventFilterMap_.erase(finalGEventIndex);
549     if (gEventRes.size() == 1) {
550         gEventMap_.Erase(internalTid, cookie, nameIndex);
551     } else {
552         gEventRes.pop_back();
553         gEventMap_.Insert(internalTid, cookie, nameIndex, gEventRes);
554     }
555     streamFilters_->processFilter_->AddThreadSliceNum(internalTid);
556     return lastRow;
557 }
558 
EndSlice(uint64_t timeStamp,uint32_t pid,uint32_t threadGroupId,DataIndex category,DataIndex name)559 size_t SliceFilter::EndSlice(uint64_t timeStamp,
560                              uint32_t pid,
561                              uint32_t threadGroupId,
562                              DataIndex category,
563                              DataIndex name)
564 {
565     uint32_t internalTid = INVALID_UINT32;
566     if (threadGroupId > 0) {
567         internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, threadGroupId);
568     } else {
569         internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timeStamp, pid);
570     }
571     return CompleteSlice(timeStamp, internalTid, category, name);
572 }
573 
UpdateIrqReadySize()574 bool SliceFilter::UpdateIrqReadySize()
575 {
576     CallStack *irqDatas = traceDataCache_->GetIrqData();
577     irqDatas->UpdateReadySize(irqDatas->Size());
578     uint64_t minIrqRowToBeUpdated = INVALID_UINT64;
579     for (const auto &[_, irqRecord] : irqEventMap_) {
580         if (minIrqRowToBeUpdated > irqRecord.row) {
581             minIrqRowToBeUpdated = irqRecord.row;
582         }
583     }
584     for (const auto &[_, softIrqRecord] : softIrqEventMap_) {
585         if (minIrqRowToBeUpdated > softIrqRecord.row) {
586             minIrqRowToBeUpdated = softIrqRecord.row;
587         }
588     }
589     for (const auto &[_, ipiRecord] : ipiEventMap_) {
590         if (minIrqRowToBeUpdated > ipiRecord.row) {
591             minIrqRowToBeUpdated = ipiRecord.row;
592         }
593     }
594     // the ready size isn't all
595     TS_CHECK_TRUE_RET(minIrqRowToBeUpdated != INVALID_UINT64, true);
596     irqDatas->UpdateReadySize(minIrqRowToBeUpdated);
597     TS_LOGI("minIrqRowToBeUpdated=%" PRIu64 ", size=%zu, ready.size=%zu\n", minIrqRowToBeUpdated, irqDatas->Size(),
598             irqDatas->readySize_);
599     for (auto &[_, irqRecord] : irqEventMap_) {
600         irqRecord.row -= irqDatas->readySize_;
601     }
602     for (auto &[_, ipiRecord] : ipiEventMap_) {
603         ipiRecord.row -= irqDatas->readySize_;
604     }
605     for (auto &[_, softIrqRecord] : softIrqEventMap_) {
606         softIrqRecord.row -= irqDatas->readySize_;
607     }
608     return true;
609 }
610 
Clear()611 void SliceFilter::Clear()
612 {
613     asyncEventMap_.Clear();
614     asyncNoEndingEventMap_.clear();
615     irqEventMap_.clear();
616     softIrqEventMap_.clear();
617     asyncEventFilterMap_.clear();
618     sliceStackMap_.clear();
619     depthHolder_.clear();
620     sliceRowToArgsSetId_.clear();
621     argsSet_.clear();
622     gEventMap_.Clear();
623     gEventFilterMap_.clear();
624 }
625 } // namespace TraceStreamer
626 } // namespace SysTuning
627