diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp index f6e091bdff9ae..1dab8809d3028 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp @@ -107,21 +107,18 @@ StringRef PerfEvent::getPfmEventString() const { return FullQualifiedEventString; } -CounterGroup::CounterGroup(PerfEvent &&E, pid_t ProcessID) - : Event(std::move(E)) { +ConfiguredEvent::ConfiguredEvent(PerfEvent &&EventToConfigure) + : Event(std::move(EventToConfigure)) { assert(Event.valid()); - IsDummyEvent = Event.name() == PerfEvent::DummyEventString; - if (!IsDummyEvent) - initRealEvent(E, ProcessID); } #ifdef HAVE_LIBPFM -void CounterGroup::initRealEvent(const PerfEvent &E, pid_t ProcessID) { - const int Cpu = -1; // measure any processor. - const int GroupFd = -1; // no grouping of counters. +void ConfiguredEvent::initRealEvent(const pid_t ProcessID) { + const int CPU = -1; + const int GroupFD = -1; const uint32_t Flags = 0; perf_event_attr AttrCopy = *Event.attribute(); - FileDescriptor = perf_event_open(&AttrCopy, ProcessID, Cpu, GroupFd, Flags); + FileDescriptor = perf_event_open(&AttrCopy, ProcessID, CPU, GroupFD, Flags); if (FileDescriptor == -1) { errs() << "Unable to open event. ERRNO: " << strerror(errno) << ". Make sure your kernel allows user " @@ -134,44 +131,67 @@ void CounterGroup::initRealEvent(const PerfEvent &E, pid_t ProcessID) { assert(FileDescriptor != -1 && "Unable to open event"); } -CounterGroup::~CounterGroup() { +Expected> +ConfiguredEvent::readOrError(StringRef /*unused*/) const { + int64_t Count = 0; + ssize_t ReadSize = ::read(FileDescriptor, &Count, sizeof(Count)); + + if (ReadSize != sizeof(Count)) + return llvm::make_error("Failed to read event counter", + llvm::errc::io_error); + + SmallVector Result; + Result.push_back(Count); + return Result; +} + +ConfiguredEvent::~ConfiguredEvent() { close(FileDescriptor); } +#else +void ConfiguredEvent::initRealEvent(pid_t ProcessID) {} + +Expected> +ConfiguredEvent::readOrError(StringRef /*unused*/) const { + return make_error("Not implemented", + errc::function_not_supported); +} + +ConfiguredEvent::~ConfiguredEvent() = default; +#endif // HAVE_LIBPFM + +CounterGroup::CounterGroup(PerfEvent &&E, pid_t ProcessID) + : EventCounter(std::move(E)) { + IsDummyEvent = EventCounter.isDummyEvent(); if (!IsDummyEvent) - close(FileDescriptor); + initRealEvent(ProcessID); +} + +#ifdef HAVE_LIBPFM +void CounterGroup::initRealEvent(pid_t ProcessID) { + EventCounter.initRealEvent(ProcessID); } void CounterGroup::start() { if (!IsDummyEvent) - ioctl(FileDescriptor, PERF_EVENT_IOC_RESET, 0); + ioctl(getFileDescriptor(), PERF_EVENT_IOC_RESET, 0); } void CounterGroup::stop() { if (!IsDummyEvent) - ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0); + ioctl(getFileDescriptor(), PERF_EVENT_IOC_DISABLE, 0); } llvm::Expected> -CounterGroup::readOrError(StringRef /*unused*/) const { - int64_t Count = 0; - if (!IsDummyEvent) { - ssize_t ReadSize = ::read(FileDescriptor, &Count, sizeof(Count)); - if (ReadSize != sizeof(Count)) - return llvm::make_error("Failed to read event counter", - llvm::errc::io_error); - } else { - Count = 42; - } - - llvm::SmallVector Result; - Result.push_back(Count); - return Result; +CounterGroup::readOrError(StringRef FunctionBytes) const { + if (!IsDummyEvent) + return EventCounter.readOrError(FunctionBytes); + else + return SmallVector(1, 42); } int CounterGroup::numValues() const { return 1; } #else -void CounterGroup::initRealEvent(const PerfEvent &, pid_t ProcessID) {} - -CounterGroup::~CounterGroup() = default; +void CounterGroup::initRealEvent(pid_t ProcessID) {} void CounterGroup::start() {} diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h index daf2fbd0e3abc..e9b73da383628 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h @@ -77,6 +77,29 @@ class PerfEvent { void initRealEvent(StringRef PfmEventString); }; +// Represents a single event that has been configured in the Linux perf +// subsystem. +class ConfiguredEvent { +public: + ConfiguredEvent(PerfEvent &&EventToConfigure); + + void initRealEvent(const pid_t ProcessID); + Expected> readOrError(StringRef FunctionBytes) const; + int getFileDescriptor() const { return FileDescriptor; } + bool isDummyEvent() const { + return Event.name() == PerfEvent::DummyEventString; + } + + ConfiguredEvent(const ConfiguredEvent &) = delete; + ConfiguredEvent(ConfiguredEvent &&other) = default; + + ~ConfiguredEvent(); + +private: + PerfEvent Event; + int FileDescriptor = -1; +}; + // Consists of a counter measuring a specific event and associated validation // counters measuring execution conditions. All counters in a group are part // of a single event group and are thus scheduled on and off the CPU as a single @@ -89,7 +112,7 @@ class CounterGroup { CounterGroup(const CounterGroup &) = delete; CounterGroup(CounterGroup &&other) = default; - virtual ~CounterGroup(); + virtual ~CounterGroup() = default; /// Starts the measurement of the event. virtual void start(); @@ -108,15 +131,14 @@ class CounterGroup { virtual int numValues() const; - int getFileDescriptor() const { return FileDescriptor; } + int getFileDescriptor() const { return EventCounter.getFileDescriptor(); } protected: - PerfEvent Event; - int FileDescriptor = -1; + ConfiguredEvent EventCounter; bool IsDummyEvent; private: - void initRealEvent(const PerfEvent &E, pid_t ProcessID); + void initRealEvent(pid_t ProcessID); }; } // namespace pfm diff --git a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp index 55ca2d7146ceb..96fb0f085a1ee 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp @@ -143,7 +143,7 @@ X86LbrPerfEvent::X86LbrPerfEvent(unsigned SamplingPeriod) { X86LbrCounter::X86LbrCounter(pfm::PerfEvent &&NewEvent) : CounterGroup(std::move(NewEvent)) { MMappedBuffer = mmap(nullptr, kMappedBufferSize, PROT_READ | PROT_WRITE, - MAP_SHARED, FileDescriptor, 0); + MAP_SHARED, getFileDescriptor(), 0); if (MMappedBuffer == MAP_FAILED) llvm::errs() << "Failed to mmap buffer."; } @@ -154,7 +154,7 @@ X86LbrCounter::~X86LbrCounter() { } void X86LbrCounter::start() { - ioctl(FileDescriptor, PERF_EVENT_IOC_REFRESH, 1024 /* kMaxPollsPerFd */); + ioctl(getFileDescriptor(), PERF_EVENT_IOC_REFRESH, 1024 /* kMaxPollsPerFd */); } llvm::Error X86LbrCounter::checkLbrSupport() { @@ -197,7 +197,7 @@ llvm::Error X86LbrCounter::checkLbrSupport() { llvm::Expected> X86LbrCounter::readOrError(StringRef FunctionBytes) const { // Disable the event before reading - ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0); + ioctl(getFileDescriptor(), PERF_EVENT_IOC_DISABLE, 0); // Find the boundary of the function so that we could filter the LBRs // to keep only the relevant records. @@ -223,7 +223,7 @@ X86LbrCounter::doReadCounter(const void *From, const void *To) const { int PollResult = 0; while (PollResult <= 0) { - PollResult = pollLbrPerfEvent(FileDescriptor); + PollResult = pollLbrPerfEvent(getFileDescriptor()); if (PollResult > 0) break; if (PollResult == -1)