blob: 1b9b4784f5dceca8def84a93ea0048b025292156 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_LIB_PERFMON_CONFIG_H_
#define GARNET_LIB_PERFMON_CONFIG_H_
#include <functional>
#include <stdint.h>
#include <string>
#include <unordered_set>
#include <lib/zircon-internal/device/cpu-trace/perf-mon.h>
#include "garnet/lib/perfmon/types.h"
namespace perfmon {
// Description of what data to collect in a trace run.
// This is internally basically a copy of the FIDL struct, kept separate and
// filled in programmatically to not pass a FIDL dependency on to our clients.
class Config {
public:
// Data for one event. Passed to |IterateFunc|.
struct EventConfig {
// Event to collect data for.
// The values are architecture specific ids.
EventId event;
// Sampling rate.
// - If rate is non-zero then when the event gets this many hits data is
// collected (e.g., pc, time).
// The rate can be non-zero for counting based events only.
// - If rate is zero then:
// If there is a timebase event then data for this event is collected
// when data for the timebase event is collected.
// Otherwise data for the event is collected once, when tracing stops.
EventRate rate;
// Flags for each event in |events|.
// The values are |Config::kFlag*|.
uint32_t flags;
};
// Callback for |IterateOverEvents()|.
using IterateFunc = std::function<void(const EventConfig& event)>;
// Bits for event flags.
// TODO(dje): hypervisor, host/guest os/user
static constexpr uint32_t kFlagMask = 0x1f;
// Collect os data.
// If neither |kFlagOs,KflagPc| are specified then both are collected.
static constexpr uint32_t kFlagOs = 0x1;
// Collect userspace data.
// If neither |kFlagOs,KflagPc| are specified then both are collected.
static constexpr uint32_t kFlagUser = 0x2;
// Collect aspace+pc values.
static constexpr uint32_t kFlagPc = 0x4;
// If set then this event is used as the "timebase": data for events that
// aren't their own time base is collected when data for this event is
// collected. Events that are their own timebase have a non-zero rate.
// It is an error to have this set and have the rate be zero.
// There can be only one "timebase" event.
static constexpr uint32_t kFlagTimebase = 0x8;
// Collect the available set of last branches.
// Branch data is emitted as PERFMON_RECORD_LAST_BRANCH records.
// This is only available when the underlying system supports it.
// TODO(dje): Provide knob to specify how many branches.
static constexpr uint32_t kFlagLastBranch = 0x10;
// These flags may only be specified with a non-zero rate.
static constexpr uint32_t kNonZeroRateOnlyFlags = kFlagPc + kFlagLastBranch + kFlagTimebase;
enum class Status {
OK,
// An invalid argument of some kind.
INVALID_ARGS,
// No room for more events.
MAX_EVENTS,
};
static std::string StatusToString(Status status);
Config() = default;
~Config() = default;
// Use the default default copy/move constructors.
// Remove existing contents.
void Reset();
// Collect data for event |event|.
// If |rate| is zero then |flags| may only contain |kFlagOs,kFlagUser|.
// If |rate| is non-zero then |flags| may contain any valid combination.
// If |flags| contains |kFlagTimebase| then events with a zero rate are
// collected at the same time as this event. Only one event may be added with
// |kFlagTimebase|.
// A value of zero for |flags| is equivalent to |kFlagOs|kFlagUser|.
Status AddEvent(EventId event, EventRate rate, uint32_t flags);
// Return the number of events.
size_t GetEventCount() const;
// Return the "mode" of data collection.
CollectionMode GetMode() const;
// Call |func| for each event.
// The iteration order is unspecified.
void IterateOverEvents(IterateFunc func) const;
// Return a string form of the configuration, for display purposes.
// The order of appearance of events in the string is unspecified.
std::string ToString();
private:
struct EventHash {
inline std::size_t operator()(const EventConfig& event) const { return event.event; }
};
struct EventEqual {
inline bool operator()(const EventConfig& e1, const EventConfig& e2) const {
return e1.event == e2.event;
}
};
// Each event may appear at most once.
std::unordered_set<EventConfig, EventHash, EventEqual> events_;
};
} // namespace perfmon
#endif // GARNET_LIB_PERFMON_CONFIG_H_