Skip to content

Commit 34a97e8

Browse files
tboschrocallahan
authored andcommitted
Detect when the kernel multiplexed hw counters.
If this happens, the counter values are incorrect. This happens when e.g. multiple rr instances run in parallel on the same machine.
1 parent 4452c7f commit 34a97e8

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

src/PerfCounters.cc

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,25 @@ static const uint64_t IN_TX = 1ULL << 32;
260260
static const uint64_t IN_TXCP = 1ULL << 33;
261261

262262
static int64_t read_counter(ScopedFd& fd) {
263-
int64_t val;
264-
ssize_t nread = read(fd, &val, sizeof(val));
265-
DEBUG_ASSERT(nread == sizeof(val));
266-
return val;
263+
struct read_format {
264+
int64_t value;
265+
int64_t time_enabled;
266+
int64_t time_running;
267+
} data;
268+
errno = 0;
269+
ssize_t nread = read(fd, &data, sizeof(data));
270+
if (nread < 0) {
271+
FATAL() << "Failed to read counter";
272+
}
273+
DEBUG_ASSERT(nread == sizeof(data));
274+
if (data.time_enabled != data.time_running) {
275+
FATAL()
276+
<< "\nCounter was multiplexed to a ratio of "
277+
<< (data.time_running * 1.0 / data.time_enabled)
278+
<< ".\nCheck that other software is not using performance counters on\n"
279+
"this CPU.";
280+
}
281+
return data.value;
267282
}
268283

269284
static ScopedFd start_counter(pid_t tid, int group_fd,
@@ -272,11 +287,14 @@ static ScopedFd start_counter(pid_t tid, int group_fd,
272287
if (disabled_txcp) {
273288
*disabled_txcp = false;
274289
}
290+
struct perf_event_attr tmp_attr = *attr;
291+
// Needed to detect when the kernel is multiplexing counters.
292+
tmp_attr.read_format =
293+
PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
275294
int fd = syscall(__NR_perf_event_open, attr, tid, -1, group_fd, 0);
276295
if (0 > fd && errno == EINVAL && attr->type == PERF_TYPE_RAW &&
277296
(attr->config & IN_TXCP)) {
278297
// The kernel might not support IN_TXCP, so try again without it.
279-
struct perf_event_attr tmp_attr = *attr;
280298
tmp_attr.config &= ~IN_TXCP;
281299
fd = syscall(__NR_perf_event_open, &tmp_attr, tid, -1, group_fd, 0);
282300
if (fd >= 0) {

0 commit comments

Comments
 (0)