blob: f52066bce25e927e56e4ada09047067f82f8b16b [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_INCLUDE_KERNEL_SPIN_TRACING_H_
#define ZIRCON_KERNEL_INCLUDE_KERNEL_SPIN_TRACING_H_
#include <lib/ktrace.h>
#include <fbl/bits.h>
#include <kernel/spin_tracing_config.h>
namespace spin_tracing {
template <bool Enabled = kSchedulerLockSpinTracingEnabled>
class SpinTracingTimestamp;
template <>
class SpinTracingTimestamp<false> {
public:
constexpr SpinTracingTimestamp() = default;
constexpr uint64_t value() const { return 0; }
};
template <>
class SpinTracingTimestamp<true> {
public:
SpinTracingTimestamp() = default;
uint64_t value() const { return value_; }
private:
const uint64_t value_{ktrace_timestamp()};
};
template <bool TraceInstrumented = false>
class Tracer {
public:
constexpr Tracer() = default;
constexpr explicit Tracer(zx_ticks_t) {}
constexpr void Finish(FinishType, EncodedLockId,
SpinTracingTimestamp<false> = SpinTracingTimestamp<false>{}) const {}
};
template <>
class Tracer<true> {
public:
Tracer() = default;
explicit constexpr Tracer(zx_ticks_t ticks) : start_{static_cast<uint64_t>(ticks)} {}
void Finish(FinishType finish_type, EncodedLockId elid,
SpinTracingTimestamp<true> end_time = SpinTracingTimestamp<true>{}) const {
const uint16_t class_name = static_cast<uint16_t>(
(elid.class_name() != fxt::InternedString::kInvalidId) ? elid.class_name()
: "<unknown>"_intern.GetId());
if constexpr (!kSchedulerLockSpinTracingCompressed) {
const uint64_t lock_id = elid.id();
const auto& lock_type =
elid.lock_type() == LockType::kSpinlock ? "Spinlock"_intern : "Mutex"_intern;
const bool blocked_after = (finish_type == FinishType::kBlocked);
FXT_EVENT_COMMON(true, ktrace_category_enabled, ktrace::EmitComplete, "kernel:sched",
"lock_spin"_intern, start_, end_time.value(), TraceContext::Thread,
("lock_id", lock_id),
("lock_class", fxt::StringRef<fxt::RefType::kId>{class_name}),
("lock_type", lock_type), ("blocked_after", blocked_after));
} else {
// TODO(johngro): We could compress this even more if we omitted the
// dedicated lock_class field (we can extract the value from the elid
// instead). To do this, I need to update my external scripts to process
// the native FXT format. Currently, it depends on conversion to JSON
// before processing, which strips the string table from the data
// (embedding it directly into the JSON instead).
FXT_EVENT_COMMON(true, ktrace_category_enabled, ktrace::EmitComplete, "kernel:sched",
"lock_spin"_intern, start_, end_time.value(), TraceContext::Thread,
("lock_class", fxt::StringRef<fxt::RefType::kId>{class_name}),
("elid", elid.FinishedValue(finish_type)));
}
}
private:
uint64_t start_ = ktrace_timestamp();
};
} // namespace spin_tracing
#endif // ZIRCON_KERNEL_INCLUDE_KERNEL_SPIN_TRACING_H_