1- // https://github.com/WojciechMula/toys/blob/master/000helpers/linux-perf-events.h
21#pragma once
32#ifdef __linux__
43
54#include < asm/unistd.h> // for __NR_perf_event_open
65#include < linux/perf_event.h> // for perf event constants
76#include < sys/ioctl.h> // for ioctl
87#include < unistd.h> // for syscall
9- # include < iostream >
8+
109#include < cerrno> // for errno
1110#include < cstring> // for memset
1211#include < stdexcept>
1312
13+ #include < iostream>
1414#include < vector>
1515
1616template <int TYPE = PERF_TYPE_HARDWARE> class LinuxEvents {
17- int group ;
17+ int fd ;
1818 bool working;
19- perf_event_attr attribs;
20- int num_events;
21- std::vector<uint64_t > temp_result_vec;
22- std::vector<int > fds ;
19+ perf_event_attr attribs{} ;
20+ size_t num_events{} ;
21+ std::vector<uint64_t > temp_result_vec{} ;
22+ std::vector<uint64_t > ids{} ;
2323
2424public:
25- explicit LinuxEvents (std::vector<int > config_vec) : group(- 1 ), working(true ) {
25+ explicit LinuxEvents (std::vector<int > config_vec) : fd( 0 ), working(true ) {
2626 memset (&attribs, 0 , sizeof (attribs));
2727 attribs.type = TYPE;
2828 attribs.size = sizeof (attribs);
@@ -36,58 +36,69 @@ template <int TYPE = PERF_TYPE_HARDWARE> class LinuxEvents {
3636 const int cpu = -1 ; // all CPUs
3737 const unsigned long flags = 0 ;
3838
39+ int group = -1 ; // no group
3940 num_events = config_vec.size ();
41+ ids.resize (config_vec.size ());
42+ uint32_t i = 0 ;
4043 for (auto config : config_vec) {
4144 attribs.config = config;
42- int fd = syscall (__NR_perf_event_open, &attribs, pid, cpu, group, flags);
43- if (fd == -1 ) {
45+ int _fd = static_cast < int >( syscall (__NR_perf_event_open, &attribs, pid, cpu, group, flags) );
46+ if (_fd == -1 ) {
4447 report_error (" perf_event_open" );
4548 }
46-
47- fds.push_back (fd);
49+ ioctl (_fd, PERF_EVENT_IOC_ID, &ids[i++]);
4850 if (group == -1 ) {
49- group = fd;
51+ group = _fd;
52+ fd = _fd;
5053 }
5154 }
5255
5356 temp_result_vec.resize (num_events * 2 + 1 );
5457 }
5558
56- ~LinuxEvents () {
57- for (auto fd : fds) {
58- close (fd);
59- }
60- }
59+ ~LinuxEvents () { if (fd != -1 ) { close (fd); } }
6160
6261 inline void start () {
63- if (ioctl (group, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1 ) {
64- report_error (" ioctl(PERF_EVENT_IOC_RESET)" );
65- }
62+ if (fd != -1 ) {
63+ if (ioctl (fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1 ) {
64+ report_error (" ioctl(PERF_EVENT_IOC_RESET)" );
65+ }
6666
67- if (ioctl (group, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1 ) {
68- report_error (" ioctl(PERF_EVENT_IOC_ENABLE)" );
67+ if (ioctl (fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1 ) {
68+ report_error (" ioctl(PERF_EVENT_IOC_ENABLE)" );
69+ }
6970 }
7071 }
7172
7273 inline void end (std::vector<unsigned long long > &results) {
73- if (ioctl (group, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1 ) {
74- report_error (" ioctl(PERF_EVENT_IOC_DISABLE)" );
75- }
74+ if (fd != -1 ) {
75+ if (ioctl (fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1 ) {
76+ report_error (" ioctl(PERF_EVENT_IOC_DISABLE)" );
77+ }
7678
77- if (read (group, &temp_result_vec[0 ], temp_result_vec.size () * 8 ) == -1 ) {
78- report_error (" read" );
79+ if (read (fd, temp_result_vec.data (), temp_result_vec.size () * 8 ) == -1 ) {
80+ report_error (" read" );
81+ }
7982 }
8083 // our actual results are in slots 1,3,5, ... of this structure
81- // we really should be checking our ids obtained earlier to be safe
8284 for (uint32_t i = 1 ; i < temp_result_vec.size (); i += 2 ) {
8385 results[i / 2 ] = temp_result_vec[i];
8486 }
87+ for (uint32_t i = 2 ; i < temp_result_vec.size (); i += 2 ) {
88+ if (ids[i/2 -1 ] != temp_result_vec[i]) {
89+ report_error (" event mismatch" );
90+ }
91+ }
92+
93+
94+ }
95+
96+ bool is_working () {
97+ return working;
8598 }
8699
87100private:
88- void report_error (const std::string &context) {
89- if (working)
90- std::cerr << (context + " : " + std::string (strerror (errno))) << std::endl;
101+ void report_error (const std::string &) {
91102 working = false ;
92103 }
93104};
0 commit comments