1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <limits> 18 19 #include <stdint.h> 20 21 #include "src/trace_processor/process_tracker.h" 22 #include "src/trace_processor/slice_tracker.h" 23 #include "src/trace_processor/trace_processor_context.h" 24 #include "src/trace_processor/trace_storage.h" 25 26 namespace perfetto { 27 namespace trace_processor { 28 namespace { 29 // Slices which have been opened but haven't been closed yet will be marked 30 // with this duration placeholder. 31 constexpr int64_t kPendingDuration = -1; 32 }; // namespace 33 34 SliceTracker::SliceTracker(TraceProcessorContext* context) 35 : context_(context) {} 36 37 SliceTracker::~SliceTracker() = default; 38 39 void SliceTracker::BeginAndroid(int64_t timestamp, 40 uint32_t ftrace_tid, 41 uint32_t atrace_tgid, 42 StringId cat, 43 StringId name) { 44 UniqueTid utid = 45 context_->process_tracker->UpdateThread(ftrace_tid, atrace_tgid); 46 ftrace_to_atrace_tgid_[ftrace_tid] = atrace_tgid; 47 Begin(timestamp, utid, cat, name); 48 } 49 50 void SliceTracker::Begin(int64_t timestamp, 51 UniqueTid utid, 52 StringId cat, 53 StringId name) { 54 MaybeCloseStack(timestamp, &threads_[utid]); 55 StartSlice(timestamp, kPendingDuration, utid, cat, name); 56 } 57 58 void SliceTracker::Scoped(int64_t timestamp, 59 UniqueTid utid, 60 StringId cat, 61 StringId name, 62 int64_t duration) { 63 PERFETTO_DCHECK(duration >= 0); 64 MaybeCloseStack(timestamp, &threads_[utid]); 65 StartSlice(timestamp, duration, utid, cat, name); 66 } 67 68 void SliceTracker::StartSlice(int64_t timestamp, 69 int64_t duration, 70 UniqueTid utid, 71 StringId cat, 72 StringId name) { 73 auto* stack = &threads_[utid]; 74 auto* slices = context_->storage->mutable_nestable_slices(); 75 76 const uint8_t depth = static_cast<uint8_t>(stack->size()); 77 if (depth >= std::numeric_limits<uint8_t>::max()) { 78 PERFETTO_DFATAL("Slices with too large depth found."); 79 return; 80 } 81 int64_t parent_stack_id = depth == 0 ? 0 : slices->stack_ids()[stack->back()]; 82 size_t slice_idx = 83 slices->AddSlice(timestamp, duration, utid, RefType::kRefUtid, cat, name, 84 depth, 0, parent_stack_id); 85 stack->emplace_back(slice_idx); 86 87 slices->set_stack_id(slice_idx, GetStackHash(*stack)); 88 } 89 90 void SliceTracker::EndAndroid(int64_t timestamp, 91 uint32_t ftrace_tid, 92 uint32_t atrace_tgid) { 93 auto actual_tgid_it = ftrace_to_atrace_tgid_.find(ftrace_tid); 94 if (actual_tgid_it == ftrace_to_atrace_tgid_.end()) { 95 // This is possible if we start tracing after a begin slice. 96 PERFETTO_DLOG("Unknown tgid for ftrace tid %u", ftrace_tid); 97 return; 98 } 99 uint32_t actual_tgid = actual_tgid_it->second; 100 // atrace_tgid can be 0 in older android versions where the end event would 101 // not contain the value. 102 if (atrace_tgid != 0 && atrace_tgid != actual_tgid) { 103 PERFETTO_DLOG("Mismatched atrace pid %u and looked up pid %u", atrace_tgid, 104 actual_tgid); 105 context_->storage->IncrementStats(stats::atrace_tgid_mismatch); 106 } 107 UniqueTid utid = 108 context_->process_tracker->UpdateThread(ftrace_tid, actual_tgid); 109 End(timestamp, utid); 110 } 111 112 void SliceTracker::End(int64_t timestamp, 113 UniqueTid utid, 114 StringId cat, 115 StringId name) { 116 MaybeCloseStack(timestamp, &threads_[utid]); 117 118 const auto& stack = threads_[utid]; 119 if (stack.empty()) 120 return; 121 122 auto* slices = context_->storage->mutable_nestable_slices(); 123 size_t slice_idx = stack.back(); 124 125 // If we are trying to close mismatching slices (e.g., slices that began 126 // before tracing started), bail out. 127 if (cat && slices->cats()[slice_idx] != cat) 128 return; 129 if (name && slices->names()[slice_idx] != name) 130 return; 131 132 PERFETTO_DCHECK(slices->durations()[slice_idx] == kPendingDuration); 133 slices->set_duration(slice_idx, timestamp - slices->start_ns()[slice_idx]); 134 135 CompleteSlice(utid); 136 // TODO(primiano): auto-close B slices left open at the end. 137 } 138 139 void SliceTracker::CompleteSlice(UniqueTid utid) { 140 threads_[utid].pop_back(); 141 } 142 143 void SliceTracker::MaybeCloseStack(int64_t ts, SlicesStack* stack) { 144 const auto& slices = context_->storage->nestable_slices(); 145 bool check_only = false; 146 for (int i = static_cast<int>(stack->size()) - 1; i >= 0; i--) { 147 size_t slice_idx = (*stack)[static_cast<size_t>(i)]; 148 149 int64_t start_ts = slices.start_ns()[slice_idx]; 150 int64_t dur = slices.durations()[slice_idx]; 151 int64_t end_ts = start_ts + dur; 152 if (dur == kPendingDuration) { 153 check_only = true; 154 } 155 156 if (check_only) { 157 PERFETTO_CHECK(ts >= start_ts); 158 PERFETTO_CHECK(dur == kPendingDuration || ts <= end_ts); 159 continue; 160 } 161 162 if (end_ts <= ts) { 163 stack->pop_back(); 164 } 165 } 166 } 167 168 int64_t SliceTracker::GetStackHash(const SlicesStack& stack) { 169 PERFETTO_DCHECK(!stack.empty()); 170 171 const auto& slices = context_->storage->nestable_slices(); 172 173 std::string s; 174 s.reserve(stack.size() * sizeof(uint64_t) * 2); 175 for (size_t i = 0; i < stack.size(); i++) { 176 size_t slice_idx = stack[i]; 177 s.append(reinterpret_cast<const char*>(&slices.cats()[slice_idx]), 178 sizeof(slices.cats()[slice_idx])); 179 s.append(reinterpret_cast<const char*>(&slices.names()[slice_idx]), 180 sizeof(slices.names()[slice_idx])); 181 } 182 constexpr uint64_t kMask = uint64_t(-1) >> 1; 183 return static_cast<int64_t>((std::hash<std::string>{}(s)) & kMask); 184 } 185 186 } // namespace trace_processor 187 } // namespace perfetto 188