1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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 "cpu_filter.h"
17 #include "process_filter.h"
18
19 namespace SysTuning {
20 namespace TraceStreamer {
CpuFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)21 CpuFilter::CpuFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter) {}
22 CpuFilter::~CpuFilter() = default;
InsertSwitchEvent(uint64_t ts,uint64_t cpu,uint64_t prevPid,uint64_t prevPior,uint64_t prevState,uint64_t nextPid,uint64_t nextPior)23 void CpuFilter::InsertSwitchEvent(uint64_t ts,
24 uint64_t cpu,
25 uint64_t prevPid,
26 uint64_t prevPior,
27 uint64_t prevState,
28 uint64_t nextPid,
29 uint64_t nextPior)
30 {
31 auto index = traceDataCache_->GetSchedSliceData()->AppendSchedSlice(ts, 0, cpu, nextPid, 0, nextPior);
32
33 auto prevTidOnCpu = cpuToRowSched_.find(cpu);
34 if (prevTidOnCpu != cpuToRowSched_.end()) {
35 traceDataCache_->GetSchedSliceData()->Update(prevTidOnCpu->second, ts, prevState, prevPior);
36 cpuToRowSched_.at(cpu) = index;
37 } else {
38 cpuToRowSched_.insert(std::make_pair(cpu, index));
39 }
40
41 if (nextPid) {
42 CheckWakeupEvent(nextPid);
43 auto lastRow = RowOfInternalTidInStateTable(nextPid);
44 if (lastRow != INVALID_UINT64) {
45 traceDataCache_->GetThreadStateData()->UpdateDuration(static_cast<TableRowId>(lastRow), ts);
46 }
47 index =
48 traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_TIME, cpu, nextPid, TASK_RUNNING);
49 RemberInternalTidInStateTable(nextPid, index, TASK_RUNNING);
50 if (cpuToRowThreadState_.find(cpu) == cpuToRowThreadState_.end()) {
51 cpuToRowThreadState_.insert(std::make_pair(cpu, index));
52 } else {
53 cpuToRowThreadState_.at(cpu) = index;
54 }
55 }
56
57 if (prevPid) {
58 CheckWakeupEvent(prevPid);
59 auto lastRow = RowOfInternalTidInStateTable(prevPid);
60 if (lastRow != INVALID_UINT64) {
61 traceDataCache_->GetThreadStateData()->UpdateDuration(static_cast<TableRowId>(lastRow), ts);
62 streamFilters_->processFilter_->AddCpuStateCount(prevPid);
63 auto thread = traceDataCache_->GetThreadData(prevPid);
64 if (thread){
65 thread->switchCount_ = 1;
66 }
67 }
68 auto temp = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_TIME, INVALID_CPU,
69 prevPid, prevState);
70 RemberInternalTidInStateTable(prevPid, temp, prevState);
71 }
72 }
InsertProcessExitEvent(uint64_t ts,uint64_t cpu,uint64_t pid)73 bool CpuFilter::InsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid)
74 {
75 UNUSED(cpu);
76 auto thread = traceDataCache_->GetThreadData(static_cast<InternalTid>(pid));
77 if (thread) {
78 thread->endT_ = ts;
79 return true;
80 }
81 return false;
82 }
83
InsertProcessFreeEvent(uint64_t ts,uint64_t pid)84 bool CpuFilter::InsertProcessFreeEvent(uint64_t ts, uint64_t pid)
85 {
86 auto thread = traceDataCache_->GetThreadData(static_cast<InternalTid>(pid));
87 if (thread) {
88 thread->endT_ = ts;
89 return true;
90 }
91 return false;
92 }
93
Finish() const94 void CpuFilter::Finish() const
95 {
96 auto size = traceDataCache_->ThreadSize();
97 for (auto i = 0; i < size; i++) {
98 auto thread = traceDataCache_->GetThreadData(i);
99 if (thread->internalPid_ != INVALID_UINT32) {
100 traceDataCache_->GetProcessData(thread->internalPid_)->threadCount_++;
101 traceDataCache_->GetProcessData(thread->internalPid_)->cpuStatesCount_ += thread->cpuStatesCount_;
102 traceDataCache_->GetProcessData(thread->internalPid_)->sliceSize_ += thread->sliceSize_;
103 traceDataCache_->GetProcessData(thread->internalPid_)->switchCount_ += thread->switchCount_;
104 continue;
105 }
106 auto ipid = traceDataCache_->AppendNewProcessData(
107 thread->tid_, traceDataCache_->GetDataFromDict(thread->nameIndex_), thread->startT_);
108 thread->internalPid_ = ipid;
109 traceDataCache_->GetProcessData(thread->internalPid_)->threadCount_++;
110 traceDataCache_->GetProcessData(thread->internalPid_)->cpuStatesCount_ += thread->cpuStatesCount_;
111 traceDataCache_->GetProcessData(thread->internalPid_)->sliceSize_ += thread->sliceSize_;
112 traceDataCache_->GetProcessData(thread->internalPid_)->switchCount_ += thread->switchCount_;
113 }
114 auto threadState = traceDataCache_->GetConstThreadStateData();
115 size = threadState.Size();
116 auto rowData = threadState.ItidsData();
117 for (auto i = 0; i < size; i++) {
118 auto thread = traceDataCache_->GetThreadData(rowData[i]);
119 if (thread->internalPid_ == INVALID_UINT32) {
120 continue;
121 }
122 auto process = traceDataCache_->GetProcessData(thread->internalPid_);
123 traceDataCache_->GetThreadStateData()->UpdateTidAndPid(i, thread->tid_, process->pid_);
124 }
125 auto slice = traceDataCache_->GetConstSchedSliceData();
126 size = slice.Size();
127 for (auto i = 0; i < size; i++) {
128 traceDataCache_->GetSchedSliceData()->AppendInternalPid(
129 traceDataCache_->GetThreadData(slice.InternalTidsData()[i])->internalPid_);
130 }
131 traceDataCache_->OperateDatabase(
132 "update thread set ipid = \
133 (select id from process where \
134 thread.tid = process.pid) where thread.ipid is null;");
135 }
Clear()136 void CpuFilter::Clear()
137 {
138 cpuToRowThreadState_.clear();
139 cpuToRowSched_.clear();
140 lastWakeUpMsg_.clear();
141 internalTidToRowThreadState_.clear();
142 }
InsertWakeupEvent(uint64_t ts,uint64_t internalTid)143 void CpuFilter::InsertWakeupEvent(uint64_t ts, uint64_t internalTid)
144 {
145 uint64_t lastrow = RowOfInternalTidInStateTable(internalTid);
146 auto lastState = StateOfInternalTidInStateTable(internalTid);
147 if (lastState == TASK_RUNNING) {
148 return;
149 }
150 if (lastrow != INVALID_UINT64) {
151 traceDataCache_->GetThreadStateData()->UpdateDuration(static_cast<TableRowId>(lastrow), ts);
152 }
153 auto index = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_TIME, INVALID_CPU,
154 internalTid, TASK_RUNNABLE);
155 RemberInternalTidInStateTable(internalTid, index, TASK_RUNNABLE);
156 }
RemberInternalTidInStateTable(uint64_t uid,uint64_t row,uint64_t state)157 uint64_t CpuFilter::RemberInternalTidInStateTable(uint64_t uid, uint64_t row, uint64_t state)
158 {
159 if (internalTidToRowThreadState_.find(uid) != internalTidToRowThreadState_.end()) {
160 internalTidToRowThreadState_.at(uid) = TPthread{row, state};
161 } else {
162 internalTidToRowThreadState_.insert(std::make_pair(uid, TPthread{row, state}));
163 }
164 return 0;
165 }
RowOfInternalTidInStateTable(uint64_t uid) const166 uint64_t CpuFilter::RowOfInternalTidInStateTable(uint64_t uid) const
167 {
168 auto row = internalTidToRowThreadState_.find(uid);
169 if (row != internalTidToRowThreadState_.end()) {
170 return (*row).second.row_;
171 }
172 return INVALID_UINT64;
173 }
174
StateOfInternalTidInStateTable(uint64_t uid) const175 uint64_t CpuFilter::StateOfInternalTidInStateTable(uint64_t uid) const
176 {
177 auto row = internalTidToRowThreadState_.find(uid);
178 if (row != internalTidToRowThreadState_.end()) {
179 return (*row).second.state_;
180 }
181 return TASK_INVALID;
182 }
183
CheckWakeupEvent(uint64_t internalTid)184 void CpuFilter::CheckWakeupEvent(uint64_t internalTid)
185 {
186 return;
187 }
188 } // namespace TraceStreamer
189 } // namespace SysTuning
190