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