Merge "Set TraceStorage for TraceProcessorContext."
diff --git a/Android.bp b/Android.bp
index ccae72b..d1412eb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -6543,6 +6543,7 @@
"src/trace_processor/importers/common/global_args_tracker.cc",
"src/trace_processor/importers/common/process_tracker.cc",
"src/trace_processor/importers/common/slice_tracker.cc",
+ "src/trace_processor/importers/common/system_info_tracker.cc",
"src/trace_processor/importers/common/track_tracker.cc",
],
}
diff --git a/BUILD b/BUILD
index 578133a..7340a49 100644
--- a/BUILD
+++ b/BUILD
@@ -731,6 +731,8 @@
"src/trace_processor/importers/common/process_tracker.h",
"src/trace_processor/importers/common/slice_tracker.cc",
"src/trace_processor/importers/common/slice_tracker.h",
+ "src/trace_processor/importers/common/system_info_tracker.cc",
+ "src/trace_processor/importers/common/system_info_tracker.h",
"src/trace_processor/importers/common/track_tracker.cc",
"src/trace_processor/importers/common/track_tracker.h",
],
@@ -881,6 +883,7 @@
"src/trace_processor/types/trace_processor_context.h",
"src/trace_processor/types/variadic.cc",
"src/trace_processor/types/variadic.h",
+ "src/trace_processor/types/version_number.h",
],
)
diff --git a/src/trace_processor/importers/BUILD.gn b/src/trace_processor/importers/BUILD.gn
index debece7..082f7bb 100644
--- a/src/trace_processor/importers/BUILD.gn
+++ b/src/trace_processor/importers/BUILD.gn
@@ -28,6 +28,8 @@
"common/process_tracker.h",
"common/slice_tracker.cc",
"common/slice_tracker.h",
+ "common/system_info_tracker.cc",
+ "common/system_info_tracker.h",
"common/track_tracker.cc",
"common/track_tracker.h",
]
diff --git a/src/trace_processor/importers/common/system_info_tracker.cc b/src/trace_processor/importers/common/system_info_tracker.cc
new file mode 100644
index 0000000..aac30fd
--- /dev/null
+++ b/src/trace_processor/importers/common/system_info_tracker.cc
@@ -0,0 +1,44 @@
+/*
+ * 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/common/system_info_tracker.h"
+#include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+SystemInfoTracker::SystemInfoTracker(TraceProcessorContext*) {}
+SystemInfoTracker::~SystemInfoTracker() = default;
+
+void SystemInfoTracker::SetKernelVersion(base::StringView name,
+ base::StringView release) {
+ if (name.empty() || release.empty() || name != "Linux") {
+ version_ = base::nullopt;
+ return;
+ }
+
+ size_t first_dot_pos = release.find(".");
+ size_t second_dot_pos = release.find(".", first_dot_pos + 1);
+ auto major_version =
+ base::StringToUInt32(release.substr(0, first_dot_pos).ToStdString());
+ auto minor_version = base::StringToUInt32(
+ release.substr(first_dot_pos + 1, second_dot_pos - (first_dot_pos + 1))
+ .ToStdString());
+ version_ = VersionNumber{major_version.value(), minor_version.value()};
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/common/system_info_tracker.h b/src/trace_processor/importers/common/system_info_tracker.h
new file mode 100644
index 0000000..1295db6
--- /dev/null
+++ b/src/trace_processor/importers/common/system_info_tracker.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SYSTEM_INFO_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SYSTEM_INFO_TRACKER_H_
+
+#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/types/destructible.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/version_number.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class SystemInfoTracker : public Destructible {
+ public:
+ ~SystemInfoTracker() override;
+
+ SystemInfoTracker(const SystemInfoTracker&) = delete;
+ SystemInfoTracker& operator=(const SystemInfoTracker&) = delete;
+
+ static SystemInfoTracker* GetOrCreate(TraceProcessorContext* context) {
+ if (!context->system_info_tracker) {
+ context->system_info_tracker.reset(new SystemInfoTracker(context));
+ }
+ return static_cast<SystemInfoTracker*>(context->system_info_tracker.get());
+ }
+
+ void SetKernelVersion(base::StringView name, base::StringView release);
+
+ base::Optional<VersionNumber> GetKernelVersion() { return version_; }
+
+ private:
+ explicit SystemInfoTracker(TraceProcessorContext*);
+
+ base::Optional<VersionNumber> version_;
+};
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SYSTEM_INFO_TRACKER_H_
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.cc b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
index 111c091..5a43d54 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
@@ -22,6 +22,7 @@
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/system_info_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/types/task_state.h"
@@ -239,7 +240,10 @@
// We store the state as a uint16 as we only consider values up to 2048
// when unpacking the information inside; this allows savings of 48 bits
// per slice.
- auto task_state = ftrace_utils::TaskState(static_cast<uint16_t>(prev_state));
+ auto kernel_version =
+ SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
+ auto task_state = ftrace_utils::TaskState(static_cast<uint16_t>(prev_state),
+ kernel_version);
if (!task_state.is_valid()) {
context_->storage->IncrementStats(stats::task_state_invalid);
}
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 6ca53a4..57b7d5c 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -23,6 +23,7 @@
#include "perfetto/protozero/proto_decoder.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/system_info_tracker.h"
#include "src/trace_processor/importers/proto/metadata_tracker.h"
#include "src/trace_processor/importers/syscalls/syscall_tracker.h"
#include "src/trace_processor/storage/metadata.h"
@@ -361,6 +362,10 @@
PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
}
+ SystemInfoTracker* system_info_tracker =
+ SystemInfoTracker::GetOrCreate(context_);
+ system_info_tracker->SetKernelVersion(utsname.sysname(), utsname.release());
+
StringPool::Id sysname_id =
context_->storage->InternString(utsname.sysname());
StringPool::Id version_id =
diff --git a/src/trace_processor/sqlite/BUILD.gn b/src/trace_processor/sqlite/BUILD.gn
index e983510..f2f4bb2 100644
--- a/src/trace_processor/sqlite/BUILD.gn
+++ b/src/trace_processor/sqlite/BUILD.gn
@@ -48,6 +48,7 @@
"../../../protos/perfetto/trace/ftrace:zero",
"../../base",
"../db:lib",
+ "../importers:common",
"../storage",
"../types",
]
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.cc b/src/trace_processor/sqlite/sqlite_raw_table.cc
index ee7d33e..e13c3af 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.cc
+++ b/src/trace_processor/sqlite/sqlite_raw_table.cc
@@ -20,6 +20,7 @@
#include "perfetto/base/compiler.h"
#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/importers/common/system_info_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/types/gfp_flags.h"
@@ -39,18 +40,6 @@
namespace trace_processor {
namespace {
-std::tuple<uint32_t, uint32_t> ParseKernelReleaseVersion(
- base::StringView system_release) {
- size_t first_dot_pos = system_release.find(".");
- size_t second_dot_pos = system_release.find(".", first_dot_pos + 1);
- auto major_version = base::StringToUInt32(
- system_release.substr(0, first_dot_pos).ToStdString());
- auto minor_version = base::StringToUInt32(
- system_release
- .substr(first_dot_pos + 1, second_dot_pos - (first_dot_pos + 1))
- .ToStdString());
- return std::make_tuple(major_version.value(), minor_version.value());
-}
struct FtraceTime {
FtraceTime(int64_t ns)
@@ -62,7 +51,7 @@
class ArgsSerializer {
public:
- ArgsSerializer(const TraceStorage*,
+ ArgsSerializer(TraceProcessorContext*,
ArgSetId arg_set_id,
NullTermStringView event_name,
std::vector<uint32_t>* field_id_to_arg_index,
@@ -100,8 +89,6 @@
void WriteValue(const Variadic& variadic);
- bool ParseGfpFlags(Variadic value);
-
uint32_t FieldIdToRow(uint32_t field_id) {
PERFETTO_DCHECK(field_id > 0);
PERFETTO_DCHECK(field_id < field_id_to_arg_index_->size());
@@ -110,6 +97,7 @@
}
const TraceStorage* storage_ = nullptr;
+ TraceProcessorContext* context_ = nullptr;
ArgSetId arg_set_id_ = kInvalidArgSetId;
NullTermStringView event_name_;
std::vector<uint32_t>* field_id_to_arg_index_;
@@ -120,16 +108,17 @@
base::StringWriter* writer_ = nullptr;
};
-ArgsSerializer::ArgsSerializer(const TraceStorage* storage,
+ArgsSerializer::ArgsSerializer(TraceProcessorContext* context,
ArgSetId arg_set_id,
NullTermStringView event_name,
std::vector<uint32_t>* field_id_to_arg_index,
base::StringWriter* writer)
- : storage_(storage),
+ : context_(context),
arg_set_id_(arg_set_id),
event_name_(event_name),
field_id_to_arg_index_(field_id_to_arg_index),
writer_(writer) {
+ storage_ = context_->storage.get();
const auto& args = storage_->arg_table();
const auto& set_ids = args.arg_set_id();
@@ -185,8 +174,10 @@
WriteArgForField(SS::kPrevStateFieldNumber, [this](const Variadic& value) {
PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
auto state = static_cast<uint16_t>(value.int_value);
+ auto kernel_version =
+ SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
writer_->AppendString(
- ftrace_utils::TaskState(state).ToString('|').data());
+ ftrace_utils::TaskState(state, kernel_version).ToString('|').data());
});
writer_->AppendLiteral(" ==>");
WriteArgForField(SS::kNextCommFieldNumber);
@@ -400,8 +391,12 @@
writer_->AppendString(key.c_str(), key.size());
writer_->AppendChar('=');
- if (key == "gfp_flags" && ParseGfpFlags(value))
+ if (key == "gfp_flags") {
+ auto kernel_version =
+ SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
+ WriteGfpFlag(value.uint_value, kernel_version, writer_);
return;
+ }
writer(value);
}
@@ -435,36 +430,14 @@
}
}
-bool ArgsSerializer::ParseGfpFlags(Variadic value) {
- const auto& metadata_table = storage_->metadata_table();
-
- auto opt_name_idx = metadata_table.name().IndexOf(
- metadata::kNames[metadata::KeyIDs::system_name]);
- auto opt_release_idx = metadata_table.name().IndexOf(
- metadata::kNames[metadata::KeyIDs::system_release]);
- if (!opt_name_idx || !opt_release_idx)
- return false;
-
- const auto& str_value = metadata_table.str_value();
- base::StringView system_name = str_value.GetString(*opt_name_idx);
- if (system_name != "Linux")
- return false;
-
- base::StringView system_release = str_value.GetString(*opt_release_idx);
- auto version = ParseKernelReleaseVersion(system_release);
-
- WriteGfpFlag(value.uint_value, version, writer_);
- return true;
-}
-
} // namespace
SqliteRawTable::SqliteRawTable(sqlite3* db, Context context)
: DbSqliteTable(
db,
{context.cache, tables::RawTable::Schema(), TableComputation::kStatic,
- &context.storage->raw_table(), nullptr}),
- serializer_(context.storage) {
+ &context.context->storage->raw_table(), nullptr}),
+ serializer_(context.context) {
auto fn = [](sqlite3_context* ctx, int argc, sqlite3_value** argv) {
auto* thiz = static_cast<SqliteRawTable*>(sqlite3_user_data(ctx));
thiz->ToSystrace(ctx, argc, argv);
@@ -478,8 +451,8 @@
void SqliteRawTable::RegisterTable(sqlite3* db,
QueryCache* cache,
- const TraceStorage* storage) {
- SqliteTable::Register<SqliteRawTable, Context>(db, Context{cache, storage},
+ TraceProcessorContext* context) {
+ SqliteTable::Register<SqliteRawTable, Context>(db, Context{cache, context},
"raw");
}
@@ -496,8 +469,10 @@
sqlite3_result_text(ctx, str.release(), -1, free);
}
-SystraceSerializer::SystraceSerializer(const TraceStorage* storage)
- : storage_(storage) {}
+SystraceSerializer::SystraceSerializer(TraceProcessorContext* context)
+ : context_(context) {
+ storage_ = context_->storage.get();
+}
SystraceSerializer::ScopedCString SystraceSerializer::SerializeToString(
uint32_t raw_row) {
@@ -518,7 +493,7 @@
}
writer.AppendChar(':');
- ArgsSerializer serializer(storage_, raw.arg_set_id()[raw_row], event_name,
+ ArgsSerializer serializer(context_, raw.arg_set_id()[raw_row], event_name,
&proto_id_to_arg_index_by_event_[event_name_id],
&writer);
serializer.SerializeArgs();
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.h b/src/trace_processor/sqlite/sqlite_raw_table.h
index 4c8190e..2e6d774 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.h
+++ b/src/trace_processor/sqlite/sqlite_raw_table.h
@@ -21,6 +21,7 @@
#include "perfetto/ext/base/string_writer.h"
#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/types/variadic.h"
namespace perfetto {
@@ -30,7 +31,7 @@
public:
using ScopedCString = std::unique_ptr<char, void (*)(void*)>;
- SystraceSerializer(const TraceStorage* storage);
+ SystraceSerializer(TraceProcessorContext* context);
ScopedCString SerializeToString(uint32_t raw_row);
@@ -41,19 +42,20 @@
StringIdMap proto_id_to_arg_index_by_event_;
const TraceStorage* storage_ = nullptr;
+ TraceProcessorContext* context_ = nullptr;
};
class SqliteRawTable : public DbSqliteTable {
public:
struct Context {
QueryCache* cache;
- const TraceStorage* storage;
+ TraceProcessorContext* context;
};
SqliteRawTable(sqlite3*, Context);
virtual ~SqliteRawTable();
- static void RegisterTable(sqlite3* db, QueryCache*, const TraceStorage*);
+ static void RegisterTable(sqlite3* db, QueryCache*, TraceProcessorContext*);
private:
void ToSystrace(sqlite3_context* ctx, int argc, sqlite3_value** argv);
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index ea0764c..f3a97bc 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -558,8 +558,7 @@
WindowOperatorTable::RegisterTable(*db_, storage);
// New style tables but with some custom logic.
- SqliteRawTable::RegisterTable(*db_, query_cache_.get(),
- context_.storage.get());
+ SqliteRawTable::RegisterTable(*db_, query_cache_.get(), &context_);
// Tables dynamically generated at query time.
RegisterDynamicTable(std::unique_ptr<ExperimentalFlamegraphGenerator>(
diff --git a/src/trace_processor/types/BUILD.gn b/src/trace_processor/types/BUILD.gn
index cb719b5..a2a3a97 100644
--- a/src/trace_processor/types/BUILD.gn
+++ b/src/trace_processor/types/BUILD.gn
@@ -23,6 +23,7 @@
"trace_processor_context.h",
"variadic.cc",
"variadic.h",
+ "version_number.h",
]
deps = [
"../../../gn:default_deps",
diff --git a/src/trace_processor/types/gfp_flags.cc b/src/trace_processor/types/gfp_flags.cc
index 74f7511..30a5932 100644
--- a/src/trace_processor/types/gfp_flags.cc
+++ b/src/trace_processor/types/gfp_flags.cc
@@ -199,14 +199,13 @@
// Get the bitmask closest to the kernel version. For versions less than 3.4
// and greater than 4.14 this may end up being inaccurate.
-const FlagArray* GetBitmaskVersion(std::tuple<int32_t, int32_t> version) {
- if (version < std::make_tuple(3, 10)) {
+const FlagArray* GetBitmaskVersion(VersionNumber version = VersionNumber{4,
+ 4}) {
+ if (version < VersionNumber{3, 10}) {
return &v3_4;
- } else if (version >= std::make_tuple(3, 10) &&
- version < std::make_tuple(4, 4)) {
+ } else if (version >= VersionNumber{3, 10} && version < VersionNumber{4, 4}) {
return &v3_10;
- } else if (version >= std::make_tuple(4, 4) &&
- version < std::make_tuple(4, 14)) {
+ } else if (version >= VersionNumber{4, 4} && version < VersionNumber{4, 14}) {
return &v4_4;
} else { // version >= 4.14
// TODO(taylori): Add newer kernel versions once we have access to them.
@@ -216,14 +215,18 @@
} // namespace
void WriteGfpFlag(uint64_t value,
- std::tuple<uint32_t, uint32_t> version,
+ base::Optional<VersionNumber> version,
base::StringWriter* writer) {
// On all kernel versions if this flag is not set, return GFP_NOWAIT.
- if (value == 0)
+ if (value == 0) {
writer->AppendString("GFP_NOWAIT");
+ return;
+ }
std::string result;
- const FlagArray* bitmasks = GetBitmaskVersion(version);
+ const FlagArray* bitmasks = version.has_value()
+ ? GetBitmaskVersion(version.value())
+ : GetBitmaskVersion();
// Based on trace_print_flags_seq() in the kernel.
size_t i = 0;
diff --git a/src/trace_processor/types/gfp_flags.h b/src/trace_processor/types/gfp_flags.h
index 837b284..fb0ae29 100644
--- a/src/trace_processor/types/gfp_flags.h
+++ b/src/trace_processor/types/gfp_flags.h
@@ -17,8 +17,9 @@
#ifndef SRC_TRACE_PROCESSOR_TYPES_GFP_FLAGS_H_
#define SRC_TRACE_PROCESSOR_TYPES_GFP_FLAGS_H_
-#include <tuple>
+#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_writer.h"
+#include "src/trace_processor/types/version_number.h"
namespace perfetto {
namespace trace_processor {
@@ -27,7 +28,7 @@
// the kernel version. This function writes a human readable version of the
// flag.
void WriteGfpFlag(uint64_t value,
- std::tuple<uint32_t, uint32_t> version,
+ base::Optional<VersionNumber> version,
base::StringWriter* writer);
} // namespace trace_processor
diff --git a/src/trace_processor/types/task_state.cc b/src/trace_processor/types/task_state.cc
index 0c8193b..30a23f4 100644
--- a/src/trace_processor/types/task_state.cc
+++ b/src/trace_processor/types/task_state.cc
@@ -26,11 +26,38 @@
namespace trace_processor {
namespace ftrace_utils {
-TaskState::TaskState(uint16_t raw_state) {
- if (raw_state > kMaxState) {
+TaskState::TaskState(uint16_t raw_state,
+ base::Optional<VersionNumber> opt_version) {
+ auto version = VersionNumber{4, 4};
+ if (opt_version) {
+ version = opt_version.value();
+ }
+ max_state_ = version < VersionNumber{4, 9} ? 2048 : 4096;
+
+ if (raw_state > max_state_) {
state_ = 0;
} else {
- state_ = raw_state | kValid;
+ state_ |= kValid;
+ }
+
+ if (version < VersionNumber{4, 14}) {
+ state_ |= raw_state;
+ return;
+ }
+ // All values below kTaskDead are consistent between kernels.
+ state_ |= raw_state & (kTaskDead - 1);
+
+ // Only values up to 0x80 (plus max_state) are relevant in kernels >= 4.14.
+ // See
+ // https://android.googlesource.com/kernel/msm.git/+/refs/heads/android-msm-coral-4.14-android10-qpr1/include/trace/events/sched.h#219
+ if (raw_state & 0x40) {
+ state_ |= kParked;
+ }
+ if (raw_state & 0x80) {
+ state_ |= kTaskDead;
+ }
+ if (raw_state & max_state_) {
+ state_ |= max_state_;
}
}
@@ -44,7 +71,7 @@
invalid_char = true;
break;
} else if (c == '+') {
- state_ |= kMaxState;
+ state_ |= max_state_;
continue;
}
@@ -77,7 +104,7 @@
state_ |= Atom::kExitDead;
else if (c == 'Z')
state_ |= Atom::kExitZombie;
- else if (c == 'x')
+ else if (c == 'x' || c == 'I')
state_ |= Atom::kTaskDead;
else if (c == 'K')
state_ |= Atom::kWakeKill;
@@ -94,9 +121,8 @@
break;
}
}
-
bool no_state = !is_runnable && state_ == 0;
- if (invalid_char || no_state || state_ > kMaxState) {
+ if (invalid_char || no_state || state_ > max_state_) {
state_ = 0;
} else {
state_ |= kValid;
@@ -113,6 +139,7 @@
// This mapping is given by the file
// https://android.googlesource.com/kernel/msm.git/+/android-msm-wahoo-4.4-pie-qpr1/include/trace/events/sched.h#155
+ // Some of these flags are ignored in later kernels but we output them anyway.
if (is_runnable()) {
buffer[pos++] = 'R';
} else {
diff --git a/src/trace_processor/types/task_state.h b/src/trace_processor/types/task_state.h
index 0b79277..b078951 100644
--- a/src/trace_processor/types/task_state.h
+++ b/src/trace_processor/types/task_state.h
@@ -19,10 +19,13 @@
#include <stddef.h>
#include <array>
+#include <utility>
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/string_writer.h"
+#include "src/trace_processor/types/version_number.h"
namespace perfetto {
namespace trace_processor {
@@ -49,49 +52,43 @@
kWaking = 256,
kParked = 512,
kNoLoad = 1024,
+ // This was added in kernel v4.9 but is never used.
+ kTaskNew = 2048,
- // kMaxState is used by sched switch to show a task was kernel preempted.
- // The difficult thing is that in newer kernels a task_new state is added
- // and kMaxState increases to 4096. Without the kernel version and the
- // mapping of this to the correct version of this enum we cannot be
- // accurate. Since task_new is rare we ignore it for now.
- kTaskNewOrMaxState = 2048,
- kMaxState = 4096,
kValid = 0x8000,
};
TaskState() = default;
- explicit TaskState(uint16_t raw_state);
+ explicit TaskState(uint16_t raw_state,
+ base::Optional<VersionNumber> = VersionNumber{4, 4});
explicit TaskState(const char* state_str);
// Returns if this TaskState has a valid representation.
bool is_valid() const { return state_ & kValid; }
// Returns the string representation of this (valid) TaskState. This array
- // is null terminated. |seperator| specifies if a separator should be printed
+ // is null terminated. |separator| specifies if a separator should be printed
// between the atoms (default: \0 meaning no separator).
// Note: This function CHECKs that |is_valid()| is true.
TaskStateStr ToString(char separator = '\0') const;
- // Returns the raw state this class was created from.
+ // Returns the raw state this class can be recreated from.
uint16_t raw_state() const {
PERFETTO_DCHECK(is_valid());
return state_ & ~kValid;
}
// Returns if this TaskState is runnable.
- bool is_runnable() const {
- return ((state_ & (kMaxState - 1)) == 0) ||
- ((state_ & (kTaskNewOrMaxState - 1)) == 0);
- }
+ bool is_runnable() const { return ((state_ & (max_state_ - 1)) == 0); }
// Returns whether kernel preemption caused the exit state.
- bool is_kernel_preempt() const {
- return state_ & kTaskNewOrMaxState || state_ & kMaxState;
- }
+ bool is_kernel_preempt() const { return state_ & max_state_; }
private:
+ // One of Atom - based on given raw_state and version. Will have isValid set
+ // if valid.
uint16_t state_ = 0;
+ uint16_t max_state_ = 2048;
};
} // namespace ftrace_utils
diff --git a/src/trace_processor/types/task_state_unittests.cc b/src/trace_processor/types/task_state_unittests.cc
index a6037ac..09f44af 100644
--- a/src/trace_processor/types/task_state_unittests.cc
+++ b/src/trace_processor/types/task_state_unittests.cc
@@ -49,8 +49,6 @@
}
TEST(TaskStateUnittest, MultipleState) {
- ASSERT_STREQ(TaskState(2048).ToString().data(), "R+");
- ASSERT_STREQ(TaskState(4096).ToString().data(), "R+");
ASSERT_STREQ(TaskState(130).ToString().data(), "DK");
ASSERT_STREQ(TaskState(258).ToString().data(), "DW");
@@ -58,6 +56,35 @@
ASSERT_EQ(TaskState("D|W").raw_state(), 258);
}
+TEST(TaskStateUnittest, KernelVersion) {
+ auto state = TaskState(static_cast<uint16_t>(0u), VersionNumber{4, 14});
+ ASSERT_TRUE(state.is_valid());
+
+ ASSERT_STREQ(state.ToString().data(), "R");
+ ASSERT_STREQ(TaskState(1, VersionNumber{4, 14}).ToString().data(), "S");
+ ASSERT_STREQ(TaskState(2, VersionNumber{4, 14}).ToString().data(), "D");
+ ASSERT_STREQ(TaskState(4, VersionNumber{4, 14}).ToString().data(), "T");
+ ASSERT_STREQ(TaskState(8, VersionNumber{4, 14}).ToString().data(), "t");
+ ASSERT_STREQ(TaskState(16, VersionNumber{4, 14}).ToString().data(), "X");
+ ASSERT_STREQ(TaskState(32, VersionNumber{4, 14}).ToString().data(), "Z");
+ ASSERT_STREQ(TaskState(64, VersionNumber{4, 14}).ToString().data(), "P");
+ ASSERT_STREQ(TaskState(128, VersionNumber{4, 14}).ToString().data(), "x");
+
+ // Any without a specific state but less than max are runnable in this kernel.
+ ASSERT_STREQ(TaskState(256, VersionNumber{4, 14}).ToString().data(), "R");
+ ASSERT_STREQ(TaskState(512, VersionNumber{4, 14}).ToString().data(), "R");
+ ASSERT_STREQ(TaskState(1024, VersionNumber{4, 14}).ToString().data(), "R");
+ ASSERT_STREQ(TaskState(2048, VersionNumber{4, 14}).ToString().data(), "R");
+}
+
+TEST(TaskStateUnittest, MaxValueKernelVersion) {
+ // Max value means pre-empted but is different for each kernel version.
+ ASSERT_STREQ(TaskState(2048).ToString().data(), "R+");
+ ASSERT_STREQ(TaskState(2048, VersionNumber{4, 8}).ToString().data(), "R+");
+ ASSERT_STREQ(TaskState(4096, VersionNumber{4, 14}).ToString().data(), "R+");
+ ASSERT_STREQ(TaskState(4096, VersionNumber{4, 19}).ToString().data(), "R+");
+}
+
} // namespace
} // namespace ftrace_utils
} // namespace trace_processor
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index 8801cd3..2f188ad 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -86,6 +86,7 @@
std::unique_ptr<Destructible> systrace_parser; // SystraceParser
std::unique_ptr<Destructible> heap_graph_tracker; // HeapGraphTracker
std::unique_ptr<Destructible> json_tracker; // JsonTracker
+ std::unique_ptr<Destructible> system_info_tracker; // SystemInfoTracker
// These fields are trace readers which will be called by |forwarding_parser|
// once the format of the trace is discovered. They are placed here as they
diff --git a/src/trace_processor/types/version_number.h b/src/trace_processor/types/version_number.h
new file mode 100644
index 0000000..9119cea
--- /dev/null
+++ b/src/trace_processor/types/version_number.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_TYPES_VERSION_NUMBER_H_
+#define SRC_TRACE_PROCESSOR_TYPES_VERSION_NUMBER_H_
+
+#include <tuple>
+
+namespace perfetto {
+namespace trace_processor {
+
+struct VersionNumber {
+ uint32_t major;
+ uint32_t minor;
+
+ bool operator<(const VersionNumber& other) {
+ return std::tie(major, minor) < std::tie(other.major, other.minor);
+ }
+ bool operator>=(const VersionNumber& other) {
+ return std::tie(major, minor) >= std::tie(other.major, other.minor);
+ }
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_TYPES_VERSION_NUMBER_H_
diff --git a/src/trace_processor/util/descriptors.cc b/src/trace_processor/util/descriptors.cc
index c92488e..e75a77b 100644
--- a/src/trace_processor/util/descriptors.cc
+++ b/src/trace_processor/util/descriptors.cc
@@ -74,8 +74,12 @@
FieldDescriptorProto::Decoder f_decoder(field_desc_proto);
auto field = CreateFieldFromDecoder(f_decoder);
- auto extendee_name =
- package_name + "." + base::StringView(f_decoder.extendee()).ToStdString();
+ auto extendee_name = base::StringView(f_decoder.extendee()).ToStdString();
+ PERFETTO_CHECK(!extendee_name.empty());
+ if (extendee_name[0] != '.') {
+ // Only prepend if the extendee is not fully qualified
+ extendee_name = package_name + "." + extendee_name;
+ }
auto extendee = FindDescriptorIdx(extendee_name);
if (!extendee.has_value()) {
return util::ErrStatus("Extendee does not exist %s", extendee_name.c_str());
diff --git a/test/trace_processor/print_systrace_unsigned.out b/test/trace_processor/print_systrace_unsigned.out
index e0acbcc..43dbb63 100644
--- a/test/trace_processor/print_systrace_unsigned.out
+++ b/test/trace_processor/print_systrace_unsigned.out
@@ -1,4 +1,4 @@
"to_ftrace(id)"
" <unknown>-10 ( 10) [000] .... 0.000000: kfree: call_site=16 ptr=32"
" <unknown>-10 ( 10) [000] .... 0.000000: kfree: call_site=18446744073709551600 ptr=18446744073709551584"
-" <unknown>-10 ( 10) [000] .... 0.000000: kmalloc: gfp_flags=0 call_site=18446744073709551600 ptr=18446744073709551584 bytes_alloc=32 bytes_req=16"
+" <unknown>-10 ( 10) [000] .... 0.000000: kmalloc: gfp_flags=GFP_NOWAIT call_site=18446744073709551600 ptr=18446744073709551584 bytes_alloc=32 bytes_req=16"