| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "src/trace_processor/event_tracker.h" |
| #include "perfetto/base/utils.h" |
| #include "src/trace_processor/process_tracker.h" |
| #include "src/trace_processor/trace_processor_context.h" |
| |
| #include <math.h> |
| |
| namespace perfetto { |
| namespace trace_processor { |
| |
| EventTracker::EventTracker(TraceProcessorContext* context) |
| : idle_string_id_(context->storage->InternString("idle")), |
| context_(context) {} |
| |
| EventTracker::~EventTracker() = default; |
| |
| StringId EventTracker::GetThreadNameId(uint32_t tid, base::StringView comm) { |
| return tid == 0 ? idle_string_id_ : context_->storage->InternString(comm); |
| } |
| |
| void EventTracker::PushSchedSwitch(uint32_t cpu, |
| int64_t timestamp, |
| uint32_t prev_pid, |
| uint32_t, |
| uint32_t next_pid, |
| base::StringView next_comm) { |
| // At this stage all events should be globally timestamp ordered. |
| if (timestamp < prev_timestamp_) { |
| PERFETTO_ELOG("sched_switch event out of order by %.4f ms, skipping", |
| (prev_timestamp_ - timestamp) / 1e6); |
| return; |
| } |
| prev_timestamp_ = timestamp; |
| PERFETTO_DCHECK(cpu < base::kMaxCpus); |
| |
| auto* slices = context_->storage->mutable_slices(); |
| auto* pending_slice = &pending_sched_per_cpu_[cpu]; |
| if (pending_slice->storage_index < std::numeric_limits<size_t>::max()) { |
| // If the this events previous pid does not match the previous event's next |
| // pid, make a note of this. |
| if (prev_pid != pending_slice->pid) { |
| context_->storage->mutable_stats()->mismatched_sched_switch_tids++; |
| } |
| |
| size_t idx = pending_slice->storage_index; |
| int64_t duration = timestamp - slices->start_ns()[idx]; |
| slices->set_duration(idx, duration); |
| } |
| |
| StringId name_id = GetThreadNameId(next_pid, next_comm); |
| auto utid = |
| context_->process_tracker->UpdateThread(timestamp, next_pid, name_id); |
| |
| pending_slice->storage_index = |
| slices->AddSlice(cpu, timestamp, 0 /* duration */, utid); |
| pending_slice->pid = next_pid; |
| } |
| |
| RowId EventTracker::PushCounter(int64_t timestamp, |
| double value, |
| StringId name_id, |
| int64_t ref, |
| RefType ref_type) { |
| if (timestamp < prev_timestamp_) { |
| PERFETTO_ELOG("counter event out of order by %.4f ms, skipping", |
| (prev_timestamp_ - timestamp) / 1e6); |
| return kInvalidRowId; |
| } |
| prev_timestamp_ = timestamp; |
| |
| auto* counters = context_->storage->mutable_counters(); |
| const auto& key = CounterKey{ref, name_id}; |
| auto counter_it = pending_counters_per_key_.find(key); |
| if (counter_it != pending_counters_per_key_.end()) { |
| size_t idx = counter_it->second; |
| int64_t duration = timestamp - counters->timestamps()[idx]; |
| // Update duration of previously stored event. |
| counters->set_duration(idx, duration); |
| } |
| |
| // At this point we don't know the duration so just store 0. |
| size_t idx = counters->AddCounter(timestamp, 0 /* duration */, name_id, value, |
| ref, ref_type); |
| pending_counters_per_key_[key] = idx; |
| return TraceStorage::CreateRowId(TableId::kCounters, |
| static_cast<uint32_t>(idx)); |
| } |
| |
| } // namespace trace_processor |
| } // namespace perfetto |