blob: be456a6143822ae4a9bc6ba08629c80d0204eb99 [file] [log] [blame]
/*
* Copyright (C) 2020 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/importers/systrace/systrace_line_parser.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
#include "src/trace_processor/args_tracker.h"
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/ftrace_utils.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/track_tracker.h"
#include <inttypes.h>
#include <cctype>
#include <string>
#include <unordered_map>
namespace perfetto {
namespace trace_processor {
SystraceLineParser::SystraceLineParser(TraceProcessorContext* ctx)
: context_(ctx),
sched_wakeup_name_id_(ctx->storage->InternString("sched_wakeup")),
cpuidle_name_id_(ctx->storage->InternString("cpuidle")) {}
util::Status SystraceLineParser::ParseLine(const SystraceLine& line) {
context_->process_tracker->GetOrCreateThread(line.pid);
if (!line.tgid_str.empty() && line.tgid_str != "-----") {
base::Optional<uint32_t> tgid = base::StringToUInt32(line.tgid_str);
if (tgid) {
context_->process_tracker->UpdateThread(line.pid, tgid.value());
}
}
std::unordered_map<std::string, std::string> args;
for (base::StringSplitter ss(line.args_str, ' '); ss.Next();) {
std::string key;
std::string value;
for (base::StringSplitter inner(ss.cur_token(), '='); inner.Next();) {
if (key.empty()) {
key = inner.cur_token();
} else {
value = inner.cur_token();
}
}
args.emplace(std::move(key), std::move(value));
}
if (line.event_name == "sched_switch") {
auto prev_state_str = args["prev_state"];
int64_t prev_state =
ftrace_utils::TaskState(prev_state_str.c_str()).raw_state();
auto prev_pid = base::StringToUInt32(args["prev_pid"]);
auto prev_comm = base::StringView(args["prev_comm"]);
auto prev_prio = base::StringToInt32(args["prev_prio"]);
auto next_pid = base::StringToUInt32(args["next_pid"]);
auto next_comm = base::StringView(args["next_comm"]);
auto next_prio = base::StringToInt32(args["next_prio"]);
if (!(prev_pid.has_value() && prev_prio.has_value() &&
next_pid.has_value() && next_prio.has_value())) {
return util::Status("Could not parse sched_switch");
}
SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
line.cpu, line.ts, prev_pid.value(), prev_comm, prev_prio.value(),
prev_state, next_pid.value(), next_comm, next_prio.value());
} else if (line.event_name == "tracing_mark_write" ||
line.event_name == "0" || line.event_name == "print") {
SystraceParser::GetOrCreate(context_)->ParsePrintEvent(
line.ts, line.pid, line.args_str.c_str());
} else if (line.event_name == "sched_wakeup") {
auto comm = args["comm"];
base::Optional<uint32_t> wakee_pid = base::StringToUInt32(args["pid"]);
if (!wakee_pid.has_value()) {
return util::Status("Could not convert wakee_pid");
}
StringId name_id = context_->storage->InternString(base::StringView(comm));
auto wakee_utid =
context_->process_tracker->UpdateThreadName(wakee_pid.value(), name_id);
context_->event_tracker->PushInstant(line.ts, sched_wakeup_name_id_,
wakee_utid, RefType::kRefUtid);
} else if (line.event_name == "cpu_idle") {
base::Optional<uint32_t> event_cpu = base::StringToUInt32(args["cpu_id"]);
base::Optional<double> new_state = base::StringToDouble(args["state"]);
if (!event_cpu.has_value()) {
return util::Status("Could not convert event cpu");
}
if (!event_cpu.has_value()) {
return util::Status("Could not convert state");
}
TrackId track = context_->track_tracker->InternCpuCounterTrack(
cpuidle_name_id_, event_cpu.value());
context_->event_tracker->PushCounter(line.ts, new_state.value(), track);
}
return util::OkStatus();
}
} // namespace trace_processor
} // namespace perfetto