blob: beebcfed933261d662bed01b5e9e15994e57cc86 [file] [log] [blame]
/*
* 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_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_
#include <array>
#include <limits>
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/utils.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/destructible.h"
#include "src/trace_processor/types/trace_processor_context.h"
namespace perfetto {
namespace trace_processor {
class EventTracker;
// Tracks sched events and stores them into the storage as sched slices.
class SchedEventTracker : public Destructible {
public:
// Declared public for testing only.
explicit SchedEventTracker(TraceProcessorContext*);
SchedEventTracker(const SchedEventTracker&) = delete;
SchedEventTracker& operator=(const SchedEventTracker&) = delete;
~SchedEventTracker() override;
static SchedEventTracker* GetOrCreate(TraceProcessorContext* context) {
if (!context->sched_tracker) {
context->sched_tracker.reset(new SchedEventTracker(context));
}
return static_cast<SchedEventTracker*>(context->sched_tracker.get());
}
// This method is called when a sched_switch event is seen in the trace.
// Virtual for testing.
virtual void PushSchedSwitch(uint32_t cpu,
int64_t timestamp,
uint32_t prev_pid,
base::StringView prev_comm,
int32_t prev_prio,
int64_t prev_state,
uint32_t next_pid,
base::StringView next_comm,
int32_t next_prio);
// This method is called when parsing a sched_switch encoded in the compact
// format.
void PushSchedSwitchCompact(uint32_t cpu,
int64_t ts,
int64_t prev_state,
uint32_t next_pid,
int32_t next_prio,
StringId next_comm_id);
// This method is called when parsing a sched_waking encoded in the compact
// format. Note that the default encoding is handled by
// |EventTracker::PushInstant|.
void PushSchedWakingCompact(uint32_t cpu,
int64_t ts,
uint32_t wakee_pid,
int32_t target_cpu,
int32_t prio,
StringId comm_id);
private:
// Information retained from the preceding sched_switch seen on a given cpu.
struct PendingSchedInfo {
// The pending scheduling slice that the next event will complete.
uint32_t pending_slice_storage_idx = std::numeric_limits<uint32_t>::max();
// pid/utid/prio corresponding to the last sched_switch seen on this cpu
// (its "next_*" fields). There is some duplication with respect to the
// slices storage, but we don't always have a slice when decoding events in
// the compact format.
uint32_t last_pid = std::numeric_limits<uint32_t>::max();
UniqueTid last_utid = std::numeric_limits<UniqueTid>::max();
int32_t last_prio = std::numeric_limits<int32_t>::max();
};
uint32_t AddRawEventAndStartSlice(uint32_t cpu,
int64_t ts,
UniqueTid prev_utid,
uint32_t prev_pid,
StringId prev_comm_id,
int32_t prev_prio,
int64_t prev_state,
UniqueTid next_utid,
uint32_t next_pid,
StringId next_comm_id,
int32_t next_prio);
StringId TaskStateToStringId(int64_t task_state);
void ClosePendingSlice(uint32_t slice_idx, int64_t ts, StringId prev_state);
// Information retained from the preceding sched_switch seen on a given cpu.
std::vector<PendingSchedInfo> pending_sched_per_cpu_;
// Get the sched info for the given CPU, resizing the vector if necessary.
PendingSchedInfo* PendingSchedByCPU(uint32_t cpu) {
if (PERFETTO_UNLIKELY(cpu >= pending_sched_per_cpu_.size())) {
pending_sched_per_cpu_.resize(cpu + 1);
}
return &pending_sched_per_cpu_[cpu];
}
static constexpr uint8_t kSchedSwitchMaxFieldId = 7;
std::array<StringId, kSchedSwitchMaxFieldId + 1> sched_switch_field_ids_;
StringId sched_switch_id_;
static constexpr uint8_t kSchedWakingMaxFieldId = 5;
std::array<StringId, kSchedWakingMaxFieldId + 1> sched_waking_field_ids_;
StringId sched_waking_id_;
StringId waker_utid_id_;
TraceProcessorContext* const context_;
};
} // namespace trace_processor
} // namespace perfetto
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_