From dce31c2378afdc122b06372463caf6c0e01c34a2 Mon Sep 17 00:00:00 2001 From: Christian von Elm Date: Tue, 18 Apr 2023 16:29:31 +0200 Subject: [PATCH 1/2] fix(EventDescription): Turn EventDescription into real class --- .../lo2s/perf/counter/counter_collection.hpp | 4 +- include/lo2s/perf/event_description.hpp | 155 +++++++++++-- include/lo2s/perf/event_provider.hpp | 37 +--- include/lo2s/perf/sample/reader.hpp | 30 +-- include/lo2s/perf/util.hpp | 3 +- include/lo2s/trace/trace.hpp | 4 +- src/config.cpp | 26 +-- src/perf/counter/group/reader.cpp | 23 +- src/perf/counter/userspace/reader.cpp | 2 +- src/perf/event_provider.cpp | 207 ++++++------------ src/perf/util.cpp | 26 --- 11 files changed, 239 insertions(+), 278 deletions(-) diff --git a/include/lo2s/perf/counter/counter_collection.hpp b/include/lo2s/perf/counter/counter_collection.hpp index 46877cbc..30e3c244 100644 --- a/include/lo2s/perf/counter/counter_collection.hpp +++ b/include/lo2s/perf/counter/counter_collection.hpp @@ -39,11 +39,11 @@ struct CounterCollection { if (index == 0) { - return leader.scale; + return leader.scale(); } else { - return counters[index - 1].scale; + return counters[index - 1].scale(); } } friend bool operator==(const CounterCollection& lhs, const CounterCollection& rhs) diff --git a/include/lo2s/perf/event_description.hpp b/include/lo2s/perf/event_description.hpp index 69d5ba8d..33e5320c 100644 --- a/include/lo2s/perf/event_description.hpp +++ b/include/lo2s/perf/event_description.hpp @@ -21,7 +21,10 @@ #pragma once +#include +#include #include +#include #include #include @@ -48,16 +51,54 @@ struct EventDescription { EventDescription(const std::string& name, perf_type_id type, std::uint64_t config, std::uint64_t config1 = 0, std::set cpus = std::set(), - double scale = 1, std::string unit = "#", - Availability availability = Availability::UNAVAILABLE) - : name(name), type(type), config(config), config1(config1), scale(scale), unit(unit), - availability(availability), cpus_(cpus) + double scale = 1, std::string unit = "#") + : name_(name), type_(type), config_(config), config1_(config1), scale_(scale), unit_(unit), + cpus_(cpus) { + struct perf_event_attr attr = perf_event_attr(); + + int proc_fd = perf_event_open(&attr, ExecutionScope(Thread(0)), -1, 0); + int sys_fd = perf_event_open(&attr, ExecutionScope(*supported_cpus().begin()), -1, 0); + + if (sys_fd == -1 && proc_fd == -1) + { + attr.exclude_kernel = 1; + proc_fd = perf_event_open(&attr, ExecutionScope(Thread(0)), -1, 0); + sys_fd = perf_event_open(&attr, ExecutionScope(*supported_cpus().begin()), -1, 0); + } + + if (sys_fd == -1 && proc_fd == -1) + { + switch (errno) + { + case ENOTSUP: + Log::debug() << "perf event not supported by the running kernel: " << name_; + break; + default: + Log::debug() << "perf event " << name_ + << " not available: " << std::string(std::strerror(errno)); + break; + } + + availability_ = Availability::UNAVAILABLE; + } + else if (sys_fd == -1) + { + availability_ = Availability::PROCESS_MODE; + } + else if (proc_fd == -1) + { + availability_ = Availability::SYSTEM_MODE; + } + else + { + availability_ = Availability::UNIVERSAL; + } } EventDescription() - : name(""), type(static_cast(-1)), config(0), config1(0), scale(1), unit("#"), - availability(Availability::UNAVAILABLE) + : name_(""), type_(static_cast(-1)), config_(0), config1_(0), scale_(1), + unit_("#"), availability_(Availability::UNAVAILABLE) { } @@ -79,30 +120,106 @@ struct EventDescription friend bool operator==(const EventDescription& lhs, const EventDescription& rhs) { - return (lhs.type == rhs.type) && (lhs.config == rhs.config) && (lhs.config1 == rhs.config1); + return (lhs.type_ == rhs.type_) && (lhs.config_ == rhs.config_) && + (lhs.config1_ == rhs.config1_); } friend bool operator<(const EventDescription& lhs, const EventDescription& rhs) { - if (lhs.type == rhs.type) + if (lhs.type_ == rhs.type_) { - if (lhs.config == rhs.config) + if (lhs.config_ == rhs.config_) { - return lhs.config1 < rhs.config1; + return lhs.config1_ < rhs.config1_; } - return lhs.config < rhs.config; + return lhs.config_ < rhs.config_; + } + return lhs.type_ < rhs.type_; + } + + struct perf_event_attr perf_event_attr() const + { + struct perf_event_attr attr; + memset(&attr, 0, sizeof(struct perf_event_attr)); + + attr.size = sizeof(struct perf_event_attr); + + attr.type = type_; + attr.config = config_; + attr.config1 = config1_; + + return attr; + } + + std::string name() const + { + return name_; + } + + std::string description() const + { + if (availability_ == Availability::UNIVERSAL) + { + return name_; + } + else if (availability_ == Availability::SYSTEM_MODE) + { + return fmt::format("{} [SYS]", name_); + } + else if (availability_ == Availability::PROCESS_MODE) + { + return fmt::format("{} [PROC]", name_); + } + + return ""; + } + + bool is_valid() const + { + return availability_ != Availability::UNAVAILABLE; + } + + double scale() const + { + return scale_; + } + + std::string unit() const + { + return unit_; + } + + int open_counter(ExecutionScope scope, int group_fd) + { + struct perf_event_attr perf_attr = perf_event_attr(); + perf_attr.sample_period = 0; + perf_attr.exclude_kernel = config().exclude_kernel; + // Needed when scaling multiplexed events, and recognize activation phases + perf_attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; + +#if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID) + perf_attr.use_clockid = config().use_clockid; + perf_attr.clockid = config().clockid; +#endif + + int fd = perf_try_event_open(&perf_attr, scope, group_fd, 0, config().cgroup_fd); + if (fd < 0) + { + Log::error() << "perf_event_open for counter failed"; + throw_errno(); } - return lhs.type < rhs.type; + return fd; } - std::string name; - perf_type_id type; - std::uint64_t config; - std::uint64_t config1; - double scale; - std::string unit; - Availability availability; private: + std::string name_; + perf_type_id type_; + std::uint64_t config_; + std::uint64_t config1_; + double scale_; + std::string unit_; + Availability availability_; + std::set cpus_; }; } // namespace perf diff --git a/include/lo2s/perf/event_provider.hpp b/include/lo2s/perf/event_provider.hpp index 6ad2b37c..af51de55 100644 --- a/include/lo2s/perf/event_provider.hpp +++ b/include/lo2s/perf/event_provider.hpp @@ -36,42 +36,7 @@ namespace perf class EventProvider { public: - struct DescriptionCache - { - private: - DescriptionCache() - : description(std::string(), static_cast(-1), 0, 0), valid_(false) - { - } - - public: - DescriptionCache(const EventDescription& description) - : description(description), valid_(true) - { - } - - DescriptionCache(EventDescription&& description) - : description(std::move(description)), valid_(true) - { - } - - static DescriptionCache make_invalid() - { - return DescriptionCache(); - } - - bool is_valid() const - { - return valid_; - } - - EventDescription description; - - private: - bool valid_; - }; - - using EventMap = std::unordered_map; + using EventMap = std::unordered_map; EventProvider(); EventProvider(const EventProvider&) = delete; diff --git a/include/lo2s/perf/sample/reader.hpp b/include/lo2s/perf/sample/reader.hpp index ffec9d92..6b5b5271 100644 --- a/include/lo2s/perf/sample/reader.hpp +++ b/include/lo2s/perf/sample/reader.hpp @@ -84,15 +84,7 @@ class Reader : public EventReader Log::debug() << "initializing event_reader for:" << scope.name() << ", enable_on_exec: " << enable_on_exec; - struct perf_event_attr perf_attr = common_perf_event_attrs(); - - if (config().use_pebs) - { - perf_attr.use_clockid = 0; - } - - perf_attr.exclude_kernel = config().exclude_kernel; - perf_attr.sample_period = config().sampling_period; + struct perf_event_attr perf_attr; if (config().sampling) { @@ -103,19 +95,31 @@ class Reader : public EventReader Log::debug() << "using sampling event \'" << config().sampling_event << "\', period: " << config().sampling_period; - - perf_attr.type = sampling_event.type; - perf_attr.config = sampling_event.config; - perf_attr.config1 = sampling_event.config1; + perf_attr = sampling_event.perf_event_attr(); perf_attr.mmap = 1; + perf_attr.disabled = 1; + +#if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID) + perf_attr.use_clockid = config().use_clockid; + perf_attr.clockid = config().clockid; +#endif + // When we poll on the fd given by perf_event_open, wakeup, when our buffer is 80% full + // Default behaviour is to wakeup on every event, which is horrible performance wise + perf_attr.watermark = 1; + perf_attr.wakeup_watermark = + static_cast(0.8 * config().mmap_pages * get_page_size()); } else { + perf_attr = common_perf_event_attrs(); + // Set up a dummy event for recording calling context enter/leaves only perf_attr.type = PERF_TYPE_SOFTWARE; perf_attr.config = PERF_COUNT_SW_DUMMY; } + perf_attr.exclude_kernel = config().exclude_kernel; + perf_attr.sample_period = config().sampling_period; perf_attr.sample_id_all = 1; // Generate PERF_RECORD_COMM events to trace changes to the command diff --git a/include/lo2s/perf/util.hpp b/include/lo2s/perf/util.hpp index a9ca34f3..6e51025c 100644 --- a/include/lo2s/perf/util.hpp +++ b/include/lo2s/perf/util.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include extern "C" { @@ -19,7 +19,6 @@ struct perf_event_attr common_perf_event_attrs(); void perf_warn_paranoid(); void perf_check_disabled(); -int perf_event_description_open(ExecutionScope scope, const EventDescription& desc, int group_fd); int perf_try_event_open(struct perf_event_attr* perf_attr, ExecutionScope scope, int group_fd, unsigned long flags, int cgroup_fd = -1); diff --git a/include/lo2s/trace/trace.hpp b/include/lo2s/trace/trace.hpp index ea828e28..313cbb29 100644 --- a/include/lo2s/trace/trace.hpp +++ b/include/lo2s/trace/trace.hpp @@ -171,9 +171,9 @@ class Trace otf2::definition::metric_member& get_event_metric_member(perf::EventDescription event) { return registry_.emplace( - ByEventDescription(event), intern(event.name), intern(event.name), + ByEventDescription(event), intern(event.name()), intern(event.name()), otf2::common::metric_type::other, otf2::common::metric_mode::accumulated_start, - otf2::common::type::Double, otf2::common::base_type::decimal, 0, intern(event.unit)); + otf2::common::type::Double, otf2::common::base_type::decimal, 0, intern(event.unit())); } otf2::definition::metric_class& perf_metric_class(MeasurementScope scope) { diff --git a/src/config.cpp b/src/config.cpp index 80cb12dc..0e88ebe2 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -74,30 +74,10 @@ static inline void print_availability(std::ostream& os, const std::string& descr std::vector event_names; for (const auto& ev : events) { - if (ev.availability == perf::Availability::UNAVAILABLE) + if (ev.is_valid()) { - continue; + event_names.push_back(ev.description()); } - - std::string availability = ""; - std::string cpu = ""; - if (ev.availability == perf::Availability::PROCESS_MODE) - { - availability = " *"; - } - else if (ev.availability == perf::Availability::SYSTEM_MODE) - { - availability = " #"; - } - if (ev.supported_cpus() != Topology::instance().cpus()) - { - const auto& cpus = ev.supported_cpus(); - cpu = - fmt::format(" [ CPUs {}-{} ]", std::min_element(cpus.begin(), cpus.end())->as_int(), - std::max_element(cpus.begin(), cpus.end())->as_int()); - } - - event_names.push_back(ev.name + availability + cpu); } list_arguments_sorted(os, description, event_names); } @@ -670,7 +650,7 @@ void parse_program_options(int argc, const char** argv) { for (const auto& mem_event : platform::get_mem_events()) { - perf_group_events.emplace_back(mem_event.name); + perf_group_events.emplace_back(mem_event.name()); } perf_group_events.emplace_back("instructions"); perf_group_events.emplace_back("cpu-cycles"); diff --git a/src/perf/counter/group/reader.cpp b/src/perf/counter/group/reader.cpp index 8f5fc9b7..43a00315 100644 --- a/src/perf/counter/group/reader.cpp +++ b/src/perf/counter/group/reader.cpp @@ -53,11 +53,19 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) CounterProvider::instance().collection_for(MeasurementScope::group_metric(scope))), counter_buffer_(counter_collection_.counters.size() + 1) { - perf_event_attr leader_attr = common_perf_event_attrs(); + perf_event_attr leader_attr = counter_collection_.leader.perf_event_attr(); - leader_attr.type = counter_collection_.leader.type; - leader_attr.config = counter_collection_.leader.config; - leader_attr.config1 = counter_collection_.leader.config1; + leader_attr.disabled = 1; + +#if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID) + leader_attr.use_clockid = config().use_clockid; + leader_attr.clockid = config().clockid; +#endif + // When we poll on the fd given by perf_event_open, wakeup, when our buffer is 80% full + // Default behaviour is to wakeup on every event, which is horrible performance wise + leader_attr.watermark = 1; + leader_attr.wakeup_watermark = + static_cast(0.8 * config().mmap_pages * get_page_size()); leader_attr.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_READ; leader_attr.freq = config().metric_use_frequency; @@ -86,7 +94,7 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) throw_errno(); } - Log::debug() << "counter::Reader: leader event: '" << counter_collection_.leader.name << "'"; + Log::debug() << "counter::Reader: leader event: '" << counter_collection_.leader.name() << "'"; counter_fds_.reserve(counter_collection_.counters.size()); for (auto& description : counter_collection_.counters) @@ -95,12 +103,11 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) { try { - counter_fds_.emplace_back( - perf_event_description_open(scope, description, group_leader_fd_)); + counter_fds_.emplace_back(description.open_counter(scope, group_leader_fd_)); } catch (const std::system_error& e) { - Log::error() << "failed to add counter '" << description.name + Log::error() << "failed to add counter '" << description.name() << "': " << e.code().message(); if (e.code().value() == EINVAL) diff --git a/src/perf/counter/userspace/reader.cpp b/src/perf/counter/userspace/reader.cpp index 1a466659..37a6662e 100644 --- a/src/perf/counter/userspace/reader.cpp +++ b/src/perf/counter/userspace/reader.cpp @@ -64,7 +64,7 @@ Reader::Reader(ExecutionScope scope) for (auto& event : counter_collection_.counters) { - counter_fds_.emplace_back(perf_event_description_open(scope, event, -1)); + counter_fds_.emplace_back(event.open_counter(scope, -1)); } } diff --git a/src/perf/event_provider.cpp b/src/perf/event_provider.cpp index 615f9f5c..cb682eaa 100644 --- a/src/perf/event_provider.cpp +++ b/src/perf/event_provider.cpp @@ -49,14 +49,21 @@ extern "C" namespace { -#define PERF_EVENT(name, type, id) \ +#define PERF_EVENT(name, id) \ { \ - (name), (type), (id) \ + (name), (id) \ } -#define PERF_EVENT_HW(name, id) PERF_EVENT(name, PERF_TYPE_HARDWARE, PERF_COUNT_HW_##id) -#define PERF_EVENT_SW(name, id) PERF_EVENT(name, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##id) +#define PERF_EVENT_HW(name, id) PERF_EVENT(name, PERF_COUNT_HW_##id) +#define PERF_EVENT_SW(name, id) PERF_EVENT(name, PERF_COUNT_SW_##id) -static lo2s::perf::EventDescription HW_EVENT_TABLE[] = { +template +struct string_to_id +{ + std::string name; + T id; +}; + +static string_to_id HW_EVENT_TABLE[] = { PERF_EVENT_HW("cpu-cycles", CPU_CYCLES), PERF_EVENT_HW("instructions", INSTRUCTIONS), PERF_EVENT_HW("cache-references", CACHE_REFERENCES), @@ -75,7 +82,7 @@ static lo2s::perf::EventDescription HW_EVENT_TABLE[] = { #endif }; -static lo2s::perf::EventDescription SW_EVENT_TABLE[] = { +static string_to_id SW_EVENT_TABLE[] = { PERF_EVENT_SW("cpu-clock", CPU_CLOCK), PERF_EVENT_SW("task-clock", TASK_CLOCK), PERF_EVENT_SW("page-faults", PAGE_FAULTS), @@ -91,17 +98,6 @@ static lo2s::perf::EventDescription SW_EVENT_TABLE[] = { #endif }; -#define PERF_MAKE_CACHE_ID(id) (id) -#define PERF_MAKE_CACHE_OP_ID(id) ((id) << 8) -#define PERF_MAKE_CACHE_OP_RES_ID(id) ((id) << 16) - -template -struct string_to_id -{ - const char* name; - T id; -}; - static string_to_id CACHE_NAME_TABLE[] = { { "L1-dcache", PERF_COUNT_HW_CACHE_L1D }, { "L1-icache", PERF_COUNT_HW_CACHE_L1I }, { "LLC", PERF_COUNT_HW_CACHE_LL }, { "dTLB", PERF_COUNT_HW_CACHE_DTLB }, @@ -132,20 +128,9 @@ inline constexpr std::uint64_t make_cache_config(perf_hw_cache_id cache, perf_hw return cache | (op << 8) | (op_result << 16); } -template -inline constexpr std::size_t array_size(T (&)[N]) -{ - return N; -} - -constexpr std::uint64_t operator"" _u64(unsigned long long int lit) -{ - return static_cast(lit); -} - constexpr std::uint64_t bit(int bitnumber) { - return static_cast(1_u64 << bitnumber); + return static_cast(1ULL << bitnumber); } } // namespace @@ -156,92 +141,31 @@ namespace perf const EventDescription sysfs_read_event(const std::string& ev_desc); -static bool event_is_openable(EventDescription& ev) -{ - struct perf_event_attr attr; - memset(&attr, 0, sizeof(attr)); - attr.size = sizeof(attr); - attr.type = ev.type; - attr.config = ev.config; - attr.config1 = ev.config1; - - int proc_fd = perf_event_open(&attr, ExecutionScope(Thread(0)), -1, 0); - int sys_fd = perf_event_open(&attr, ExecutionScope(*ev.supported_cpus().begin()), -1, 0); - if (sys_fd == -1 && proc_fd == -1) - { - Log::debug() << "perf event not openable, retrying with exclude_kernel=1"; - - attr.exclude_kernel = 1; - int proc_fd = perf_event_open(&attr, ExecutionScope(Thread(0)), -1, 0); - int sys_fd = perf_event_open(&attr, ExecutionScope(*ev.supported_cpus().begin()), -1, 0); - - if (sys_fd == -1 && proc_fd == -1) - { - switch (errno) - { - case ENOTSUP: - Log::debug() << "perf event not supported by the running kernel: " << ev.name; - break; - default: - Log::debug() << "perf event " << ev.name - << " not available: " << std::string(std::strerror(errno)); - break; - } - return false; - } - } - else if (sys_fd == -1) - { - close(proc_fd); - ev.availability = Availability::PROCESS_MODE; - } - else if (proc_fd == -1) - { - close(sys_fd); - ev.availability = Availability::SYSTEM_MODE; - } - else - { - ev.availability = Availability::UNIVERSAL; - close(sys_fd); - close(proc_fd); - } - - return true; -} - static void populate_event_map(EventProvider::EventMap& map) { Log::info() << "checking available events..."; - map.reserve(array_size(HW_EVENT_TABLE) + array_size(SW_EVENT_TABLE) + - array_size(CACHE_NAME_TABLE) * array_size(CACHE_OPERATION_TABLE)); + for (auto& ev : HW_EVENT_TABLE) { - map.emplace(ev.name, - event_is_openable(ev) ? ev : EventProvider::DescriptionCache::make_invalid()); + map.emplace(ev.name, EventDescription(ev.name, PERF_TYPE_HARDWARE, ev.id)); } for (auto& ev : SW_EVENT_TABLE) { - map.emplace(ev.name, - event_is_openable(ev) ? ev : EventProvider::DescriptionCache::make_invalid()); + map.emplace(ev.name, EventDescription(ev.name, PERF_TYPE_SOFTWARE, ev.id)); } - std::stringstream name_fmt; for (auto& cache : CACHE_NAME_TABLE) { for (auto& operation : CACHE_OPERATION_TABLE) { - name_fmt.str(std::string()); - name_fmt << cache.name << '-' << operation.name; + std::string cache_str = fmt::format("{}-{}", cache.name, operation.name); EventDescription ev( - name_fmt.str(), PERF_TYPE_HW_CACHE, + cache_str, PERF_TYPE_HW_CACHE, make_cache_config(cache.id, operation.id.op_id, operation.id.result_id)); - map.emplace(ev.name, event_is_openable(ev) ? - ev : - EventProvider::DescriptionCache::make_invalid()); + map.emplace(ev.name(), ev); } } } @@ -378,38 +302,6 @@ static constexpr std::uint64_t apply_mask(std::uint64_t value, std::uint64_t mas return res; } -static void event_description_update(EventDescription& event, std::uint64_t value, - const std::string& format) -{ - // Parse config terms // - - /* Format: : - * - * We only assign the terms 'config' and 'config1'. - * - * */ - - static constexpr auto npos = std::string::npos; - const auto colon = format.find_first_of(':'); - if (colon == npos) - { - throw EventProvider::InvalidEvent("invalid format description: missing colon"); - } - - const auto target_config = format.substr(0, colon); - const auto mask = parse_bitmask(format.substr(colon + 1)); - - if (target_config == "config") - { - event.config |= apply_mask(value, mask); - } - - if (target_config == "config1") - { - event.config1 |= apply_mask(value, mask); - } -} - const EventDescription raw_read_event(const std::string& ev_desc) { uint64_t code = std::stoull(ev_desc.substr(1), nullptr, 16); @@ -462,6 +354,13 @@ const EventDescription sysfs_read_event(const std::string& ev_desc) * * */ + std::underlying_type::type type; + uint64_t config = 0; + uint64_t config1 = 0; + std::set cpus; + double scale; + std::string unit; + enum EVENT_DESCRIPTION_REGEX_GROUPS { ED_WHOLE_MATCH, @@ -486,7 +385,6 @@ const EventDescription sysfs_read_event(const std::string& ev_desc) std::filesystem::path("/sys/bus/event_source/devices") / pmu_name; // read PMU type id - std::underlying_type::type type; std::ifstream type_stream(pmu_path / "type"); type_stream >> type; if (!type_stream) @@ -495,11 +393,9 @@ const EventDescription sysfs_read_event(const std::string& ev_desc) throw EventProvider::InvalidEvent("unknown PMU '"s + pmu_name + "'"); } - std::set cpus; auto cpuids = parse_list_from_file(pmu_path / "cpus"); std::transform(cpuids.begin(), cpuids.end(), std::inserter(cpus, cpus.end()), [](uint32_t cpuid) { return Cpu(cpuid); }); - EventDescription event(ev_desc, static_cast(type), 0, 0, cpus); // Parse event configuration from sysfs // @@ -560,30 +456,51 @@ const EventDescription sysfs_read_event(const std::string& ev_desc) std::uint64_t val = std::stol(value, nullptr, 0); Log::debug() << "parsing config assignment: " << term << " = " << std::hex << std::showbase << val << std::dec << std::noshowbase; - event_description_update(event, val, format); + + static constexpr auto npos = std::string::npos; + const auto colon = format.find_first_of(':'); + if (colon == npos) + { + throw EventProvider::InvalidEvent("invalid format description: missing colon"); + } + + const auto target_config = format.substr(0, colon); + const auto mask = parse_bitmask(format.substr(colon + 1)); + + if (target_config == "config") + { + config |= apply_mask(val, mask); + } + + if (target_config == "config1") + { + config1 |= apply_mask(val, mask); + } ev_cfg = kv_match.suffix(); } Log::debug() << std::hex << std::showbase << "parsed event description: " << pmu_name << "/" - << event_name << "/type=" << event.type << ",config=" << event.config - << ",config1=" << event.config1 << std::dec << std::noshowbase << "/"; + << event_name << "/type=" << type << ",config=" << config << ",config1=" << config1 + << std::dec << std::noshowbase << "/"; std::ifstream scale_stream(event_path.string() + ".scale"); - scale_stream >> event.scale; + scale_stream >> scale; if (scale_stream.fail()) { - event.scale = 1; + scale = 1; } std::ifstream unit_stream(event_path.string() + ".unit"); - unit_stream >> event.unit; + unit_stream >> unit; if (scale_stream.fail()) { - event.unit = "#"; + unit = "#"; } - if (!event_is_openable(event)) + EventDescription event(ev_desc, static_cast(type), config, config1, cpus, scale, + unit); + if (!event.is_valid()) { throw EventProvider::InvalidEvent( "Event can not be opened in process- or system-monitoring-mode"); @@ -607,18 +524,16 @@ const EventDescription& EventProvider::cache_event(const std::string& name) { if (regex_match(name, raw_regex)) { - return event_map_.emplace(name, DescriptionCache(raw_read_event(name))) - .first->second.description; + return event_map_.emplace(name, raw_read_event(name)).first->second; } else { - return event_map_.emplace(name, DescriptionCache(sysfs_read_event(name))) - .first->second.description; + return event_map_.emplace(name, sysfs_read_event(name)).first->second; } } catch (const InvalidEvent& e) { - event_map_.emplace(name, DescriptionCache::make_invalid()); + event_map_.emplace(name, EventDescription()); throw e; } } @@ -631,7 +546,7 @@ const EventDescription& EventProvider::get_event_by_name(const std::string& name { if (event_it->second.is_valid()) { - return event_it->second.description; + return event_it->second; } else { @@ -678,7 +593,7 @@ std::vector EventProvider::get_predefined_events() { if (event.second.is_valid()) { - events.push_back(event.second.description); + events.push_back(event.second); } } diff --git a/src/perf/util.cpp b/src/perf/util.cpp index 3f3ea06f..76e955dd 100644 --- a/src/perf/util.cpp +++ b/src/perf/util.cpp @@ -112,31 +112,5 @@ int perf_try_event_open(struct perf_event_attr* perf_attr, ExecutionScope scope, return fd; } -int perf_event_description_open(ExecutionScope scope, const EventDescription& desc, int group_fd) -{ - struct perf_event_attr perf_attr; - memset(&perf_attr, 0, sizeof(perf_attr)); - perf_attr.size = sizeof(perf_attr); - perf_attr.sample_period = 0; - perf_attr.type = desc.type; - perf_attr.config = desc.config; - perf_attr.config1 = desc.config1; - perf_attr.exclude_kernel = config().exclude_kernel; - // Needed when scaling multiplexed events, and recognize activation phases - perf_attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; - -#ifndef USE_HW_BREAKPOINT_COMPAT - perf_attr.use_clockid = config().use_clockid; - perf_attr.clockid = config().clockid; -#endif - - int fd = perf_try_event_open(&perf_attr, scope, group_fd, 0, config().cgroup_fd); - if (fd < 0) - { - Log::error() << "perf_event_open for counter failed"; - throw_errno(); - } - return fd; -} } // namespace perf } // namespace lo2s From dc2d7bf79058641ed15a670e8bcb96789b7f0be2 Mon Sep 17 00:00:00 2001 From: Christian von Elm Date: Thu, 27 Apr 2023 13:19:38 +0200 Subject: [PATCH 2/2] Rebase onto master --- include/lo2s/perf/event_description.hpp | 2 +- include/lo2s/perf/sample/reader.hpp | 2 +- src/perf/counter/group/reader.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/lo2s/perf/event_description.hpp b/include/lo2s/perf/event_description.hpp index 33e5320c..72730fb2 100644 --- a/include/lo2s/perf/event_description.hpp +++ b/include/lo2s/perf/event_description.hpp @@ -197,7 +197,7 @@ struct EventDescription // Needed when scaling multiplexed events, and recognize activation phases perf_attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; -#if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID) +#ifndef USE_HW_BREAKPOINT_COMPAT perf_attr.use_clockid = config().use_clockid; perf_attr.clockid = config().clockid; #endif diff --git a/include/lo2s/perf/sample/reader.hpp b/include/lo2s/perf/sample/reader.hpp index 6b5b5271..5bc1e5cc 100644 --- a/include/lo2s/perf/sample/reader.hpp +++ b/include/lo2s/perf/sample/reader.hpp @@ -100,7 +100,7 @@ class Reader : public EventReader perf_attr.mmap = 1; perf_attr.disabled = 1; -#if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID) +#ifndef USE_HW_BREAKPOINT_COMPAT perf_attr.use_clockid = config().use_clockid; perf_attr.clockid = config().clockid; #endif diff --git a/src/perf/counter/group/reader.cpp b/src/perf/counter/group/reader.cpp index 43a00315..7f20cf96 100644 --- a/src/perf/counter/group/reader.cpp +++ b/src/perf/counter/group/reader.cpp @@ -57,7 +57,7 @@ Reader::Reader(ExecutionScope scope, bool enable_on_exec) leader_attr.disabled = 1; -#if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID) +#ifndef USE_HW_BREAKPOINT_COMPAT leader_attr.use_clockid = config().use_clockid; leader_attr.clockid = config().clockid; #endif