| // 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_ |