diff --git a/include/lo2s/perf/bio/writer.hpp b/include/lo2s/perf/bio/writer.hpp index e9eed62a..ff259b35 100644 --- a/include/lo2s/perf/bio/writer.hpp +++ b/include/lo2s/perf/bio/writer.hpp @@ -82,7 +82,7 @@ class Writer void write(IoReaderIdentity& identity, TracepointSampleType* header) { - if (identity.tracepoint == bio_queue_) + if (identity.tracepoint() == bio_queue_) { struct RecordBioQueue* event = (RecordBioQueue*)header; @@ -112,7 +112,7 @@ class Writer time_converter_(event->header.time), handle, mode, otf2::common::io_operation_flag_type::non_blocking, size, event->sector); } - else if (identity.tracepoint == bio_issue_) + else if (identity.tracepoint() == bio_issue_) { struct RecordBlock* event = (RecordBlock*)header; @@ -129,7 +129,7 @@ class Writer writer << otf2::event::io_operation_issued(time_converter_(event->header.time), handle, event->sector); } - else if (identity.tracepoint == bio_complete_) + else if (identity.tracepoint() == bio_complete_) { struct RecordBlock* event = (RecordBlock*)header; @@ -150,7 +150,7 @@ class Writer } else { - throw std::runtime_error("tracepoint " + identity.tracepoint.name() + + throw std::runtime_error("tracepoint " + identity.tracepoint().name() + " not valid for block I/O"); } } @@ -164,7 +164,7 @@ class Writer bio_complete_ = perf::EventProvider::instance().create_tracepoint_event("block:block_rq_complete"); - return { bio_queue_, bio_issue_, bio_complete_ }; + return { bio_queue_.value(), bio_issue_.value(), bio_complete_.value() }; } private: @@ -185,9 +185,9 @@ class Writer time::Converter& time_converter_; // Unavailable until get_tracepoints() is called - perf::tracepoint::TracepointEvent bio_queue_; - perf::tracepoint::TracepointEvent bio_issue_; - perf::tracepoint::TracepointEvent bio_complete_; + std::optional bio_queue_; + std::optional bio_issue_; + std::optional bio_complete_; // The unit "sector" is always 512 bit large, regardless of the actual sector size of the device static constexpr int SECTOR_SIZE = 512; diff --git a/include/lo2s/perf/counter/counter_collection.hpp b/include/lo2s/perf/counter/counter_collection.hpp index d6bf6f0f..f0269ed9 100644 --- a/include/lo2s/perf/counter/counter_collection.hpp +++ b/include/lo2s/perf/counter/counter_collection.hpp @@ -23,6 +23,7 @@ #include +#include #include namespace lo2s @@ -33,14 +34,14 @@ namespace counter { struct CounterCollection { - Event leader; + std::optional leader_; std::vector counters; double get_scale(int index) const { if (index == 0) { - return leader.scale(); + return leader_.value().scale(); } else { @@ -48,9 +49,14 @@ struct CounterCollection } } + Event& leader() const + { + return const_cast(leader_.value()); + } + friend bool operator==(const CounterCollection& lhs, const CounterCollection& rhs) { - if (lhs.leader == rhs.leader) + if (lhs.leader_.value() == rhs.leader_.value()) { return lhs.counters == rhs.counters; } @@ -59,11 +65,11 @@ struct CounterCollection friend bool operator<(const CounterCollection& lhs, const CounterCollection& rhs) { - if (lhs.leader == rhs.leader) + if (lhs.leader_.value() == rhs.leader_.value()) { return lhs.counters < rhs.counters; } - return lhs.leader < rhs.leader; + return lhs.leader_.value() < rhs.leader_.value(); } }; diff --git a/include/lo2s/perf/counter/counter_provider.hpp b/include/lo2s/perf/counter/counter_provider.hpp index 3071e225..662bd84c 100644 --- a/include/lo2s/perf/counter/counter_provider.hpp +++ b/include/lo2s/perf/counter/counter_provider.hpp @@ -25,6 +25,7 @@ #include #include +#include #include namespace lo2s @@ -58,7 +59,7 @@ class CounterProvider std::vector get_tracepoint_event_names(); private: - Event group_leader_; + std::optional group_leader_; std::vector group_events_; std::vector userspace_events_; std::vector tracepoint_events_; diff --git a/include/lo2s/perf/event.hpp b/include/lo2s/perf/event.hpp index 06d65c10..78f5607f 100644 --- a/include/lo2s/perf/event.hpp +++ b/include/lo2s/perf/event.hpp @@ -74,7 +74,6 @@ class Event public: Event(const std::string& name, perf_type_id type, std::uint64_t config, std::uint64_t config1 = 0); - Event(); /** * returns an opened instance of any Event object @@ -214,9 +213,9 @@ class Event class SysfsEvent : public Event { public: - using Event::Event; SysfsEvent(const std::string& ev_name, bool enable_on_exec = false); + void make_invalid(); void use_sampling_options(const bool& use_pebs, const bool& sampling, const bool& enable_cct); }; diff --git a/include/lo2s/perf/io_reader.hpp b/include/lo2s/perf/io_reader.hpp index 98797ca2..6003b026 100644 --- a/include/lo2s/perf/io_reader.hpp +++ b/include/lo2s/perf/io_reader.hpp @@ -63,17 +63,22 @@ struct IoReaderIdentity { IoReaderIdentity(std::string tracepoint_name, Cpu cpu) : cpu(cpu) { - tracepoint = EventProvider::instance().create_tracepoint_event(tracepoint_name); + tracepoint_.value() = EventProvider::instance().create_tracepoint_event(tracepoint_name); } - tracepoint::TracepointEvent tracepoint; + std::optional tracepoint_; Cpu cpu; + tracepoint::TracepointEvent tracepoint() + { + return tracepoint_.value(); + } + friend bool operator>(const IoReaderIdentity& lhs, const IoReaderIdentity& rhs) { if (lhs.cpu == rhs.cpu) { - return lhs.tracepoint > rhs.tracepoint; + return lhs.tracepoint_.value() > rhs.tracepoint_.value(); } return lhs.cpu > rhs.cpu; @@ -83,7 +88,7 @@ struct IoReaderIdentity { if (lhs.cpu == rhs.cpu) { - return lhs.tracepoint < rhs.tracepoint; + return lhs.tracepoint_.value() < rhs.tracepoint_.value(); } return lhs.cpu < rhs.cpu; @@ -97,7 +102,7 @@ class IoReader : public PullReader { try { - event_ = identity_.tracepoint.open(identity.cpu); + event_ = identity_.tracepoint().open(identity.cpu); } catch (const std::system_error& e) { diff --git a/include/lo2s/perf/tracepoint/event.hpp b/include/lo2s/perf/tracepoint/event.hpp index 0b0b9368..ffc7001a 100644 --- a/include/lo2s/perf/tracepoint/event.hpp +++ b/include/lo2s/perf/tracepoint/event.hpp @@ -46,10 +46,6 @@ class TracepointEvent : public Event ParseError(const std::string& what, int error_code); }; - TracepointEvent() : id_(-1) - { - } - TracepointEvent(const std::string& name, bool enable_on_exec = false); void parse_format(); diff --git a/include/lo2s/trace/trace.hpp b/include/lo2s/trace/trace.hpp index 5da43324..2a4f7cc9 100644 --- a/include/lo2s/trace/trace.hpp +++ b/include/lo2s/trace/trace.hpp @@ -247,7 +247,7 @@ class Trace if (scope.type == MeasurementScopeType::GROUP_METRIC) { - metric_class.add_member(get_event_metric_member(counter_collection.leader)); + metric_class.add_member(get_event_metric_member(counter_collection.leader())); } for (const auto& counter : counter_collection.counters) diff --git a/src/perf/counter/counter_provider.cpp b/src/perf/counter/counter_provider.cpp index 5b0b20b7..eb6922c5 100644 --- a/src/perf/counter/counter_provider.cpp +++ b/src/perf/counter/counter_provider.cpp @@ -122,7 +122,7 @@ void CounterProvider::initialize_group_counters(const std::string& leader, try { // skip event if it has already been declared as group leader - if (ev == group_leader_.name()) + if (ev == group_leader_.value().name()) { Log::info() << "'" << ev << "' has been requested as both the metric leader event and a regular " @@ -150,9 +150,9 @@ CounterCollection CounterProvider::collection_for(MeasurementScope scope) CounterCollection res; if (scope.type == MeasurementScopeType::GROUP_METRIC) { - if (group_leader_.is_available_in(scope.scope)) + if (group_leader_.value().is_available_in(scope.scope)) { - res.leader = group_leader_; + res.leader() = group_leader_.value(); for (auto& ev : group_events_) { if (ev.is_available_in(scope.scope)) @@ -219,7 +219,7 @@ bool CounterProvider::has_group_counters(ExecutionScope scope) } else { - return group_leader_.is_available_in(scope) && + return group_leader_.value().is_available_in(scope) && std::any_of(group_events_.begin(), group_events_.end(), [scope](const auto& ev) { return ev.is_available_in(scope); }); } diff --git a/src/perf/counter/group/reader.cpp b/src/perf/counter/group/reader.cpp index 4445b358..39d0dd45 100644 --- a/src/perf/counter/group/reader.cpp +++ b/src/perf/counter/group/reader.cpp @@ -55,11 +55,11 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) { if (config().metric_use_frequency) { - counter_collection_.leader.sample_freq(config().metric_frequency); + counter_collection_.leader().sample_freq(config().metric_frequency); } else { - counter_collection_.leader.sample_period(config().metric_count); + counter_collection_.leader().sample_period(config().metric_count); } do @@ -67,15 +67,15 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) try { counter_leader_ = - counter_collection_.leader.open_as_group_leader(scope, config().cgroup_fd); + counter_collection_.leader().open_as_group_leader(scope, config().cgroup_fd); } catch (const std::system_error& e) { // perf_try_event_open was used here before if (counter_leader_.value().get_fd() < 0 && errno == EACCES && - !counter_collection_.leader.attr().exclude_kernel && perf_event_paranoid() > 1) + !counter_collection_.leader().attr().exclude_kernel && perf_event_paranoid() > 1) { - counter_collection_.leader.mut_attr().exclude_kernel = 1; + counter_collection_.leader().mut_attr().exclude_kernel = 1; perf_warn_paranoid(); continue; @@ -89,14 +89,16 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) } } while (!counter_leader_.value().is_valid()); - Log::debug() << "counter::Reader: leader event: '" << counter_collection_.leader.name() << "'"; + Log::debug() << "counter::Reader: leader event: '" << counter_collection_.leader().name() + << "'"; for (auto& counter_ev : counter_collection_.counters) { if (counter_ev.is_available_in(scope)) { std::optional counter = std::nullopt; - counter_ev.mut_attr().exclude_kernel = counter_collection_.leader.attr().exclude_kernel; + counter_ev.mut_attr().exclude_kernel = + counter_collection_.leader().attr().exclude_kernel; try { diff --git a/src/perf/event.cpp b/src/perf/event.cpp index 69b03cee..5fb3305a 100644 --- a/src/perf/event.cpp +++ b/src/perf/event.cpp @@ -112,19 +112,6 @@ static constexpr std::uint64_t apply_mask(std::uint64_t value, std::uint64_t mas return res; } -Event::Event() : name_("") -{ - memset(&attr_, 0, sizeof(attr_)); - attr_.size = sizeof(attr_); - attr_.type = PERF_TYPE_RAW; - - attr_.config = 0; - attr_.config1 = 0; - - attr_.sample_period = 0; - attr_.exclude_kernel = 1; -} - Event::Event(const std::string& name, perf_type_id type, std::uint64_t config, std::uint64_t config1) : name_(name) @@ -361,7 +348,8 @@ bool Event::degrade_precision() } } -SysfsEvent::SysfsEvent(const std::string& ev_name, bool enable_on_exec) : Event() +SysfsEvent::SysfsEvent(const std::string& ev_name, bool enable_on_exec) +: Event(ev_name, static_cast(0), 0) { set_common_attrs(enable_on_exec); @@ -483,6 +471,11 @@ SysfsEvent::SysfsEvent(const std::string& ev_name, bool enable_on_exec) : Event( } } +void SysfsEvent::make_invalid() +{ + availability_ = Availability::UNAVAILABLE; +} + void SysfsEvent::use_sampling_options(const bool& use_pebs, const bool& sampling, const bool& enable_cct) { diff --git a/src/perf/event_provider.cpp b/src/perf/event_provider.cpp index aae5399d..43eb8b11 100644 --- a/src/perf/event_provider.cpp +++ b/src/perf/event_provider.cpp @@ -301,7 +301,10 @@ Event EventProvider::cache_event(const std::string& name) catch (const InvalidEvent& e) { // emplace unavailable Sampling Event - event_map_.emplace(name, SysfsEvent()); + SysfsEvent event = EventProvider::instance().create_sysfs_event(name, false); + event.make_invalid(); + + event_map_.emplace(name, event); throw e; } } diff --git a/src/perf/tracepoint/event.cpp b/src/perf/tracepoint/event.cpp index 6136014f..70671511 100644 --- a/src/perf/tracepoint/event.cpp +++ b/src/perf/tracepoint/event.cpp @@ -30,13 +30,13 @@ namespace tracepoint { TracepointEvent::TracepointEvent(const std::string& name, bool enable_on_exec) -: Event(), name_(name) +: Event(name, PERF_TYPE_TRACEPOINT, 0), name_(name) { set_common_attrs(enable_on_exec); parse_format(); + // update to correct config (id_ set in parse_format()) attr_.config = id_; - attr_.type = PERF_TYPE_TRACEPOINT; attr_.sample_type |= PERF_SAMPLE_RAW | PERF_SAMPLE_IDENTIFIER; update_availability();